Merge branches 'for-3.11/wacom-fixed' and 'for-3.11/wiimote' into for-linus
authorJiri Kosina <jkosina@suse.cz>
Thu, 4 Jul 2013 13:05:02 +0000 (15:05 +0200)
committerJiri Kosina <jkosina@suse.cz>
Thu, 4 Jul 2013 13:05:02 +0000 (15:05 +0200)
1557 files changed:
Documentation/bcache.txt
Documentation/devices.txt
Documentation/devicetree/bindings/net/macb.txt
Documentation/devicetree/bindings/rtc/atmel,at91rm9200-rtc.txt
Documentation/devicetree/bindings/video/exynos_hdmi.txt [moved from Documentation/devicetree/bindings/drm/exynos/hdmi.txt with 100% similarity]
Documentation/devicetree/bindings/video/exynos_hdmiddc.txt [moved from Documentation/devicetree/bindings/drm/exynos/hdmiddc.txt with 100% similarity]
Documentation/devicetree/bindings/video/exynos_hdmiphy.txt [moved from Documentation/devicetree/bindings/drm/exynos/hdmiphy.txt with 100% similarity]
Documentation/devicetree/bindings/video/exynos_mixer.txt [moved from Documentation/devicetree/bindings/drm/exynos/mixer.txt with 100% similarity]
Documentation/devicetree/bindings/video/simple-framebuffer.txt [new file with mode: 0644]
Documentation/devicetree/usage-model.txt
Documentation/dmatest.txt
Documentation/filesystems/xfs.txt
Documentation/kernel-parameters.txt
Documentation/kernel-per-CPU-kthreads.txt [new file with mode: 0644]
Documentation/m68k/kernel-options.txt
Documentation/power/devices.txt
Documentation/power/interface.txt
Documentation/power/notifiers.txt
Documentation/power/states.txt
Documentation/powerpc/transactional_memory.txt
Documentation/rapidio/rapidio.txt
Documentation/rapidio/sysfs.txt
MAINTAINERS
Makefile
arch/Kconfig
arch/arc/boot/dts/abilis_tb100_dvk.dts
arch/arc/boot/dts/abilis_tb101_dvk.dts
arch/arc/boot/dts/abilis_tb10x.dtsi
arch/arc/include/asm/cacheflush.h
arch/arc/include/asm/page.h
arch/arc/include/asm/pgtable.h
arch/arc/include/asm/tlb.h
arch/arc/mm/cache_arc700.c
arch/arc/mm/tlb.c
arch/arc/mm/tlbex.S
arch/arc/plat-tb10x/tb10x.c
arch/arm/Kconfig
arch/arm/Makefile
arch/arm/boot/compressed/Makefile
arch/arm/boot/compressed/debug.S
arch/arm/boot/compressed/head-sa1100.S
arch/arm/boot/compressed/head-shark.S
arch/arm/boot/compressed/head.S
arch/arm/boot/dts/Makefile
arch/arm/boot/dts/armada-370-xp.dtsi
arch/arm/boot/dts/armada-370.dtsi
arch/arm/boot/dts/armada-xp-gp.dts
arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts
arch/arm/boot/dts/armada-xp.dtsi
arch/arm/boot/dts/at91sam9260.dtsi
arch/arm/boot/dts/at91sam9n12.dtsi
arch/arm/boot/dts/at91sam9x25ek.dts
arch/arm/boot/dts/bcm2835.dtsi
arch/arm/boot/dts/exynos5250.dtsi
arch/arm/boot/dts/imx25.dtsi
arch/arm/boot/dts/imx27.dtsi
arch/arm/boot/dts/imx51.dtsi
arch/arm/boot/dts/imx53.dtsi
arch/arm/boot/dts/omap3.dtsi
arch/arm/boot/dts/sama5d3.dtsi
arch/arm/boot/dts/sama5d3xcm.dtsi
arch/arm/boot/dts/ste-nomadik-s8815.dts
arch/arm/boot/dts/sun4i-a10-mini-xplus.dts
arch/arm/common/mcpm_platsmp.c
arch/arm/configs/exynos_defconfig
arch/arm/configs/omap1_defconfig
arch/arm/configs/omap2plus_defconfig
arch/arm/configs/tegra_defconfig
arch/arm/crypto/sha1-armv4-large.S
arch/arm/include/asm/cmpxchg.h
arch/arm/include/asm/percpu.h
arch/arm/include/asm/tlb.h
arch/arm/include/debug/ux500.S
arch/arm/kernel/process.c
arch/arm/kernel/smp.c
arch/arm/kernel/topology.c
arch/arm/kvm/arm.c
arch/arm/kvm/mmu.c
arch/arm/mach-at91/at91rm9200_time.c
arch/arm/mach-at91/at91sam9n12.c
arch/arm/mach-at91/include/mach/at91_pmc.h
arch/arm/mach-exynos/Kconfig
arch/arm/mach-exynos/common.c
arch/arm/mach-exynos/common.h
arch/arm/mach-exynos/include/mach/pm-core.h
arch/arm/mach-exynos/mach-universal_c210.c
arch/arm/mach-imx/clk-imx6q.c
arch/arm/mach-imx/headsmp.S
arch/arm/mach-imx/platsmp.c
arch/arm/mach-kirkwood/board-ts219.c
arch/arm/mach-kirkwood/common.c
arch/arm/mach-kirkwood/ts219-setup.c
arch/arm/mach-mvebu/Kconfig
arch/arm/mach-mvebu/armada-370-xp.c
arch/arm/mach-mvebu/coherency_ll.S
arch/arm/mach-omap1/dma.c
arch/arm/mach-omap2/cclock33xx_data.c
arch/arm/mach-omap2/omap_hwmod.c
arch/arm/mach-omap2/omap_hwmod.h
arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
arch/arm/mach-omap2/omap_hwmod_33xx_data.c
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
arch/arm/mach-omap2/omap_hwmod_44xx_data.c
arch/arm/mach-omap2/serial.c
arch/arm/mach-orion5x/common.c
arch/arm/mach-shmobile/board-marzen.c
arch/arm/mach-shmobile/setup-sh73a0.c
arch/arm/mach-sunxi/Kconfig
arch/arm/mach-tegra/tegra2_emc.c
arch/arm/mach-ux500/Kconfig
arch/arm/mach-ux500/board-mop500-regulators.c
arch/arm/mach-ux500/board-mop500.c
arch/arm/mach-ux500/cpu-db8500.c
arch/arm/mach-ux500/cpuidle.c
arch/arm/mach-ux500/setup.h
arch/arm/mach-vt8500/vt8500.c
arch/arm/plat-orion/common.c
arch/arm/plat-orion/include/plat/common.h
arch/arm/plat-samsung/adc.c
arch/arm/plat-samsung/devs.c
arch/arm/plat-samsung/include/plat/uncompress.h
arch/arm/vfp/entry.S
arch/arm/xen/enlighten.c
arch/arm64/Kconfig
arch/arm64/include/asm/assembler.h
arch/arm64/include/asm/unistd32.h
arch/arm64/kernel/arm64ksyms.c
arch/arm64/kernel/debug-monitors.c
arch/arm64/kernel/early_printk.c
arch/arm64/kernel/entry.S
arch/arm64/kernel/setup.c
arch/arm64/kernel/sys32.S
arch/arm64/kernel/traps.c
arch/arm64/mm/cache.S
arch/arm64/mm/fault.c
arch/arm64/mm/proc.S
arch/avr32/Kconfig
arch/avr32/include/asm/Kbuild
arch/avr32/include/asm/numnodes.h [deleted file]
arch/avr32/include/asm/param.h [deleted file]
arch/avr32/include/uapi/asm/Kbuild
arch/avr32/include/uapi/asm/param.h [deleted file]
arch/avr32/kernel/module.c
arch/ia64/include/asm/tlb.h
arch/m68k/configs/amiga_defconfig
arch/m68k/configs/apollo_defconfig
arch/m68k/configs/atari_defconfig
arch/m68k/configs/bvme6000_defconfig
arch/m68k/configs/hp300_defconfig
arch/m68k/configs/mac_defconfig
arch/m68k/configs/multi_defconfig
arch/m68k/configs/mvme147_defconfig
arch/m68k/configs/mvme16x_defconfig
arch/m68k/configs/q40_defconfig
arch/m68k/configs/sun3_defconfig
arch/m68k/configs/sun3x_defconfig
arch/m68k/include/asm/Kbuild
arch/m68k/include/asm/commproc.h
arch/m68k/include/asm/futex.h [new file with mode: 0644]
arch/m68k/include/asm/gpio.h
arch/m68k/kernel/head.S
arch/microblaze/include/asm/cacheflush.h
arch/microblaze/include/asm/futex.h
arch/microblaze/include/asm/io.h
arch/microblaze/include/asm/uaccess.h
arch/microblaze/kernel/cpu/cache.c
arch/mips/alchemy/board-gpr.c
arch/mips/alchemy/common/time.c
arch/mips/ath79/setup.c
arch/mips/cavium-octeon/setup.c
arch/mips/cobalt/reset.c
arch/mips/configs/db1000_defconfig
arch/mips/configs/db1235_defconfig
arch/mips/configs/lemote2f_defconfig
arch/mips/include/asm/clock.h
arch/mips/include/asm/idle.h [new file with mode: 0644]
arch/mips/include/asm/io.h
arch/mips/include/asm/kvm.h [deleted file]
arch/mips/include/asm/kvm_host.h
arch/mips/include/asm/mmu_context.h
arch/mips/include/asm/page.h
arch/mips/include/asm/processor.h
arch/mips/include/asm/ptrace.h
arch/mips/include/uapi/asm/kvm.h [new file with mode: 0644]
arch/mips/include/uapi/asm/ptrace.h
arch/mips/include/uapi/asm/unistd.h
arch/mips/kernel/Makefile
arch/mips/kernel/binfmt_elfn32.c
arch/mips/kernel/binfmt_elfo32.c
arch/mips/kernel/cpu-probe.c
arch/mips/kernel/crash_dump.c
arch/mips/kernel/ftrace.c
arch/mips/kernel/genex.S
arch/mips/kernel/idle.c [new file with mode: 0644]
arch/mips/kernel/kprobes.c
arch/mips/kernel/linux32.c
arch/mips/kernel/proc.c
arch/mips/kernel/process.c
arch/mips/kernel/rtlx.c
arch/mips/kernel/scall64-64.S
arch/mips/kernel/scall64-o32.S
arch/mips/kernel/smp.c
arch/mips/kernel/smtc.c
arch/mips/kernel/traps.c
arch/mips/kvm/kvm_mips.c
arch/mips/kvm/kvm_mips_emul.c
arch/mips/kvm/kvm_tlb.c
arch/mips/kvm/kvm_trap_emul.c
arch/mips/lantiq/xway/gptu.c
arch/mips/lib/dump_tlb.c
arch/mips/lib/r3k_dump_tlb.c
arch/mips/loongson/common/reset.c
arch/mips/loongson1/common/reset.c
arch/mips/mm/tlb-r3k.c
arch/mips/mm/tlb-r4k.c
arch/mips/mm/tlb-r8k.c
arch/mips/mm/tlbex.c
arch/mips/netlogic/xlp/setup.c
arch/mips/netlogic/xlr/setup.c
arch/mips/pmcs-msp71xx/msp_prom.c
arch/mips/pmcs-msp71xx/msp_setup.c
arch/mips/ralink/dts/rt3050.dtsi
arch/mips/ralink/dts/rt3052_eval.dts
arch/mips/ralink/of.c
arch/mips/txx9/generic/setup.c
arch/mips/vr41xx/common/pmu.c
arch/mips/wrppmc/reset.c
arch/mn10300/include/asm/pci.h
arch/mn10300/kernel/entry.S
arch/mn10300/unit-asb2305/pci.c
arch/parisc/Kconfig
arch/parisc/Makefile
arch/parisc/include/asm/assembly.h
arch/parisc/include/asm/hardirq.h
arch/parisc/include/asm/mmzone.h
arch/parisc/include/asm/processor.h
arch/parisc/kernel/drivers.c
arch/parisc/kernel/entry.S
arch/parisc/kernel/hardware.c
arch/parisc/kernel/irq.c
arch/parisc/kernel/pacache.S
arch/parisc/kernel/setup.c
arch/parisc/kernel/sys_parisc32.c
arch/parisc/kernel/traps.c
arch/parisc/kernel/unaligned.c
arch/parisc/mm/init.c
arch/powerpc/Kconfig.debug
arch/powerpc/configs/ps3_defconfig
arch/powerpc/include/asm/context_tracking.h [new file with mode: 0644]
arch/powerpc/include/asm/cputable.h
arch/powerpc/include/asm/firmware.h
arch/powerpc/include/asm/hvcall.h
arch/powerpc/include/asm/hw_irq.h
arch/powerpc/include/asm/kvm_asm.h
arch/powerpc/include/asm/opal.h
arch/powerpc/include/asm/pci-bridge.h
arch/powerpc/include/asm/pgalloc-64.h
arch/powerpc/include/asm/ppc_asm.h
arch/powerpc/include/asm/processor.h
arch/powerpc/include/asm/pte-hash64-64k.h
arch/powerpc/include/asm/reg.h
arch/powerpc/include/asm/rtas.h
arch/powerpc/include/asm/signal.h
arch/powerpc/include/asm/thread_info.h
arch/powerpc/include/asm/tm.h
arch/powerpc/include/asm/udbg.h
arch/powerpc/include/uapi/asm/Kbuild
arch/powerpc/include/uapi/asm/tm.h [new file with mode: 0644]
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kernel/cpu_setup_power.S
arch/powerpc/kernel/cputable.c
arch/powerpc/kernel/entry_32.S
arch/powerpc/kernel/entry_64.S
arch/powerpc/kernel/exceptions-64e.S
arch/powerpc/kernel/exceptions-64s.S
arch/powerpc/kernel/machine_kexec_64.c
arch/powerpc/kernel/misc_32.S
arch/powerpc/kernel/misc_64.S
arch/powerpc/kernel/pci-common.c
arch/powerpc/kernel/pci_64.c
arch/powerpc/kernel/pci_dn.c
arch/powerpc/kernel/ppc_ksyms.c
arch/powerpc/kernel/process.c
arch/powerpc/kernel/ptrace.c
arch/powerpc/kernel/rtas.c
arch/powerpc/kernel/rtas_flash.c
arch/powerpc/kernel/signal.c
arch/powerpc/kernel/signal.h
arch/powerpc/kernel/signal_32.c
arch/powerpc/kernel/signal_64.c
arch/powerpc/kernel/sys_ppc32.c
arch/powerpc/kernel/traps.c
arch/powerpc/kernel/udbg.c
arch/powerpc/kvm/44x_tlb.c
arch/powerpc/kvm/book3s_hv.c
arch/powerpc/kvm/book3s_pr_papr.c
arch/powerpc/kvm/book3s_xics.c
arch/powerpc/kvm/booke.c
arch/powerpc/kvm/e500_mmu.c
arch/powerpc/kvm/e500mc.c
arch/powerpc/lib/copypage_power7.S
arch/powerpc/lib/copyuser_power7.S
arch/powerpc/mm/fault.c
arch/powerpc/mm/hash_native_64.c
arch/powerpc/mm/hash_utils_64.c
arch/powerpc/mm/init_64.c
arch/powerpc/perf/core-book3s.c
arch/powerpc/platforms/Kconfig
arch/powerpc/platforms/powernv/Kconfig
arch/powerpc/platforms/powernv/opal.c
arch/powerpc/platforms/powernv/pci-ioda.c
arch/powerpc/platforms/powernv/pci.c
arch/powerpc/platforms/powernv/pci.h
arch/powerpc/platforms/powernv/powernv.h
arch/powerpc/platforms/powernv/setup.c
arch/powerpc/platforms/powernv/smp.c
arch/powerpc/platforms/pseries/Kconfig
arch/powerpc/platforms/pseries/eeh_pseries.c
arch/powerpc/platforms/pseries/msi.c
arch/powerpc/platforms/pseries/suspend.c
arch/powerpc/platforms/wsp/ics.c
arch/powerpc/sysdev/Makefile
arch/powerpc/sysdev/ehv_pic.c
arch/powerpc/sysdev/mpic.c
arch/powerpc/sysdev/udbg_memcons.c [new file with mode: 0644]
arch/powerpc/sysdev/xics/ics-opal.c
arch/s390/Kconfig
arch/s390/appldata/appldata_base.c
arch/s390/include/asm/dma-mapping.h
arch/s390/include/asm/ftrace.h
arch/s390/include/asm/io.h
arch/s390/include/asm/page.h
arch/s390/include/asm/pgtable.h
arch/s390/kernel/compat_wrapper.S
arch/s390/kernel/dis.c
arch/s390/kernel/ftrace.c
arch/s390/kernel/mcount.S
arch/s390/kernel/mcount64.S
arch/s390/kernel/smp.c
arch/s390/kernel/syscalls.S
arch/s390/mm/pgtable.c
arch/score/mm/init.c
arch/sparc/kernel/sys32.S
arch/sparc/kernel/systbls_64.S
arch/unicore32/kernel/sys.c
arch/x86/Kconfig
arch/x86/crypto/crc32-pclmul_asm.S
arch/x86/crypto/sha256-avx-asm.S
arch/x86/crypto/sha256-ssse3-asm.S
arch/x86/ia32/sys_ia32.c
arch/x86/include/asm/inst.h
arch/x86/include/asm/sys_ia32.h
arch/x86/include/asm/syscalls.h
arch/x86/include/uapi/asm/msr-index.h
arch/x86/kernel/head64.c
arch/x86/kernel/head_64.S
arch/x86/kernel/i387.c
arch/x86/kernel/microcode_intel_early.c
arch/x86/kernel/process.c
arch/x86/kernel/vm86_32.c
arch/x86/kvm/emulate.c
arch/x86/kvm/lapic.c
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c
arch/x86/mm/init.c
arch/x86/pci/common.c
arch/x86/pci/mrst.c
arch/x86/pci/xen.c
arch/x86/platform/efi/efi.c
arch/x86/syscalls/syscall_32.tbl
arch/x86/xen/enlighten.c
arch/x86/xen/smp.c
arch/x86/xen/smp.h
arch/x86/xen/spinlock.c
block/blk-core.c
crypto/Kconfig
drivers/acpi/Makefile
drivers/acpi/ac.c
drivers/acpi/acpi_lpss.c
drivers/acpi/apei/cper.c
drivers/acpi/apei/ghes.c
drivers/acpi/csrt.c [deleted file]
drivers/acpi/device_pm.c
drivers/acpi/ec.c
drivers/acpi/internal.h
drivers/acpi/pci_root.c
drivers/acpi/processor_driver.c
drivers/acpi/processor_idle.c
drivers/acpi/scan.c
drivers/acpi/video.c
drivers/acpi/video_detect.c
drivers/ata/acard-ahci.c
drivers/ata/ahci.c
drivers/ata/ahci.h
drivers/ata/ata_piix.c
drivers/ata/libahci.c
drivers/ata/libata-core.c
drivers/ata/libata-eh.c
drivers/ata/libata-scsi.c
drivers/ata/libata-sff.c
drivers/ata/pata_ep93xx.c
drivers/ata/pdc_adma.c
drivers/ata/sata_promise.c
drivers/ata/sata_rcar.c
drivers/ata/sata_sil.c
drivers/ata/sata_sx4.c
drivers/ata/sata_via.c
drivers/base/bus.c
drivers/base/core.c
drivers/base/power/common.c
drivers/base/regmap/regcache-rbtree.c
drivers/base/regmap/regcache.c
drivers/base/regmap/regmap-debugfs.c
drivers/bcma/scan.c
drivers/block/brd.c
drivers/block/cciss.c
drivers/block/mtip32xx/mtip32xx.c
drivers/block/nvme-core.c
drivers/block/nvme-scsi.c
drivers/block/pktcdvd.c
drivers/block/rbd.c
drivers/block/xsysace.c
drivers/bluetooth/Kconfig
drivers/bluetooth/btmrvl_sdio.c
drivers/char/hw_random/mxc-rnga.c
drivers/char/hw_random/omap-rng.c
drivers/char/ipmi/ipmi_bt_sm.c
drivers/char/ipmi/ipmi_devintf.c
drivers/char/ipmi/ipmi_msghandler.c
drivers/char/ipmi/ipmi_si_intf.c
drivers/char/lp.c
drivers/char/random.c
drivers/char/ttyprintk.c
drivers/clk/clk-si5351.c
drivers/clk/clk-vt8500.c
drivers/clk/mxs/clk-imx28.c
drivers/clk/samsung/clk-exynos4.c
drivers/clk/tegra/clk-tegra20.c
drivers/clk/ux500/clk-sysctrl.c
drivers/clk/ux500/u8500_clk.c
drivers/clk/x86/clk-lpt.c
drivers/cpufreq/Kconfig
drivers/cpufreq/Kconfig.arm
drivers/cpufreq/Kconfig.x86
drivers/cpufreq/acpi-cpufreq.c
drivers/cpufreq/arm_big_little.c
drivers/cpufreq/arm_big_little.h
drivers/cpufreq/arm_big_little_dt.c
drivers/cpufreq/cpufreq-cpu0.c
drivers/cpufreq/cpufreq.c
drivers/cpufreq/cpufreq_governor.c
drivers/cpufreq/cpufreq_governor.h
drivers/cpufreq/cpufreq_ondemand.c
drivers/cpufreq/cpufreq_stats.c
drivers/cpufreq/intel_pstate.c
drivers/cpufreq/kirkwood-cpufreq.c
drivers/cpufreq/loongson2_cpufreq.c
drivers/crypto/caam/caamalg.c
drivers/crypto/nx/nx-aes-cbc.c
drivers/crypto/nx/nx-aes-ecb.c
drivers/crypto/nx/nx-aes-gcm.c
drivers/crypto/nx/nx-sha256.c
drivers/crypto/nx/nx-sha512.c
drivers/crypto/nx/nx.c
drivers/crypto/sahara.c
drivers/dma/acpi-dma.c
drivers/dma/dmatest.c
drivers/dma/ste_dma40.c
drivers/dma/tegra20-apb-dma.c
drivers/edac/amd64_edac_inj.c
drivers/firmware/efi/efivars.c
drivers/gpio/Kconfig
drivers/gpio/gpio-langwell.c
drivers/gpio/gpio-ml-ioh.c
drivers/gpio/gpio-mvebu.c
drivers/gpio/gpio-mxs.c
drivers/gpio/gpio-omap.c
drivers/gpio/gpio-pch.c
drivers/gpio/gpio-sch.c
drivers/gpio/gpio-tegra.c
drivers/gpio/gpio-viperboard.c
drivers/gpu/drm/drm_crtc.c
drivers/gpu/drm/drm_crtc_helper.c
drivers/gpu/drm/drm_drv.c
drivers/gpu/drm/drm_encoder_slave.c
drivers/gpu/drm/drm_irq.c
drivers/gpu/drm/drm_mm.c
drivers/gpu/drm/drm_modes.c
drivers/gpu/drm/exynos/exynos_drm_crtc.c
drivers/gpu/drm/exynos/exynos_drm_fbdev.c
drivers/gpu/drm/exynos/exynos_drm_fimc.c
drivers/gpu/drm/exynos/exynos_drm_fimd.c
drivers/gpu/drm/exynos/exynos_drm_g2d.c
drivers/gpu/drm/exynos/exynos_drm_gsc.c
drivers/gpu/drm/exynos/exynos_drm_hdmi.c
drivers/gpu/drm/exynos/exynos_drm_ipp.c
drivers/gpu/drm/exynos/exynos_drm_rotator.c
drivers/gpu/drm/exynos/exynos_drm_vidi.c
drivers/gpu/drm/exynos/exynos_hdmi.c
drivers/gpu/drm/exynos/exynos_mixer.c
drivers/gpu/drm/gma500/cdv_intel_display.c
drivers/gpu/drm/gma500/framebuffer.c
drivers/gpu/drm/gma500/psb_intel_display.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_gtt.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_ddi.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_fb.c
drivers/gpu/drm/i915/intel_i2c.c
drivers/gpu/drm/i915/intel_lvds.c
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/i915/intel_sdvo.c
drivers/gpu/drm/mgag200/mgag200_mode.c
drivers/gpu/drm/nouveau/core/engine/device/nvc0.c
drivers/gpu/drm/nouveau/core/engine/disp/dacnv50.c
drivers/gpu/drm/nouveau/core/engine/disp/hdminv84.c
drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c
drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c
drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c
drivers/gpu/drm/nouveau/core/include/core/class.h
drivers/gpu/drm/nouveau/core/subdev/bios/init.c
drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c
drivers/gpu/drm/nouveau/nouveau_display.c
drivers/gpu/drm/nouveau/nouveau_drm.c
drivers/gpu/drm/nouveau/nv50_display.c
drivers/gpu/drm/omapdrm/omap_drv.c
drivers/gpu/drm/qxl/Kconfig
drivers/gpu/drm/qxl/qxl_cmd.c
drivers/gpu/drm/qxl/qxl_display.c
drivers/gpu/drm/qxl/qxl_drv.h
drivers/gpu/drm/qxl/qxl_ioctl.c
drivers/gpu/drm/qxl/qxl_kms.c
drivers/gpu/drm/radeon/atombios_crtc.c
drivers/gpu/drm/radeon/atombios_encoders.c
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/evergreen_hdmi.c
drivers/gpu/drm/radeon/ni.c
drivers/gpu/drm/radeon/r100.c
drivers/gpu/drm/radeon/r300.c
drivers/gpu/drm/radeon/r300_cmdbuf.c
drivers/gpu/drm/radeon/r420.c
drivers/gpu/drm/radeon/r520.c
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/r600_hdmi.c
drivers/gpu/drm/radeon/r600d.h
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_asic.c
drivers/gpu/drm/radeon/radeon_asic.h
drivers/gpu/drm/radeon/radeon_bios.c
drivers/gpu/drm/radeon/radeon_device.c
drivers/gpu/drm/radeon/radeon_display.c
drivers/gpu/drm/radeon/radeon_drv.c
drivers/gpu/drm/radeon/radeon_family.h
drivers/gpu/drm/radeon/radeon_legacy_crtc.c
drivers/gpu/drm/radeon/radeon_mode.h
drivers/gpu/drm/radeon/radeon_ttm.c
drivers/gpu/drm/radeon/rs400.c
drivers/gpu/drm/radeon/rs600.c
drivers/gpu/drm/radeon/rs690.c
drivers/gpu/drm/radeon/rv515.c
drivers/gpu/drm/radeon/rv770.c
drivers/gpu/drm/radeon/si.c
drivers/gpu/drm/radeon/sid.h
drivers/gpu/drm/shmobile/shmob_drm_crtc.c
drivers/gpu/drm/tilcdc/Kconfig
drivers/gpu/host1x/drm/dc.c
drivers/hid/Kconfig
drivers/hid/Makefile
drivers/hid/hid-core.c
drivers/hid/hid-elo.c [new file with mode: 0644]
drivers/hid/hid-holtek-mouse.c [new file with mode: 0644]
drivers/hid/hid-huion.c [new file with mode: 0644]
drivers/hid/hid-hyperv.c
drivers/hid/hid-ids.h
drivers/hid/hid-input.c
drivers/hid/hid-kye.c
drivers/hid/hid-multitouch.c
drivers/hid/hid-ps3remote.c [deleted file]
drivers/hid/hid-roccat.c
drivers/hid/hid-sony.c
drivers/hid/hid-wacom.c
drivers/hid/i2c-hid/i2c-hid.c
drivers/hv/channel_mgmt.c
drivers/hwmon/abituguru.c
drivers/hwmon/adm1021.c
drivers/hwmon/iio_hwmon.c
drivers/hwmon/nct6775.c
drivers/hwmon/tmp401.c
drivers/i2c/busses/i2c-designware-core.c
drivers/i2c/busses/i2c-designware-core.h
drivers/i2c/busses/i2c-designware-platdrv.c
drivers/i2c/busses/i2c-i801.c
drivers/i2c/busses/i2c-mv64xxx.c
drivers/i2c/busses/i2c-s3c2410.c
drivers/i2c/busses/i2c-sirf.c
drivers/i2c/busses/i2c-tegra.c
drivers/i2c/i2c-core.c
drivers/idle/intel_idle.c
drivers/iio/adc/exynos_adc.c
drivers/iio/buffer_cb.c
drivers/iio/common/st_sensors/st_sensors_core.c
drivers/iio/dac/Kconfig
drivers/iio/frequency/adf4350.c
drivers/iio/inkern.c
drivers/infiniband/hw/qib/qib_keys.c
drivers/infiniband/ulp/iser/iscsi_iser.c
drivers/infiniband/ulp/iser/iscsi_iser.h
drivers/infiniband/ulp/iser/iser_initiator.c
drivers/infiniband/ulp/iser/iser_memory.c
drivers/infiniband/ulp/iser/iser_verbs.c
drivers/infiniband/ulp/srpt/ib_srpt.c
drivers/infiniband/ulp/srpt/ib_srpt.h
drivers/input/mouse/synaptics.c
drivers/input/tablet/wacom_wac.c
drivers/input/tablet/wacom_wac.h
drivers/input/touchscreen/egalax_ts.c
drivers/irqchip/irq-mxs.c
drivers/irqchip/irq-versatile-fpga.c
drivers/irqchip/irq-vic.c
drivers/isdn/capi/kcapi.c
drivers/leds/leds-gpio.c
drivers/leds/leds-ot200.c
drivers/lguest/page_tables.c
drivers/md/bcache/Kconfig
drivers/md/bcache/bcache.h
drivers/md/bcache/stats.c
drivers/md/bcache/super.c
drivers/md/bcache/writeback.c
drivers/md/dm-bufio.c
drivers/md/dm-cache-metadata.c
drivers/md/dm-cache-policy.h
drivers/md/dm-cache-target.c
drivers/md/dm-mpath.c
drivers/md/dm-snap.c
drivers/md/dm-stripe.c
drivers/md/dm-table.c
drivers/md/dm-thin-metadata.c
drivers/md/dm-thin-metadata.h
drivers/md/dm-thin.c
drivers/md/persistent-data/dm-space-map-disk.c
drivers/md/persistent-data/dm-space-map-metadata.c
drivers/md/persistent-data/dm-space-map.h
drivers/md/raid5.c
drivers/media/pci/zoran/zoran.h
drivers/media/pci/zoran/zoran_driver.c
drivers/media/platform/omap/omap_vout.c
drivers/memory/emif.c
drivers/mfd/Kconfig
drivers/mfd/ab8500-core.c
drivers/mfd/ab8500-debugfs.c
drivers/mfd/ab8500-gpadc.c
drivers/mfd/ab8500-sysctrl.c
drivers/mfd/abx500-core.c
drivers/mfd/cros_ec_spi.c
drivers/mfd/db8500-prcmu.c
drivers/mfd/intel_msic.c
drivers/mfd/si476x-cmd.c
drivers/misc/atmel-ssc.c
drivers/misc/dummy-irq.c
drivers/misc/mei/bus.c
drivers/misc/mei/main.c
drivers/misc/sgi-gru/grufile.c
drivers/misc/vmw_vmci/Kconfig
drivers/misc/vmw_vmci/vmci_queue_pair.c
drivers/mmc/host/atmel-mci.c
drivers/mmc/host/mmci.c
drivers/mmc/host/omap_hsmmc.c
drivers/mmc/host/sdhci-acpi.c
drivers/mmc/host/sdhci-esdhc-imx.c
drivers/mmc/host/sdhci-pci.c
drivers/mtd/nand/lpc32xx_mlc.c
drivers/net/bonding/bond_3ad.c
drivers/net/bonding/bond_3ad.h
drivers/net/bonding/bond_main.c
drivers/net/bonding/bond_procfs.c
drivers/net/bonding/bond_sysfs.c
drivers/net/caif/Kconfig
drivers/net/can/usb/esd_usb2.c
drivers/net/can/usb/kvaser_usb.c
drivers/net/can/usb/peak_usb/pcan_usb_pro.c
drivers/net/can/usb/peak_usb/pcan_usb_pro.h
drivers/net/ethernet/3com/3c59x.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
drivers/net/ethernet/broadcom/tg3.c
drivers/net/ethernet/broadcom/tg3.h
drivers/net/ethernet/brocade/bna/bnad.c
drivers/net/ethernet/cadence/Kconfig
drivers/net/ethernet/cadence/macb.c
drivers/net/ethernet/cadence/macb.h
drivers/net/ethernet/calxeda/Kconfig
drivers/net/ethernet/emulex/benet/be.h
drivers/net/ethernet/emulex/benet/be_cmds.c
drivers/net/ethernet/emulex/benet/be_hw.h
drivers/net/ethernet/emulex/benet/be_main.c
drivers/net/ethernet/freescale/fec_main.c
drivers/net/ethernet/freescale/gianfar_ptp.c
drivers/net/ethernet/ibm/emac/core.c
drivers/net/ethernet/icplus/ipg.h
drivers/net/ethernet/marvell/mv643xx_eth.c
drivers/net/ethernet/mellanox/mlx4/cmd.c
drivers/net/ethernet/mellanox/mlx4/en_netdev.c
drivers/net/ethernet/mellanox/mlx4/en_resources.c
drivers/net/ethernet/mellanox/mlx4/fw.c
drivers/net/ethernet/mellanox/mlx4/main.c
drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
drivers/net/ethernet/qlogic/qlge/qlge_main.c
drivers/net/ethernet/realtek/8139cp.c
drivers/net/ethernet/realtek/r8169.c
drivers/net/ethernet/renesas/sh_eth.c
drivers/net/ethernet/sfc/efx.c
drivers/net/ethernet/sfc/net_driver.h
drivers/net/ethernet/sfc/rx.c
drivers/net/ethernet/stmicro/stmmac/Kconfig
drivers/net/ethernet/ti/davinci_mdio.c
drivers/net/ethernet/xilinx/xilinx_emaclite.c
drivers/net/hyperv/netvsc_drv.c
drivers/net/macvlan.c
drivers/net/ntb_netdev.c
drivers/net/phy/phy.c
drivers/net/team/team.c
drivers/net/team/team_mode_random.c
drivers/net/team/team_mode_roundrobin.c
drivers/net/tun.c
drivers/net/usb/cdc_ether.c
drivers/net/usb/qmi_wwan.c
drivers/net/usb/rtl8150.c
drivers/net/usb/usbnet.c
drivers/net/virtio_net.c
drivers/net/vxlan.c
drivers/net/wireless/ath/ath5k/base.c
drivers/net/wireless/ath/ath9k/Kconfig
drivers/net/wireless/ath/ath9k/Makefile
drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
drivers/net/wireless/ath/ath9k/ar9003_calib.c
drivers/net/wireless/ath/ath9k/ar9003_eeprom.h
drivers/net/wireless/ath/ath9k/ar9003_phy.c
drivers/net/wireless/ath/ath9k/ar9485_initvals.h
drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h
drivers/net/wireless/ath/ath9k/ath9k.h
drivers/net/wireless/ath/ath9k/debug.c
drivers/net/wireless/ath/ath9k/debug.h
drivers/net/wireless/ath/ath9k/hw.c
drivers/net/wireless/ath/ath9k/init.c
drivers/net/wireless/ath/ath9k/mac.c
drivers/net/wireless/ath/ath9k/main.c
drivers/net/wireless/ath/ath9k/rc.c
drivers/net/wireless/ath/ath9k/rc.h
drivers/net/wireless/ath/ath9k/reg.h
drivers/net/wireless/ath/ath9k/xmit.c
drivers/net/wireless/atmel.c
drivers/net/wireless/b43/dma.c
drivers/net/wireless/b43/dma.h
drivers/net/wireless/b43/main.c
drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
drivers/net/wireless/brcm80211/brcmfmac/fweh.c
drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h
drivers/net/wireless/brcm80211/brcmfmac/p2p.c
drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h
drivers/net/wireless/iwlegacy/4965-mac.c
drivers/net/wireless/iwlegacy/common.c
drivers/net/wireless/iwlegacy/common.h
drivers/net/wireless/iwlwifi/dvm/sta.c
drivers/net/wireless/iwlwifi/mvm/fw-api.h
drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
drivers/net/wireless/iwlwifi/mvm/mac80211.c
drivers/net/wireless/iwlwifi/mvm/mvm.h
drivers/net/wireless/iwlwifi/mvm/ops.c
drivers/net/wireless/iwlwifi/mvm/scan.c
drivers/net/wireless/iwlwifi/mvm/sta.c
drivers/net/wireless/iwlwifi/mvm/sta.h
drivers/net/wireless/iwlwifi/mvm/tx.c
drivers/net/wireless/mac80211_hwsim.c
drivers/net/wireless/mwifiex/cfg80211.c
drivers/net/wireless/mwifiex/cmdevt.c
drivers/net/wireless/mwifiex/debugfs.c
drivers/net/wireless/mwifiex/main.c
drivers/net/wireless/mwifiex/sta_ioctl.c
drivers/net/wireless/rtlwifi/pci.c
drivers/net/wireless/rtlwifi/rtl8188ee/trx.h
drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
drivers/net/wireless/rtlwifi/rtl8192cu/hw.h
drivers/net/wireless/rtlwifi/rtl8192cu/mac.c
drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
drivers/net/wireless/rtlwifi/rtl8192cu/sw.h
drivers/net/wireless/rtlwifi/usb.c
drivers/net/wireless/rtlwifi/wifi.h
drivers/net/wireless/ti/wl12xx/scan.c
drivers/net/wireless/ti/wl12xx/wl12xx.h
drivers/net/wireless/ti/wl18xx/scan.c
drivers/nfc/Kconfig
drivers/nfc/mei_phy.c
drivers/nfc/microread/mei.c
drivers/nfc/pn544/mei.c
drivers/ntb/ntb_hw.c
drivers/ntb/ntb_transport.c
drivers/of/base.c
drivers/parisc/lba_pci.c
drivers/parisc/superio.c
drivers/parport/Kconfig
drivers/parport/parport_gsc.c
drivers/parport/parport_gsc.h
drivers/pci/hotplug/acpiphp_glue.c
drivers/pci/pcie/aer/aerdrv_core.c
drivers/pci/pcie/aer/aerdrv_errprint.c
drivers/pcmcia/m8xx_pcmcia.c
drivers/pinctrl/pinconf.c
drivers/pinctrl/pinctrl-abx500.c
drivers/pinctrl/pinctrl-coh901.c
drivers/pinctrl/pinctrl-exynos.c
drivers/pinctrl/pinctrl-exynos.h
drivers/pinctrl/pinctrl-exynos5440.c
drivers/pinctrl/pinctrl-lantiq.c
drivers/pinctrl/pinctrl-samsung.c
drivers/pinctrl/pinctrl-samsung.h
drivers/pinctrl/pinctrl-single.c
drivers/pinctrl/pinctrl-sunxi.c
drivers/pinctrl/pinctrl-xway.c
drivers/pinctrl/sh-pfc/pfc-r8a7779.c
drivers/pinctrl/vt8500/pinctrl-wm8750.c
drivers/pinctrl/vt8500/pinctrl-wmt.c
drivers/platform/x86/Kconfig
drivers/platform/x86/Makefile
drivers/platform/x86/asus-nb-wmi.c
drivers/platform/x86/dell-laptop.c
drivers/platform/x86/dell-wmi-aio.c
drivers/platform/x86/hp-wmi.c
drivers/platform/x86/hp_accel.c
drivers/platform/x86/ideapad-laptop.c
drivers/platform/x86/pvpanic.c [new file with mode: 0644]
drivers/platform/x86/samsung-q10.c
drivers/platform/x86/sony-laptop.c
drivers/power/Kconfig
drivers/power/pm2301_charger.c
drivers/power/wm831x_backup.c
drivers/ptp/ptp_pch.c
drivers/pwm/pwm-imx.c
drivers/pwm/pwm-puv3.c
drivers/pwm/pwm-pxa.c
drivers/pwm/pwm-tegra.c
drivers/pwm/pwm-tiecap.c
drivers/pwm/pwm-tiehrpwm.c
drivers/pwm/pwm-tipwmss.c
drivers/pwm/pwm-vt8500.c
drivers/rapidio/Kconfig
drivers/rapidio/Makefile
drivers/rapidio/devices/tsi721.c
drivers/rapidio/rio-driver.c
drivers/rapidio/rio-scan.c
drivers/rapidio/rio-sysfs.c
drivers/rapidio/rio.c
drivers/rapidio/rio.h
drivers/regulator/core.c
drivers/regulator/dbx500-prcmu.c
drivers/regulator/palmas-regulator.c
drivers/rtc/Kconfig
drivers/rtc/rtc-at91rm9200.c
drivers/rtc/rtc-cmos.c
drivers/rtc/rtc-max8998.c
drivers/rtc/rtc-nuc900.c
drivers/rtc/rtc-omap.c
drivers/rtc/rtc-pl031.c
drivers/rtc/rtc-s3c.c
drivers/rtc/rtc-tegra.c
drivers/rtc/rtc-tps6586x.c
drivers/rtc/rtc-twl.c
drivers/s390/block/dasd.c
drivers/s390/block/xpram.c
drivers/s390/cio/chp.c
drivers/s390/cio/chsc.h
drivers/scsi/Kconfig
drivers/scsi/aic94xx/aic94xx_dev.c
drivers/scsi/aic94xx/aic94xx_hwi.c
drivers/scsi/aic94xx/aic94xx_tmf.c
drivers/scsi/be2iscsi/be.h
drivers/scsi/be2iscsi/be_cmds.c
drivers/scsi/be2iscsi/be_cmds.h
drivers/scsi/be2iscsi/be_iscsi.c
drivers/scsi/be2iscsi/be_iscsi.h
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/bnx2fc/bnx2fc.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_lnode.h
drivers/scsi/csiostor/csio_rnode.h
drivers/scsi/fnic/fnic.h
drivers/scsi/fnic/fnic_fcs.c
drivers/scsi/fnic/fnic_fip.h [new file with mode: 0644]
drivers/scsi/fnic/fnic_main.c
drivers/scsi/fnic/vnic_dev.c
drivers/scsi/fnic/vnic_dev.h
drivers/scsi/fnic/vnic_devcmd.h
drivers/scsi/ibmvscsi/ibmvfc.c
drivers/scsi/ibmvscsi/ibmvfc.h
drivers/scsi/ipr.c
drivers/scsi/ipr.h
drivers/scsi/isci/remote_device.c
drivers/scsi/isci/remote_device.h
drivers/scsi/isci/request.c
drivers/scsi/isci/task.c
drivers/scsi/libsas/sas_ata.c
drivers/scsi/libsas/sas_discover.c
drivers/scsi/libsas/sas_expander.c
drivers/scsi/libsas/sas_internal.h
drivers/scsi/libsas/sas_port.c
drivers/scsi/lpfc/lpfc.h
drivers/scsi/lpfc/lpfc_attr.c
drivers/scsi/lpfc/lpfc_bsg.c
drivers/scsi/lpfc/lpfc_crtn.h
drivers/scsi/lpfc/lpfc_ct.c
drivers/scsi/lpfc/lpfc_els.c
drivers/scsi/lpfc/lpfc_hbadisc.c
drivers/scsi/lpfc/lpfc_hw.h
drivers/scsi/lpfc/lpfc_hw4.h
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/lpfc/lpfc_logmsg.h
drivers/scsi/lpfc/lpfc_mbox.c
drivers/scsi/lpfc/lpfc_mem.c
drivers/scsi/lpfc/lpfc_nportdisc.c
drivers/scsi/lpfc/lpfc_scsi.c
drivers/scsi/lpfc/lpfc_sli.c
drivers/scsi/lpfc/lpfc_sli4.h
drivers/scsi/lpfc/lpfc_version.h
drivers/scsi/lpfc/lpfc_vport.c
drivers/scsi/lpfc/lpfc_vport.h
drivers/scsi/megaraid/megaraid_sas_base.c
drivers/scsi/mvsas/mv_init.c
drivers/scsi/mvsas/mv_sas.c
drivers/scsi/mvsas/mv_sas.h
drivers/scsi/pm8001/Makefile
drivers/scsi/pm8001/pm8001_ctl.c
drivers/scsi/pm8001/pm8001_defs.h
drivers/scsi/pm8001/pm8001_hwi.c
drivers/scsi/pm8001/pm8001_hwi.h
drivers/scsi/pm8001/pm8001_init.c
drivers/scsi/pm8001/pm8001_sas.c
drivers/scsi/pm8001/pm8001_sas.h
drivers/scsi/pm8001/pm80xx_hwi.c [new file with mode: 0644]
drivers/scsi/pm8001/pm80xx_hwi.h [new file with mode: 0644]
drivers/scsi/qla2xxx/Kconfig
drivers/scsi/qla2xxx/qla_mr.c
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/qla2xxx/tcm_qla2xxx.c
drivers/scsi/qla4xxx/ql4_iocb.c
drivers/scsi/qla4xxx/ql4_os.c
drivers/scsi/qla4xxx/ql4_version.h
drivers/scsi/scsi_debug.c
drivers/scsi/scsi_error.c
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_pm.c
drivers/scsi/scsi_proc.c
drivers/scsi/scsi_transport_iscsi.c
drivers/scsi/sd.c
drivers/scsi/sd.h
drivers/scsi/sd_dif.c
drivers/scsi/ufs/Kconfig
drivers/scsi/ufs/Makefile
drivers/scsi/ufs/ufshcd-pltfrm.c [new file with mode: 0644]
drivers/scsi/ufs/ufshcd.c
drivers/spi/spi-atmel.c
drivers/spi/spi-davinci.c
drivers/spi/spi-sh-hspi.c
drivers/spi/spi-tegra20-sflash.c
drivers/spi/spi-topcliff-pch.c
drivers/spi/spi-xilinx.c
drivers/spi/spi.c
drivers/staging/Kconfig
drivers/staging/android/alarm-dev.c
drivers/staging/android/logger.c
drivers/staging/android/logger.h
drivers/staging/comedi/Kconfig
drivers/staging/comedi/comedi_buf.c
drivers/staging/comedi/comedi_fops.c
drivers/staging/comedi/drivers/ni_labpc.c
drivers/staging/comedi/drivers/ni_labpc.h
drivers/staging/comedi/drivers/ni_mio_common.c
drivers/staging/dwc2/Kconfig
drivers/staging/dwc2/hcd.c
drivers/staging/dwc2/hcd_intr.c
drivers/staging/dwc2/platform.c
drivers/staging/gdm72xx/Kconfig
drivers/staging/iio/adc/mxs-lradc.c
drivers/staging/iio/light/tsl2x7x_core.c
drivers/staging/imx-drm/Kconfig
drivers/staging/imx-drm/imx-tve.c
drivers/staging/imx-drm/ipuv3-crtc.c
drivers/staging/media/solo6x10/Kconfig
drivers/staging/nvec/nvec.c
drivers/staging/nvec/nvec.h
drivers/staging/nvec/nvec_kbd.c
drivers/staging/nvec/nvec_power.c
drivers/staging/nvec/nvec_ps2.c
drivers/staging/sep/Kconfig
drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c
drivers/staging/vt6656/hostap.c
drivers/staging/vt6656/iwctl.c
drivers/staging/zcache/ramster.h
drivers/staging/zcache/ramster/debug.c
drivers/staging/zcache/ramster/ramster-howto.txt [new file with mode: 0644]
drivers/staging/zcache/ramster/ramster.c
drivers/staging/zcache/zcache-main.c
drivers/target/iscsi/iscsi_target.c
drivers/target/iscsi/iscsi_target_erl1.c
drivers/target/iscsi/iscsi_target_erl2.c
drivers/target/iscsi/iscsi_target_parameters.c
drivers/target/iscsi/iscsi_target_parameters.h
drivers/target/iscsi/iscsi_target_util.c
drivers/target/iscsi/iscsi_target_util.h
drivers/target/target_core_configfs.c
drivers/target/target_core_device.c
drivers/target/target_core_file.c
drivers/target/target_core_iblock.c
drivers/target/target_core_internal.h
drivers/target/target_core_rd.c
drivers/target/target_core_rd.h
drivers/target/target_core_transport.c
drivers/thermal/armada_thermal.c
drivers/thermal/dove_thermal.c
drivers/thermal/exynos_thermal.c
drivers/tty/ehv_bytechan.c
drivers/tty/mxser.c
drivers/tty/n_tty.c
drivers/tty/rocket.c
drivers/tty/serial/8250/8250_core.c
drivers/tty/serial/8250/8250_dw.c
drivers/tty/serial/amba-pl011.c
drivers/tty/serial/imx.c
drivers/tty/serial/mcf.c
drivers/tty/serial/mpc52xx_uart.c
drivers/tty/serial/nwpserial.c
drivers/tty/serial/omap-serial.c
drivers/tty/serial/samsung.c
drivers/tty/tty_audit.c
drivers/tty/vt/vt.c
drivers/tty/vt/vt_ioctl.c
drivers/uio/Kconfig
drivers/usb/atm/cxacru.c
drivers/usb/chipidea/Kconfig
drivers/usb/chipidea/ci13xxx_imx.c
drivers/usb/chipidea/core.c
drivers/usb/core/Kconfig
drivers/usb/core/devio.c
drivers/usb/core/quirks.c
drivers/usb/dwc3/Kconfig
drivers/usb/dwc3/dwc3-exynos.c
drivers/usb/dwc3/dwc3-pci.c
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/Kconfig
drivers/usb/gadget/atmel_usba_udc.c
drivers/usb/gadget/bcm63xx_udc.c
drivers/usb/gadget/configfs.c
drivers/usb/gadget/dummy_hcd.c
drivers/usb/gadget/f_ecm.c
drivers/usb/gadget/f_subset.c
drivers/usb/gadget/f_uac2.c
drivers/usb/gadget/fusb300_udc.c
drivers/usb/gadget/imx_udc.c
drivers/usb/gadget/m66592-udc.c
drivers/usb/gadget/pxa25x_udc.c
drivers/usb/gadget/r8a66597-udc.c
drivers/usb/gadget/s3c-hsotg.c
drivers/usb/gadget/s3c2410_udc.c
drivers/usb/gadget/zero.c
drivers/usb/host/Kconfig
drivers/usb/host/ehci-atmel.c
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ehci-omap.c
drivers/usb/host/ehci-orion.c
drivers/usb/host/ehci-s5p.c
drivers/usb/host/ehci-sched.c
drivers/usb/host/ehci-spear.c
drivers/usb/host/ehci-tegra.c
drivers/usb/host/isp1760-hcd.c
drivers/usb/host/isp1760-if.c
drivers/usb/host/ohci-at91.c
drivers/usb/host/ohci-exynos.c
drivers/usb/host/ohci-hcd.c
drivers/usb/host/ohci-nxp.c
drivers/usb/host/ohci-omap3.c
drivers/usb/host/ohci-pxa27x.c
drivers/usb/host/ohci-spear.c
drivers/usb/host/oxu210hp-hcd.c
drivers/usb/host/sl811-hcd.c
drivers/usb/host/uhci-hub.c
drivers/usb/host/uhci-platform.c
drivers/usb/host/uhci-q.c
drivers/usb/host/xhci-mem.c
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci.c
drivers/usb/host/xhci.h
drivers/usb/musb/musb_dsps.c
drivers/usb/musb/musb_host.c
drivers/usb/musb/musb_host.h
drivers/usb/musb/omap2430.c
drivers/usb/phy/Kconfig
drivers/usb/phy/phy-ab8500-usb.c
drivers/usb/phy/phy-fsl-usb.c
drivers/usb/phy/phy-gpio-vbus-usb.c
drivers/usb/phy/phy-isp1301.c
drivers/usb/phy/phy-mv-u3d-usb.c
drivers/usb/phy/phy-mv-usb.c
drivers/usb/phy/phy-mxs-usb.c
drivers/usb/phy/phy-nop.c
drivers/usb/phy/phy-samsung-usb2.c
drivers/usb/phy/phy-samsung-usb3.c
drivers/usb/serial/ark3116.c
drivers/usb/serial/cypress_m8.c
drivers/usb/serial/cypress_m8.h
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio_ids.h
drivers/usb/serial/generic.c
drivers/usb/serial/io_ti.c
drivers/usb/serial/iuu_phoenix.c
drivers/usb/serial/keyspan.c
drivers/usb/serial/mos7720.c
drivers/usb/serial/mos7840.c
drivers/usb/serial/option.c
drivers/usb/serial/qcserial.c
drivers/usb/serial/ti_usb_3410_5052.c
drivers/usb/serial/usb-serial.c
drivers/usb/serial/visor.c
drivers/usb/serial/whiteheat.c
drivers/usb/serial/zte_ev.c
drivers/usb/storage/realtek_cr.c
drivers/vfio/vfio.c
drivers/vhost/net.c
drivers/vhost/vhost.c
drivers/vhost/vhost.h
drivers/vhost/vringh.c
drivers/video/Kconfig
drivers/video/Makefile
drivers/video/atmel_lcdfb.c
drivers/video/console/Makefile
drivers/video/omap2/dss/core.c
drivers/video/omap2/dss/hdmi.c
drivers/video/omap2/omapfb/omapfb-main.c
drivers/video/omap2/vrfb.c
drivers/video/ps3fb.c
drivers/video/simplefb.c [new file with mode: 0644]
drivers/w1/masters/omap_hdq.c
drivers/watchdog/ath79_wdt.c
drivers/watchdog/davinci_wdt.c
drivers/watchdog/imx2_wdt.c
drivers/xen/Kconfig
drivers/xen/balloon.c
drivers/xen/events.c
drivers/xen/privcmd.c
drivers/xen/tmem.c
drivers/xen/xen-pciback/pci_stub.c
drivers/xen/xen-selfballoon.c
drivers/xen/xenbus/xenbus_client.c
drivers/xen/xenbus/xenbus_comms.h
drivers/xen/xenbus/xenbus_dev_backend.c
drivers/xen/xenbus/xenbus_probe.c
drivers/xen/xenbus/xenbus_probe.h
drivers/xen/xenbus/xenbus_probe_frontend.c
fs/aio.c
fs/befs/linuxvfs.c
fs/btrfs/backref.c
fs/btrfs/check-integrity.c
fs/btrfs/ctree.c
fs/btrfs/ctree.h
fs/btrfs/delayed-ref.h
fs/btrfs/dev-replace.c
fs/btrfs/disk-io.c
fs/btrfs/extent-tree.c
fs/btrfs/extent_io.c
fs/btrfs/extent_io.h
fs/btrfs/free-space-cache.c
fs/btrfs/free-space-cache.h
fs/btrfs/inode-map.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/raid56.c
fs/btrfs/relocation.c
fs/btrfs/scrub.c
fs/btrfs/super.c
fs/btrfs/volumes.c
fs/btrfs/volumes.h
fs/ceph/locks.c
fs/ceph/mds_client.c
fs/ceph/super.h
fs/cifs/cifs_dfs_ref.c
fs/cifs/cifsfs.c
fs/cifs/connect.c
fs/cifs/dns_resolve.c
fs/cifs/inode.c
fs/ecryptfs/crypto.c
fs/ecryptfs/ecryptfs_kernel.h
fs/ecryptfs/file.c
fs/efivarfs/file.c
fs/ext4/ext4.h
fs/ext4/extents.c
fs/ext4/extents_status.c
fs/ext4/extents_status.h
fs/ext4/file.c
fs/ext4/inode.c
fs/ext4/mballoc.c
fs/ext4/page-io.c
fs/fat/inode.c
fs/fuse/dir.c
fs/fuse/file.c
fs/fuse/inode.c
fs/gfs2/Kconfig
fs/gfs2/bmap.c
fs/gfs2/dir.c
fs/gfs2/file.c
fs/gfs2/inode.c
fs/gfs2/lops.c
fs/gfs2/quota.c
fs/gfs2/rgrp.c
fs/gfs2/super.c
fs/hfs/bnode.c
fs/hpfs/dir.c
fs/hpfs/file.c
fs/jfs/jfs_logmgr.c
fs/jfs/super.c
fs/namei.c
fs/nfs/callback_proc.c
fs/nfs/callback_xdr.c
fs/nfs/nfs4client.c
fs/nfs/nfs4proc.c
fs/nfs/nfs4session.c
fs/nfs/nfs4session.h
fs/nfs/nfs4state.c
fs/nfs/super.c
fs/nfsd/nfs4proc.c
fs/nfsd/nfs4recover.c
fs/nilfs2/inode.c
fs/notify/fanotify/fanotify_user.c
fs/ocfs2/dlm/dlmrecovery.c
fs/ocfs2/extent_map.c
fs/ocfs2/file.c
fs/ocfs2/namei.c
fs/pnode.c
fs/proc/base.c
fs/proc/kmsg.c
fs/qnx6/dir.c
fs/reiserfs/dir.c
fs/reiserfs/inode.c
fs/reiserfs/xattr.c
fs/reiserfs/xattr_acl.c
fs/xfs/xfs_acl.c
fs/xfs/xfs_acl.h
fs/xfs/xfs_aops.c
fs/xfs/xfs_attr_leaf.c
fs/xfs/xfs_attr_remote.c
fs/xfs/xfs_attr_remote.h
fs/xfs/xfs_buf.c
fs/xfs/xfs_buf_item.c
fs/xfs/xfs_da_btree.c
fs/xfs/xfs_dfrag.c
fs/xfs/xfs_dir2_format.h
fs/xfs/xfs_dir2_leaf.c
fs/xfs/xfs_dir2_node.c
fs/xfs/xfs_dquot.c
fs/xfs/xfs_extfree_item.c
fs/xfs/xfs_fs.h
fs/xfs/xfs_fsops.c
fs/xfs/xfs_inode.c
fs/xfs/xfs_iops.c
fs/xfs/xfs_log_cil.c
fs/xfs/xfs_log_recover.c
fs/xfs/xfs_qm.c
fs/xfs/xfs_qm_syscalls.c
fs/xfs/xfs_quota.h
fs/xfs/xfs_super.c
fs/xfs/xfs_symlink.c
fs/xfs/xfs_vnodeops.c
include/acpi/acpi_bus.h
include/acpi/acpiosxf.h
include/acpi/processor.h
include/asm-generic/io.h
include/asm-generic/kvm_para.h
include/asm-generic/tlb.h
include/drm/drmP.h
include/drm/drm_fb_helper.h
include/drm/drm_os_linux.h
include/drm/drm_pciids.h
include/linux/acpi_dma.h
include/linux/aer.h
include/linux/audit.h
include/linux/bcma/bcma.h
include/linux/brcmphy.h
include/linux/cgroup.h
include/linux/compat.h
include/linux/cpu.h
include/linux/cpuidle.h
include/linux/device-mapper.h
include/linux/filter.h
include/linux/ftrace.h
include/linux/ftrace_event.h
include/linux/if_team.h
include/linux/journal-head.h
include/linux/kernel.h
include/linux/kref.h
include/linux/list.h
include/linux/math64.h
include/linux/mfd/abx500/ab8500.h
include/linux/mlx4/qp.h
include/linux/netdevice.h
include/linux/netfilter_ipv6.h
include/linux/of_platform.h
include/linux/pci-acpi.h
include/linux/pci_ids.h
include/linux/pinctrl/pinconf-generic.h
include/linux/platform_data/clk-lpss.h
include/linux/platform_data/serial-omap.h
include/linux/printk.h
include/linux/rculist.h
include/linux/rculist_nulls.h
include/linux/rcupdate.h
include/linux/rio.h
include/linux/rio_drv.h
include/linux/scatterlist.h
include/linux/sched.h
include/linux/skbuff.h
include/linux/socket.h
include/linux/spi/spi.h
include/linux/swapops.h
include/linux/syslog.h
include/linux/time.h
include/linux/tty.h
include/linux/uio.h
include/linux/usb/gadget.h
include/linux/usb/serial.h
include/linux/vt_kern.h
include/linux/wait.h
include/net/addrconf.h
include/net/bluetooth/hci_core.h
include/net/bluetooth/mgmt.h
include/net/mac80211.h
include/net/netfilter/nf_log.h
include/net/netfilter/nfnetlink_log.h
include/net/sch_generic.h
include/net/sock.h
include/net/xfrm.h
include/scsi/libsas.h
include/scsi/osd_protocol.h
include/scsi/sas.h
include/scsi/sas_ata.h
include/scsi/scsi_device.h
include/scsi/scsi_transport_iscsi.h
include/scsi/scsi_transport_sas.h
include/target/target_core_base.h
include/target/target_core_fabric.h
include/trace/events/ext4.h
include/uapi/linux/audit.h
include/uapi/linux/kvm.h
include/uapi/linux/virtio_console.h
include/video/omapdss.h
include/xen/xenbus.h
ipc/sem.c
kernel/audit.c
kernel/audit.h
kernel/audit_tree.c
kernel/auditfilter.c
kernel/auditsc.c
kernel/cgroup.c
kernel/cpu.c
kernel/cpu/idle.c
kernel/events/core.c
kernel/irq/irqdomain.c
kernel/kmod.c
kernel/module.c
kernel/params.c
kernel/printk.c
kernel/range.c
kernel/rcutree_plugin.h
kernel/softirq.c
kernel/sys.c
kernel/sys_ni.c
kernel/sysctl_binary.c
kernel/time/Kconfig
kernel/time/ntp.c
kernel/time/tick-broadcast.c
kernel/time/tick-sched.c
kernel/time/timekeeping.c
kernel/timer.c
kernel/trace/Kconfig
kernel/trace/ftrace.c
kernel/trace/ring_buffer.c
kernel/trace/trace.c
kernel/trace/trace.h
kernel/trace/trace_events.c
kernel/trace/trace_events_filter.c
kernel/trace/trace_kprobe.c
kernel/trace/trace_selftest.c
kernel/workqueue.c
lib/Makefile
lib/iovec.c [new file with mode: 0644]
lib/klist.c
lib/mpi/longlong.h
lib/mpi/mpicoder.c
mm/frontswap.c
mm/huge_memory.c
mm/hugetlb.c
mm/memcontrol.c
mm/memory.c
mm/memory_hotplug.c
mm/migrate.c
mm/mmu_notifier.c
mm/page_alloc.c
mm/pagewalk.c
mm/swap_state.c
mm/swapfile.c
net/802/mrp.c
net/9p/client.c
net/batman-adv/distributed-arp-table.c
net/batman-adv/main.c
net/batman-adv/network-coding.c
net/batman-adv/originator.c
net/batman-adv/originator.h
net/batman-adv/soft-interface.c
net/batman-adv/translation-table.c
net/bluetooth/hci_core.c
net/bluetooth/hidp/core.c
net/bluetooth/hidp/hidp.h
net/bluetooth/l2cap_core.c
net/bluetooth/mgmt.c
net/bluetooth/smp.c
net/bridge/netfilter/ebt_log.c
net/bridge/netfilter/ebt_ulog.c
net/ceph/osd_client.c
net/compat.c
net/core/dev_addr_lists.c
net/core/filter.c
net/core/iovec.c
net/core/skbuff.c
net/core/sock.c
net/core/sock_diag.c
net/ipv4/ip_gre.c
net/ipv4/ip_output.c
net/ipv4/ip_tunnel.c
net/ipv4/netfilter/ipt_ULOG.c
net/ipv4/route.c
net/ipv4/tcp.c
net/ipv4/tcp_input.c
net/ipv4/tcp_output.c
net/ipv6/addrconf.c
net/ipv6/ip6_gre.c
net/ipv6/ip6_output.c
net/ipv6/netfilter.c
net/ipv6/proc.c
net/ipv6/tcp_ipv6.c
net/ipv6/udp.c
net/ipv6/udp_impl.h
net/ipv6/udp_offload.c
net/ipv6/udplite.c
net/ipv6/xfrm6_policy.c
net/irda/irlap_frame.c
net/key/af_key.c
net/mac80211/ieee80211_i.h
net/mac80211/iface.c
net/mac80211/mlme.c
net/mac80211/rate.c
net/mac80211/rx.c
net/mac80211/tkip.c
net/mac80211/util.c
net/netfilter/core.c
net/netfilter/ipvs/ip_vs_core.c
net/netfilter/ipvs/ip_vs_ctl.c
net/netfilter/ipvs/ip_vs_sh.c
net/netfilter/nf_log.c
net/netfilter/nfnetlink_acct.c
net/netfilter/nfnetlink_cttimeout.c
net/netfilter/nfnetlink_log.c
net/netfilter/nfnetlink_queue_core.c
net/netfilter/xt_LOG.c
net/netfilter/xt_NFLOG.c
net/netfilter/xt_TCPMSS.c
net/netfilter/xt_TCPOPTSTRIP.c
net/netfilter/xt_addrtype.c
net/netlabel/netlabel_domainhash.c
net/netlink/af_netlink.c
net/nfc/Makefile
net/sched/act_police.c
net/sched/sch_api.c
net/sched/sch_generic.c
net/sched/sch_htb.c
net/sched/sch_tbf.c
net/sctp/socket.c
net/socket.c
net/sunrpc/auth_gss/auth_gss.c
net/sunrpc/auth_gss/gss_rpc_xdr.c
net/sunrpc/auth_gss/svcauth_gss.c
net/sunrpc/netns.h
net/sunrpc/rpc_pipe.c
net/sunrpc/sched.c
net/sunrpc/svcauth_unix.c
net/wireless/core.c
net/wireless/nl80211.c
net/wireless/sme.c
net/wireless/trace.h
net/xfrm/xfrm_output.c
net/xfrm/xfrm_policy.c
net/xfrm/xfrm_user.c
scripts/Makefile.lib
scripts/config
scripts/kconfig/lxdialog/menubox.c
scripts/kconfig/mconf.c
scripts/kconfig/menu.c
scripts/package/Makefile
security/selinux/xfrm.c
sound/aoa/fabrics/layout.c
sound/aoa/soundbus/i2sbus/core.c
sound/oss/Kconfig
sound/pci/hda/hda_generic.c
sound/pci/hda/hda_generic.h
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_via.c
sound/pci/sis7019.c
sound/soc/codecs/ab8500-codec.h
sound/soc/codecs/cs42l52.c
sound/soc/codecs/cs42l52.h
sound/soc/codecs/da7213.c
sound/soc/codecs/max98090.c
sound/soc/codecs/wm0010.c
sound/soc/codecs/wm5110.c
sound/soc/codecs/wm8994.c
sound/soc/davinci/davinci-mcasp.c
sound/soc/fsl/imx-ssi.c
sound/soc/kirkwood/kirkwood-i2s.c
sound/soc/soc-compress.c
sound/usb/6fire/firmware.c
sound/usb/mixer.c
sound/usb/proc.c
sound/usb/quirks-table.h
tools/perf/scripts/python/net_dropmonitor.py
tools/power/x86/turbostat/turbostat.c
tools/testing/selftests/Makefile
tools/testing/selftests/soft-dirty/Makefile [deleted file]
tools/testing/selftests/soft-dirty/soft-dirty.c [deleted file]
virt/kvm/kvm_main.c

index 77db880..b3a7e7d 100644 (file)
@@ -319,7 +319,10 @@ cache<0..n>
   Symlink to each of the cache devices comprising this cache set. 
 
 cache_available_percent
-  Percentage of cache device free.
+  Percentage of cache device which doesn't contain dirty data, and could
+  potentially be used for writeback.  This doesn't mean this space isn't used
+  for clean cached data; the unused statistic (in priority_stats) is typically
+  much lower.
 
 clear_stats
   Clears the statistics associated with this cache
@@ -423,8 +426,11 @@ nbuckets
   Total buckets in this cache
 
 priority_stats
-  Statistics about how recently data in the cache has been accessed.  This can
-  reveal your working set size.
+  Statistics about how recently data in the cache has been accessed.
+  This can reveal your working set size.  Unused is the percentage of
+  the cache that doesn't contain any data.  Metadata is bcache's
+  metadata overhead.  Average is the average priority of cache buckets.
+  Next is a list of quantiles with the priority threshold of each.
 
 written
   Sum of all data that has been written to the cache; comparison with
index 08f01e7..b901591 100644 (file)
@@ -498,12 +498,8 @@ Your cooperation is appreciated.
 
                Each device type has 5 bits (32 minors).
 
- 13 block      8-bit MFM/RLL/IDE controller
-                 0 = /dev/xda          First XT disk whole disk
-                64 = /dev/xdb          Second XT disk whole disk
-
-               Partitions are handled in the same way as IDE disks
-               (see major number 3).
+ 13 block      Previously used for the XT disk (/dev/xdN)
+               Deleted in kernel v3.9.
 
  14 char       Open Sound System (OSS)
                  0 = /dev/mixer        Mixer control
index 44afa0e..4ff6504 100644 (file)
@@ -4,7 +4,7 @@ Required properties:
 - compatible: Should be "cdns,[<chip>-]{macb|gem}"
   Use "cdns,at91sam9260-macb" Atmel at91sam9260 and at91sam9263 SoCs.
   Use "cdns,at32ap7000-macb" for other 10/100 usage or use the generic form: "cdns,macb".
-  Use "cnds,pc302-gem" for Picochip picoXcell pc302 and later devices based on
+  Use "cdns,pc302-gem" for Picochip picoXcell pc302 and later devices based on
   the Cadence GEM, or the generic form: "cdns,gem".
 - reg: Address and length of the register set for the device
 - interrupts: Should contain macb interrupt
index 2a3feab..34c1505 100644 (file)
@@ -1,7 +1,7 @@
 Atmel AT91RM9200 Real Time Clock
 
 Required properties:
-- compatible: should be: "atmel,at91rm9200-rtc"
+- compatible: should be: "atmel,at91rm9200-rtc" or "atmel,at91sam9x5-rtc"
 - reg: physical base address of the controller and length of memory mapped
   region.
 - interrupts: rtc alarm/event interrupt
diff --git a/Documentation/devicetree/bindings/video/simple-framebuffer.txt b/Documentation/devicetree/bindings/video/simple-framebuffer.txt
new file mode 100644 (file)
index 0000000..3ea4605
--- /dev/null
@@ -0,0 +1,25 @@
+Simple Framebuffer
+
+A simple frame-buffer describes a raw memory region that may be rendered to,
+with the assumption that the display hardware has already been set up to scan
+out from that buffer.
+
+Required properties:
+- compatible: "simple-framebuffer"
+- reg: Should contain the location and size of the framebuffer memory.
+- width: The width of the framebuffer in pixels.
+- height: The height of the framebuffer in pixels.
+- stride: The number of bytes in each line of the framebuffer.
+- format: The format of the framebuffer surface. Valid values are:
+  - r5g6b5 (16-bit pixels, d[15:11]=r, d[10:5]=g, d[4:0]=b).
+
+Example:
+
+       framebuffer {
+               compatible = "simple-framebuffer";
+               reg = <0x1d385000 (1600 * 1200 * 2)>;
+               width = <1600>;
+               height = <1200>;
+               stride = <(1600 * 2)>;
+               format = "r5g6b5";
+       };
index ef9d06c..0efedaa 100644 (file)
@@ -191,9 +191,11 @@ Linux it will look something like this:
        };
 
 The bootargs property contains the kernel arguments, and the initrd-*
-properties define the address and size of an initrd blob.  The
-chosen node may also optionally contain an arbitrary number of
-additional properties for platform-specific configuration data.
+properties define the address and size of an initrd blob.  Note that
+initrd-end is the first address after the initrd image, so this doesn't
+match the usual semantic of struct resource.  The chosen node may also
+optionally contain an arbitrary number of additional properties for
+platform-specific configuration data.
 
 During early boot, the architecture setup code calls of_scan_flat_dt()
 several times with different helper callbacks to parse device tree
index 279ac0a..132a094 100644 (file)
@@ -34,7 +34,7 @@ command:
 After a while you will start to get messages about current status or error like
 in the original code.
 
-Note that running a new test will stop any in progress test.
+Note that running a new test will not stop any in progress test.
 
 The following command should return actual state of the test.
        % cat /sys/kernel/debug/dmatest/run
@@ -52,8 +52,8 @@ To wait for test done the user may perform a busy loop that checks the state.
 
 The module parameters that is supplied to the kernel command line will be used
 for the first performed test. After user gets a control, the test could be
-interrupted or re-run with same or different parameters. For the details see
-the above section "Part 2 - When dmatest is built as a module..."
+re-run with the same or different parameters. For the details see the above
+section "Part 2 - When dmatest is built as a module..."
 
 In both cases the module parameters are used as initial values for the test case.
 You always could check them at run-time by running
index 3e4b3dd..83577f0 100644 (file)
@@ -33,6 +33,9 @@ When mounting an XFS filesystem, the following options are accepted.
        removing extended attributes) the on-disk superblock feature
        bit field will be updated to reflect this format being in use.
 
+       CRC enabled filesystems always use the attr2 format, and so
+       will reject the noattr2 mount option if it is set.
+
   barrier
        Enables the use of block layer write barriers for writes into
        the journal and unwritten extent conversion.  This allows for
index c3bfacb..2fe6e76 100644 (file)
@@ -3005,6 +3005,27 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        Force threading of all interrupt handlers except those
                        marked explicitly IRQF_NO_THREAD.
 
+       tmem            [KNL,XEN]
+                       Enable the Transcendent memory driver if built-in.
+
+       tmem.cleancache=0|1 [KNL, XEN]
+                       Default is on (1). Disable the usage of the cleancache
+                       API to send anonymous pages to the hypervisor.
+
+       tmem.frontswap=0|1 [KNL, XEN]
+                       Default is on (1). Disable the usage of the frontswap
+                       API to send swap pages to the hypervisor. If disabled
+                       the selfballooning and selfshrinking are force disabled.
+
+       tmem.selfballooning=0|1 [KNL, XEN]
+                       Default is on (1). Disable the driving of swap pages
+                       to the hypervisor.
+
+       tmem.selfshrinking=0|1 [KNL, XEN]
+                       Default is on (1). Partial swapoff that immediately
+                       transfers pages from Xen hypervisor back to the
+                       kernel based on different criteria.
+
        topology=       [S390]
                        Format: {off | on}
                        Specify if the kernel should make use of the cpu
@@ -3330,9 +3351,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        plus one apbt timer for broadcast timer.
                        x86_mrst_timer=apbt_only | lapic_and_apbt
 
-       xd=             [HW,XT] Original XT pre-IDE (RLL encoded) disks.
-       xd_geo=         See header of drivers/block/xd.c.
-
        xen_emul_unplug=                [HW,X86,XEN]
                        Unplug Xen emulated devices
                        Format: [unplug0,][unplug1]
diff --git a/Documentation/kernel-per-CPU-kthreads.txt b/Documentation/kernel-per-CPU-kthreads.txt
new file mode 100644 (file)
index 0000000..cbf7ae4
--- /dev/null
@@ -0,0 +1,202 @@
+REDUCING OS JITTER DUE TO PER-CPU KTHREADS
+
+This document lists per-CPU kthreads in the Linux kernel and presents
+options to control their OS jitter.  Note that non-per-CPU kthreads are
+not listed here.  To reduce OS jitter from non-per-CPU kthreads, bind
+them to a "housekeeping" CPU dedicated to such work.
+
+
+REFERENCES
+
+o      Documentation/IRQ-affinity.txt:  Binding interrupts to sets of CPUs.
+
+o      Documentation/cgroups:  Using cgroups to bind tasks to sets of CPUs.
+
+o      man taskset:  Using the taskset command to bind tasks to sets
+       of CPUs.
+
+o      man sched_setaffinity:  Using the sched_setaffinity() system
+       call to bind tasks to sets of CPUs.
+
+o      /sys/devices/system/cpu/cpuN/online:  Control CPU N's hotplug state,
+       writing "0" to offline and "1" to online.
+
+o      In order to locate kernel-generated OS jitter on CPU N:
+
+               cd /sys/kernel/debug/tracing
+               echo 1 > max_graph_depth # Increase the "1" for more detail
+               echo function_graph > current_tracer
+               # run workload
+               cat per_cpu/cpuN/trace
+
+
+KTHREADS
+
+Name: ehca_comp/%u
+Purpose: Periodically process Infiniband-related work.
+To reduce its OS jitter, do any of the following:
+1.     Don't use eHCA Infiniband hardware, instead choosing hardware
+       that does not require per-CPU kthreads.  This will prevent these
+       kthreads from being created in the first place.  (This will
+       work for most people, as this hardware, though important, is
+       relatively old and is produced in relatively low unit volumes.)
+2.     Do all eHCA-Infiniband-related work on other CPUs, including
+       interrupts.
+3.     Rework the eHCA driver so that its per-CPU kthreads are
+       provisioned only on selected CPUs.
+
+
+Name: irq/%d-%s
+Purpose: Handle threaded interrupts.
+To reduce its OS jitter, do the following:
+1.     Use irq affinity to force the irq threads to execute on
+       some other CPU.
+
+Name: kcmtpd_ctr_%d
+Purpose: Handle Bluetooth work.
+To reduce its OS jitter, do one of the following:
+1.     Don't use Bluetooth, in which case these kthreads won't be
+       created in the first place.
+2.     Use irq affinity to force Bluetooth-related interrupts to
+       occur on some other CPU and furthermore initiate all
+       Bluetooth activity on some other CPU.
+
+Name: ksoftirqd/%u
+Purpose: Execute softirq handlers when threaded or when under heavy load.
+To reduce its OS jitter, each softirq vector must be handled
+separately as follows:
+TIMER_SOFTIRQ:  Do all of the following:
+1.     To the extent possible, keep the CPU out of the kernel when it
+       is non-idle, for example, by avoiding system calls and by forcing
+       both kernel threads and interrupts to execute elsewhere.
+2.     Build with CONFIG_HOTPLUG_CPU=y.  After boot completes, force
+       the CPU offline, then bring it back online.  This forces
+       recurring timers to migrate elsewhere.  If you are concerned
+       with multiple CPUs, force them all offline before bringing the
+       first one back online.  Once you have onlined the CPUs in question,
+       do not offline any other CPUs, because doing so could force the
+       timer back onto one of the CPUs in question.
+NET_TX_SOFTIRQ and NET_RX_SOFTIRQ:  Do all of the following:
+1.     Force networking interrupts onto other CPUs.
+2.     Initiate any network I/O on other CPUs.
+3.     Once your application has started, prevent CPU-hotplug operations
+       from being initiated from tasks that might run on the CPU to
+       be de-jittered.  (It is OK to force this CPU offline and then
+       bring it back online before you start your application.)
+BLOCK_SOFTIRQ:  Do all of the following:
+1.     Force block-device interrupts onto some other CPU.
+2.     Initiate any block I/O on other CPUs.
+3.     Once your application has started, prevent CPU-hotplug operations
+       from being initiated from tasks that might run on the CPU to
+       be de-jittered.  (It is OK to force this CPU offline and then
+       bring it back online before you start your application.)
+BLOCK_IOPOLL_SOFTIRQ:  Do all of the following:
+1.     Force block-device interrupts onto some other CPU.
+2.     Initiate any block I/O and block-I/O polling on other CPUs.
+3.     Once your application has started, prevent CPU-hotplug operations
+       from being initiated from tasks that might run on the CPU to
+       be de-jittered.  (It is OK to force this CPU offline and then
+       bring it back online before you start your application.)
+TASKLET_SOFTIRQ: Do one or more of the following:
+1.     Avoid use of drivers that use tasklets.  (Such drivers will contain
+       calls to things like tasklet_schedule().)
+2.     Convert all drivers that you must use from tasklets to workqueues.
+3.     Force interrupts for drivers using tasklets onto other CPUs,
+       and also do I/O involving these drivers on other CPUs.
+SCHED_SOFTIRQ: Do all of the following:
+1.     Avoid sending scheduler IPIs to the CPU to be de-jittered,
+       for example, ensure that at most one runnable kthread is present
+       on that CPU.  If a thread that expects to run on the de-jittered
+       CPU awakens, the scheduler will send an IPI that can result in
+       a subsequent SCHED_SOFTIRQ.
+2.     Build with CONFIG_RCU_NOCB_CPU=y, CONFIG_RCU_NOCB_CPU_ALL=y,
+       CONFIG_NO_HZ_FULL=y, and, in addition, ensure that the CPU
+       to be de-jittered is marked as an adaptive-ticks CPU using the
+       "nohz_full=" boot parameter.  This reduces the number of
+       scheduler-clock interrupts that the de-jittered CPU receives,
+       minimizing its chances of being selected to do the load balancing
+       work that runs in SCHED_SOFTIRQ context.
+3.     To the extent possible, keep the CPU out of the kernel when it
+       is non-idle, for example, by avoiding system calls and by
+       forcing both kernel threads and interrupts to execute elsewhere.
+       This further reduces the number of scheduler-clock interrupts
+       received by the de-jittered CPU.
+HRTIMER_SOFTIRQ:  Do all of the following:
+1.     To the extent possible, keep the CPU out of the kernel when it
+       is non-idle.  For example, avoid system calls and force both
+       kernel threads and interrupts to execute elsewhere.
+2.     Build with CONFIG_HOTPLUG_CPU=y.  Once boot completes, force the
+       CPU offline, then bring it back online.  This forces recurring
+       timers to migrate elsewhere.  If you are concerned with multiple
+       CPUs, force them all offline before bringing the first one
+       back online.  Once you have onlined the CPUs in question, do not
+       offline any other CPUs, because doing so could force the timer
+       back onto one of the CPUs in question.
+RCU_SOFTIRQ:  Do at least one of the following:
+1.     Offload callbacks and keep the CPU in either dyntick-idle or
+       adaptive-ticks state by doing all of the following:
+       a.      Build with CONFIG_RCU_NOCB_CPU=y, CONFIG_RCU_NOCB_CPU_ALL=y,
+               CONFIG_NO_HZ_FULL=y, and, in addition ensure that the CPU
+               to be de-jittered is marked as an adaptive-ticks CPU using
+               the "nohz_full=" boot parameter.  Bind the rcuo kthreads
+               to housekeeping CPUs, which can tolerate OS jitter.
+       b.      To the extent possible, keep the CPU out of the kernel
+               when it is non-idle, for example, by avoiding system
+               calls and by forcing both kernel threads and interrupts
+               to execute elsewhere.
+2.     Enable RCU to do its processing remotely via dyntick-idle by
+       doing all of the following:
+       a.      Build with CONFIG_NO_HZ=y and CONFIG_RCU_FAST_NO_HZ=y.
+       b.      Ensure that the CPU goes idle frequently, allowing other
+               CPUs to detect that it has passed through an RCU quiescent
+               state.  If the kernel is built with CONFIG_NO_HZ_FULL=y,
+               userspace execution also allows other CPUs to detect that
+               the CPU in question has passed through a quiescent state.
+       c.      To the extent possible, keep the CPU out of the kernel
+               when it is non-idle, for example, by avoiding system
+               calls and by forcing both kernel threads and interrupts
+               to execute elsewhere.
+
+Name: rcuc/%u
+Purpose: Execute RCU callbacks in CONFIG_RCU_BOOST=y kernels.
+To reduce its OS jitter, do at least one of the following:
+1.     Build the kernel with CONFIG_PREEMPT=n.  This prevents these
+       kthreads from being created in the first place, and also obviates
+       the need for RCU priority boosting.  This approach is feasible
+       for workloads that do not require high degrees of responsiveness.
+2.     Build the kernel with CONFIG_RCU_BOOST=n.  This prevents these
+       kthreads from being created in the first place.  This approach
+       is feasible only if your workload never requires RCU priority
+       boosting, for example, if you ensure frequent idle time on all
+       CPUs that might execute within the kernel.
+3.     Build with CONFIG_RCU_NOCB_CPU=y and CONFIG_RCU_NOCB_CPU_ALL=y,
+       which offloads all RCU callbacks to kthreads that can be moved
+       off of CPUs susceptible to OS jitter.  This approach prevents the
+       rcuc/%u kthreads from having any work to do, so that they are
+       never awakened.
+4.     Ensure that the CPU never enters the kernel, and, in particular,
+       avoid initiating any CPU hotplug operations on this CPU.  This is
+       another way of preventing any callbacks from being queued on the
+       CPU, again preventing the rcuc/%u kthreads from having any work
+       to do.
+
+Name: rcuob/%d, rcuop/%d, and rcuos/%d
+Purpose: Offload RCU callbacks from the corresponding CPU.
+To reduce its OS jitter, do at least one of the following:
+1.     Use affinity, cgroups, or other mechanism to force these kthreads
+       to execute on some other CPU.
+2.     Build with CONFIG_RCU_NOCB_CPUS=n, which will prevent these
+       kthreads from being created in the first place.  However, please
+       note that this will not eliminate OS jitter, but will instead
+       shift it to RCU_SOFTIRQ.
+
+Name: watchdog/%u
+Purpose: Detect software lockups on each CPU.
+To reduce its OS jitter, do at least one of the following:
+1.     Build with CONFIG_LOCKUP_DETECTOR=n, which will prevent these
+       kthreads from being created in the first place.
+2.     Echo a zero to /proc/sys/kernel/watchdog to disable the
+       watchdog timer.
+3.     Echo a large number of /proc/sys/kernel/watchdog_thresh in
+       order to reduce the frequency of OS jitter due to the watchdog
+       timer down to a level that is acceptable for your workload.
index 97d45f2..eaf32a1 100644 (file)
@@ -80,8 +80,6 @@ Valid names are:
   /dev/sdd: -> 0x0830 (forth SCSI disk)
   /dev/sde: -> 0x0840 (fifth SCSI disk)
   /dev/fd : -> 0x0200 (floppy disk)
-  /dev/xda: -> 0x0c00 (first XT disk, unused in Linux/m68k)
-  /dev/xdb: -> 0x0c40 (second XT disk, unused in Linux/m68k)
 
   The name must be followed by a decimal number, that stands for the
 partition number. Internally, the value of the number is just
index 504dfe4..a66c982 100644 (file)
@@ -268,7 +268,7 @@ situations.
 System Power Management Phases
 ------------------------------
 Suspending or resuming the system is done in several phases.  Different phases
-are used for standby or memory sleep states ("suspend-to-RAM") and the
+are used for freeze, standby, and memory sleep states ("suspend-to-RAM") and the
 hibernation state ("suspend-to-disk").  Each phase involves executing callbacks
 for every device before the next phase begins.  Not all busses or classes
 support all these callbacks and not all drivers use all the callbacks.  The
@@ -309,7 +309,8 @@ execute the corresponding method from dev->driver->pm instead if there is one.
 
 Entering System Suspend
 -----------------------
-When the system goes into the standby or memory sleep state, the phases are:
+When the system goes into the freeze, standby or memory sleep state,
+the phases are:
 
                prepare, suspend, suspend_late, suspend_noirq.
 
@@ -368,7 +369,7 @@ the devices that were suspended.
 
 Leaving System Suspend
 ----------------------
-When resuming from standby or memory sleep, the phases are:
+When resuming from freeze, standby or memory sleep, the phases are:
 
                resume_noirq, resume_early, resume, complete.
 
@@ -433,8 +434,8 @@ the system log.
 
 Entering Hibernation
 --------------------
-Hibernating the system is more complicated than putting it into the standby or
-memory sleep state, because it involves creating and saving a system image.
+Hibernating the system is more complicated than putting it into the other
+sleep states, because it involves creating and saving a system image.
 Therefore there are more phases for hibernation, with a different set of
 callbacks.  These phases always run after tasks have been frozen and memory has
 been freed.
@@ -485,8 +486,8 @@ image forms an atomic snapshot of the system state.
 
 At this point the system image is saved, and the devices then need to be
 prepared for the upcoming system shutdown.  This is much like suspending them
-before putting the system into the standby or memory sleep state, and the phases
-are similar.
+before putting the system into the freeze, standby or memory sleep state,
+and the phases are similar.
 
     9. The prepare phase is discussed above.
 
index c537834..f1f0f59 100644 (file)
@@ -7,8 +7,8 @@ running. The interface exists in /sys/power/ directory (assuming sysfs
 is mounted at /sys). 
 
 /sys/power/state controls system power state. Reading from this file
-returns what states are supported, which is hard-coded to 'standby'
-(Power-On Suspend), 'mem' (Suspend-to-RAM), and 'disk'
+returns what states are supported, which is hard-coded to 'freeze',
+'standby' (Power-On Suspend), 'mem' (Suspend-to-RAM), and 'disk'
 (Suspend-to-Disk). 
 
 Writing to this file one of those strings causes the system to
index c2a4a34..a81fa25 100644 (file)
@@ -15,8 +15,10 @@ A suspend/hibernation notifier may be used for this purpose.
 The subsystems or drivers having such needs can register suspend notifiers that
 will be called upon the following events by the PM core:
 
-PM_HIBERNATION_PREPARE The system is going to hibernate or suspend, tasks will
-                       be frozen immediately.
+PM_HIBERNATION_PREPARE The system is going to hibernate, tasks will be frozen
+                       immediately. This is different from PM_SUSPEND_PREPARE
+                       below because here we do additional work between notifiers
+                       and drivers freezing.
 
 PM_POST_HIBERNATION    The system memory state has been restored from a
                        hibernation image or an error occurred during
index 4416b28..442d43d 100644 (file)
@@ -2,12 +2,26 @@
 System Power Management States
 
 
-The kernel supports three power management states generically, though
-each is dependent on platform support code to implement the low-level
-details for each state. This file describes each state, what they are
+The kernel supports four power management states generically, though
+one is generic and the other three are dependent on platform support
+code to implement the low-level details for each state.
+This file describes each state, what they are
 commonly called, what ACPI state they map to, and what string to write
 to /sys/power/state to enter that state
 
+state:         Freeze / Low-Power Idle
+ACPI state:    S0
+String:                "freeze"
+
+This state is a generic, pure software, light-weight, low-power state.
+It allows more energy to be saved relative to idle by freezing user
+space and putting all I/O devices into low-power states (possibly
+lower-power than available at run time), such that the processors can
+spend more time in their idle states.
+This state can be used for platforms without Standby/Suspend-to-RAM
+support, or it can be used in addition to Suspend-to-RAM (memory sleep)
+to provide reduced resume latency.
+
 
 State:         Standby / Power-On Suspend
 ACPI State:    S1
@@ -22,9 +36,6 @@ We try to put devices in a low-power state equivalent to D1, which
 also offers low power savings, but low resume latency. Not all devices
 support D1, and those that don't are left on. 
 
-A transition from Standby to the On state should take about 1-2
-seconds. 
-
 
 State:         Suspend-to-RAM
 ACPI State:    S3
@@ -42,9 +53,6 @@ transition back to the On state.
 For at least ACPI, STR requires some minimal boot-strapping code to
 resume the system from STR. This may be true on other platforms. 
 
-A transition from Suspend-to-RAM to the On state should take about
-3-5 seconds. 
-
 
 State:         Suspend-to-disk
 ACPI State:    S4
@@ -74,7 +82,3 @@ low-power state (like ACPI S4), or it may simply power down. Powering
 down offers greater savings, and allows this mechanism to work on any
 system. However, entering a real low-power state allows the user to
 trigger wake up events (e.g. pressing a key or opening a laptop lid).
-
-A transition from Suspend-to-Disk to the On state should take about 30
-seconds, though it's typically a bit more with the current
-implementation. 
index c907be4..dc23e58 100644 (file)
@@ -147,6 +147,25 @@ Example signal handler:
       fix_the_problem(ucp->dar);
     }
 
+When in an active transaction that takes a signal, we need to be careful with
+the stack.  It's possible that the stack has moved back up after the tbegin.
+The obvious case here is when the tbegin is called inside a function that
+returns before a tend.  In this case, the stack is part of the checkpointed
+transactional memory state.  If we write over this non transactionally or in
+suspend, we are in trouble because if we get a tm abort, the program counter and
+stack pointer will be back at the tbegin but our in memory stack won't be valid
+anymore.
+
+To avoid this, when taking a signal in an active transaction, we need to use
+the stack pointer from the checkpointed state, rather than the speculated
+state.  This ensures that the signal context (written tm suspended) will be
+written below the stack required for the rollback.  The transaction is aborted
+becuase of the treclaim, so any memory written between the tbegin and the
+signal will be rolled back anyway.
+
+For signals taken in non-TM or suspended mode, we use the
+normal/non-checkpointed stack pointer.
+
 
 Failure cause codes used by kernel
 ==================================
@@ -155,14 +174,18 @@ These are defined in <asm/reg.h>, and distinguish different reasons why the
 kernel aborted a transaction:
 
  TM_CAUSE_RESCHED       Thread was rescheduled.
+ TM_CAUSE_TLBI          Software TLB invalide.
  TM_CAUSE_FAC_UNAV      FP/VEC/VSX unavailable trap.
  TM_CAUSE_SYSCALL       Currently unused; future syscalls that must abort
                         transactions for consistency will use this.
  TM_CAUSE_SIGNAL        Signal delivered.
  TM_CAUSE_MISC          Currently unused.
+ TM_CAUSE_ALIGNMENT     Alignment fault.
+ TM_CAUSE_EMULATE       Emulation that touched memory.
 
-These can be checked by the user program's abort handler as TEXASR[0:7].
-
+These can be checked by the user program's abort handler as TEXASR[0:7].  If
+bit 7 is set, it indicates that the error is consider persistent.  For example
+a TM_CAUSE_ALIGNMENT will be persistent while a TM_CAUSE_RESCHED will not.q
 
 GDB
 ===
index c75694b..a9c16c9 100644 (file)
@@ -79,20 +79,63 @@ master port that is used to communicate with devices within the network.
 In order to initialize the RapidIO subsystem, a platform must initialize and
 register at least one master port within the RapidIO network. To register mport
 within the subsystem controller driver initialization code calls function
-rio_register_mport() for each available master port. After all active master
-ports are registered with a RapidIO subsystem, the rio_init_mports() routine
-is called to perform enumeration and discovery.
+rio_register_mport() for each available master port.
 
-In the current PowerPC-based implementation a subsys_initcall() is specified to
-perform controller initialization and mport registration. At the end it directly
-calls rio_init_mports() to execute RapidIO enumeration and discovery.
+RapidIO subsystem uses subsys_initcall() or device_initcall() to perform
+controller initialization (depending on controller device type).
+
+After all active master ports are registered with a RapidIO subsystem,
+an enumeration and/or discovery routine may be called automatically or
+by user-space command.
 
 4. Enumeration and Discovery
 ----------------------------
 
-When rio_init_mports() is called it scans a list of registered master ports and
-calls an enumeration or discovery routine depending on the configured role of a
-master port: host or agent.
+4.1 Overview
+------------
+
+RapidIO subsystem configuration options allow users to specify enumeration and
+discovery methods as statically linked components or loadable modules.
+An enumeration/discovery method implementation and available input parameters
+define how any given method can be attached to available RapidIO mports:
+simply to all available mports OR individually to the specified mport device.
+
+Depending on selected enumeration/discovery build configuration, there are
+several methods to initiate an enumeration and/or discovery process:
+
+  (a) Statically linked enumeration and discovery process can be started
+  automatically during kernel initialization time using corresponding module
+  parameters. This was the original method used since introduction of RapidIO
+  subsystem. Now this method relies on enumerator module parameter which is
+  'rio-scan.scan' for existing basic enumeration/discovery method.
+  When automatic start of enumeration/discovery is used a user has to ensure
+  that all discovering endpoints are started before the enumerating endpoint
+  and are waiting for enumeration to be completed.
+  Configuration option CONFIG_RAPIDIO_DISC_TIMEOUT defines time that discovering
+  endpoint waits for enumeration to be completed. If the specified timeout
+  expires the discovery process is terminated without obtaining RapidIO network
+  information. NOTE: a timed out discovery process may be restarted later using
+  a user-space command as it is described later if the given endpoint was
+  enumerated successfully.
+
+  (b) Statically linked enumeration and discovery process can be started by
+  a command from user space. This initiation method provides more flexibility
+  for a system startup compared to the option (a) above. After all participating
+  endpoints have been successfully booted, an enumeration process shall be
+  started first by issuing a user-space command, after an enumeration is
+  completed a discovery process can be started on all remaining endpoints.
+
+  (c) Modular enumeration and discovery process can be started by a command from
+  user space. After an enumeration/discovery module is loaded, a network scan
+  process can be started by issuing a user-space command.
+  Similar to the option (b) above, an enumerator has to be started first.
+
+  (d) Modular enumeration and discovery process can be started by a module
+  initialization routine. In this case an enumerating module shall be loaded
+  first.
+
+When a network scan process is started it calls an enumeration or discovery
+routine depending on the configured role of a master port: host or agent.
 
 Enumeration is performed by a master port if it is configured as a host port by
 assigning a host device ID greater than or equal to zero. A host device ID is
@@ -104,8 +147,58 @@ for it.
 The enumeration and discovery routines use RapidIO maintenance transactions
 to access the configuration space of devices.
 
-The enumeration process is implemented according to the enumeration algorithm
-outlined in the RapidIO Interconnect Specification: Annex I [1].
+4.2 Automatic Start of Enumeration and Discovery
+------------------------------------------------
+
+Automatic enumeration/discovery start method is applicable only to built-in
+enumeration/discovery RapidIO configuration selection. To enable automatic
+enumeration/discovery start by existing basic enumerator method set use boot
+command line parameter "rio-scan.scan=1".
+
+This configuration requires synchronized start of all RapidIO endpoints that
+form a network which will be enumerated/discovered. Discovering endpoints have
+to be started before an enumeration starts to ensure that all RapidIO
+controllers have been initialized and are ready to be discovered. Configuration
+parameter CONFIG_RAPIDIO_DISC_TIMEOUT defines time (in seconds) which
+a discovering endpoint will wait for enumeration to be completed.
+
+When automatic enumeration/discovery start is selected, basic method's
+initialization routine calls rio_init_mports() to perform enumeration or
+discovery for all known mport devices.
+
+Depending on RapidIO network size and configuration this automatic
+enumeration/discovery start method may be difficult to use due to the
+requirement for synchronized start of all endpoints.
+
+4.3 User-space Start of Enumeration and Discovery
+-------------------------------------------------
+
+User-space start of enumeration and discovery can be used with built-in and
+modular build configurations. For user-space controlled start RapidIO subsystem
+creates the sysfs write-only attribute file '/sys/bus/rapidio/scan'. To initiate
+an enumeration or discovery process on specific mport device, a user needs to
+write mport_ID (not RapidIO destination ID) into that file. The mport_ID is a
+sequential number (0 ... RIO_MAX_MPORTS) assigned during mport device
+registration. For example for machine with single RapidIO controller, mport_ID
+for that controller always will be 0.
+
+To initiate RapidIO enumeration/discovery on all available mports a user may
+write '-1' (or RIO_MPORT_ANY) into the scan attribute file.
+
+4.4 Basic Enumeration Method
+----------------------------
+
+This is an original enumeration/discovery method which is available since
+first release of RapidIO subsystem code. The enumeration process is
+implemented according to the enumeration algorithm outlined in the RapidIO
+Interconnect Specification: Annex I [1].
+
+This method can be configured as statically linked or loadable module.
+The method's single parameter "scan" allows to trigger the enumeration/discovery
+process from module initialization routine.
+
+This enumeration/discovery method can be started only once and does not support
+unloading if it is built as a module.
 
 The enumeration process traverses the network using a recursive depth-first
 algorithm. When a new device is found, the enumerator takes ownership of that
@@ -160,6 +253,19 @@ time period. If this wait time period expires before enumeration is completed,
 an agent skips RapidIO discovery and continues with remaining kernel
 initialization.
 
+4.5 Adding New Enumeration/Discovery Method
+-------------------------------------------
+
+RapidIO subsystem code organization allows addition of new enumeration/discovery
+methods as new configuration options without significant impact to to the core
+RapidIO code.
+
+A new enumeration/discovery method has to be attached to one or more mport
+devices before an enumeration/discovery process can be started. Normally,
+method's module initialization routine calls rio_register_scan() to attach
+an enumerator to a specified mport device (or devices). The basic enumerator
+implementation demonstrates this process.
+
 5. References
 -------------
 
index 97f71ce..1987817 100644 (file)
@@ -88,3 +88,20 @@ that exports additional attributes.
 
 IDT_GEN2:
  errlog - reads contents of device error log until it is empty.
+
+
+5. RapidIO Bus Attributes
+-------------------------
+
+RapidIO bus subdirectory /sys/bus/rapidio implements the following bus-specific
+attribute:
+
+  scan - allows to trigger enumeration discovery process from user space. This
+        is a write-only attribute. To initiate an enumeration or discovery
+        process on specific mport device, a user needs to write mport_ID (not
+        RapidIO destination ID) into this file. The mport_ID is a sequential
+        number (0 ... RIO_MAX_MPORTS) assigned to the mport device.
+        For example, for a machine with a single RapidIO controller, mport_ID
+        for that controller always will be 0.
+        To initiate RapidIO enumeration/discovery on all available mports
+        a user must write '-1' (or RIO_MPORT_ANY) into this attribute file.
index 3d7782b..0c9dc71 100644 (file)
@@ -2890,8 +2890,8 @@ F:        drivers/media/dvb-frontends/ec100*
 
 ECRYPT FILE SYSTEM
 M:     Tyler Hicks <tyhicks@canonical.com>
-M:     Dustin Kirkland <dustin.kirkland@gazzang.com>
 L:     ecryptfs@vger.kernel.org
+W:     http://ecryptfs.org
 W:     https://launchpad.net/ecryptfs
 S:     Supported
 F:     Documentation/filesystems/ecryptfs.txt
@@ -3322,11 +3322,12 @@ F:      drivers/net/wan/dlci.c
 F:     drivers/net/wan/sdla.c
 
 FRAMEBUFFER LAYER
-M:     Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
+M:     Jean-Christophe Plagniol-Villard <plagnioj@jcrosoft.com>
+M:     Tomi Valkeinen <tomi.valkeinen@ti.com>
 L:     linux-fbdev@vger.kernel.org
 W:     http://linux-fbdev.sourceforge.net/
 Q:     http://patchwork.kernel.org/project/linux-fbdev/list/
-T:     git git://github.com/schandinat/linux-2.6.git fbdev-next
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/plagnioj/linux-fbdev.git
 S:     Maintained
 F:     Documentation/fb/
 F:     Documentation/devicetree/bindings/fb/
@@ -3865,9 +3866,16 @@ M:       K. Y. Srinivasan <kys@microsoft.com>
 M:     Haiyang Zhang <haiyangz@microsoft.com>
 L:     devel@linuxdriverproject.org
 S:     Maintained
-F:     drivers/hv/
+F:     arch/x86/include/asm/mshyperv.h
+F:     arch/x86/include/uapi/asm/hyperv.h
+F:     arch/x86/kernel/cpu/mshyperv.c
 F:     drivers/hid/hid-hyperv.c
+F:     drivers/hv/
 F:     drivers/net/hyperv/
+F:     drivers/scsi/storvsc_drv.c
+F:     drivers/video/hyperv_fb.c
+F:     include/linux/hyperv.h
+F:     tools/hv/
 
 I2C OVER PARALLEL PORT
 M:     Jean Delvare <khali@linux-fr.org>
@@ -4440,6 +4448,16 @@ S:       Maintained
 F:     drivers/scsi/*iscsi*
 F:     include/scsi/*iscsi*
 
+ISCSI EXTENSIONS FOR RDMA (ISER) INITIATOR
+M:     Or Gerlitz <ogerlitz@mellanox.com>
+M:     Roi Dayan <roid@mellanox.com>
+L:     linux-rdma@vger.kernel.org
+S:     Supported
+W:     http://www.openfabrics.org
+W:     www.open-iscsi.org
+Q:     http://patchwork.kernel.org/project/linux-rdma/list/
+F:     drivers/infiniband/ulp/iser
+
 ISDN SUBSYSTEM
 M:     Karsten Keil <isdn@linux-pingi.de>
 L:     isdn4linux@listserv.isdn4linux.de (subscribers-only)
@@ -4641,12 +4659,13 @@ F:      include/linux/sunrpc/
 F:     include/uapi/linux/sunrpc/
 
 KERNEL VIRTUAL MACHINE (KVM)
-M:     Marcelo Tosatti <mtosatti@redhat.com>
 M:     Gleb Natapov <gleb@redhat.com>
+M:     Paolo Bonzini <pbonzini@redhat.com>
 L:     kvm@vger.kernel.org
-W:     http://kvm.qumranet.com
+W:     http://linux-kvm.org
 S:     Supported
-F:     Documentation/*/kvm.txt
+F:     Documentation/*/kvm*.txt
+F:     Documentation/virtual/kvm/
 F:     arch/*/kvm/
 F:     arch/*/include/asm/kvm*
 F:     include/linux/kvm*
@@ -4976,6 +4995,13 @@ S:       Maintained
 F:     Documentation/hwmon/lm90
 F:     drivers/hwmon/lm90.c
 
+LM95234 HARDWARE MONITOR DRIVER
+M:     Guenter Roeck <linux@roeck-us.net>
+L:     lm-sensors@lm-sensors.org
+S:     Maintained
+F:     Documentation/hwmon/lm95234
+F:     drivers/hwmon/lm95234.c
+
 LME2510 MEDIA DRIVER
 M:     Malcolm Priestley <tvboxspy@gmail.com>
 L:     linux-media@vger.kernel.org
@@ -5509,18 +5535,18 @@ F:      Documentation/networking/s2io.txt
 F:     Documentation/networking/vxge.txt
 F:     drivers/net/ethernet/neterion/
 
-NETFILTER/IPTABLES/IPCHAINS
-P:     Harald Welte
-P:     Jozsef Kadlecsik
+NETFILTER/IPTABLES
 M:     Pablo Neira Ayuso <pablo@netfilter.org>
 M:     Patrick McHardy <kaber@trash.net>
+M:     Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
 L:     netfilter-devel@vger.kernel.org
 L:     netfilter@vger.kernel.org
 L:     coreteam@netfilter.org
 W:     http://www.netfilter.org/
 W:     http://www.iptables.org/
-T:     git git://1984.lsi.us.es/nf
-T:     git git://1984.lsi.us.es/nf-next
+Q:     http://patchwork.ozlabs.org/project/netfilter-devel/list/
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next.git
 S:     Supported
 F:     include/linux/netfilter*
 F:     include/linux/netfilter/
@@ -5740,7 +5766,7 @@ M:        Matthew Wilcox <willy@linux.intel.com>
 L:     linux-nvme@lists.infradead.org
 T:     git git://git.infradead.org/users/willy/linux-nvme.git
 S:     Supported
-F:     drivers/block/nvme.c
+F:     drivers/block/nvme*
 F:     include/linux/nvme.h
 
 OMAP SUPPORT
@@ -6069,9 +6095,18 @@ L:       linux-parisc@vger.kernel.org
 W:     http://www.parisc-linux.org/
 Q:     http://patchwork.kernel.org/project/linux-parisc/list/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/jejb/parisc-2.6.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux.git
 S:     Maintained
 F:     arch/parisc/
+F:     Documentation/parisc/
 F:     drivers/parisc/
+F:     drivers/char/agp/parisc-agp.c
+F:     drivers/input/serio/gscps2.c
+F:     drivers/parport/parport_gsc.*
+F:     drivers/tty/serial/8250/8250_gsc.c
+F:     drivers/video/sti*
+F:     drivers/video/console/sti*
+F:     drivers/video/logo/logo_parisc*
 
 PC87360 HARDWARE MONITORING DRIVER
 M:     Jim Cromie <jim.cromie@gmail.com>
@@ -7589,7 +7624,7 @@ F:        drivers/clk/spear/
 SPI SUBSYSTEM
 M:     Mark Brown <broonie@kernel.org>
 M:     Grant Likely <grant.likely@linaro.org>
-L:     spi-devel-general@lists.sourceforge.net
+L:     linux-spi@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git
 Q:     http://patchwork.kernel.org/project/spi-devel-general/list/
 S:     Maintained
@@ -7854,7 +7889,7 @@ L:        linux-scsi@vger.kernel.org
 L:     target-devel@vger.kernel.org
 L:     http://groups.google.com/group/linux-iscsi-target-dev
 W:     http://www.linux-iscsi.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/nab/lio-core.git master
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending.git master
 S:     Supported
 F:     drivers/target/
 F:     include/target/
@@ -8182,6 +8217,13 @@ F:       drivers/mmc/host/sh_mobile_sdhi.c
 F:     include/linux/mmc/tmio.h
 F:     include/linux/mmc/sh_mobile_sdhi.h
 
+TMP401 HARDWARE MONITOR DRIVER
+M:     Guenter Roeck <linux@roeck-us.net>
+L:     lm-sensors@lm-sensors.org
+S:     Maintained
+F:     Documentation/hwmon/tmp401
+F:     drivers/hwmon/tmp401.c
+
 TMPFS (SHMEM FILESYSTEM)
 M:     Hugh Dickins <hughd@google.com>
 L:     linux-mm@kvack.org
index a3a834b..9040016 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 3
-PATCHLEVEL = 9
+PATCHLEVEL = 10
 SUBLEVEL = 0
-EXTRAVERSION =
+EXTRAVERSION = -rc5
 NAME = Unicycling Gorilla
 
 # *DOCUMENTATION*
index dd0e8eb..a4429bc 100644 (file)
@@ -213,6 +213,9 @@ config USE_GENERIC_SMP_HELPERS
 config GENERIC_SMP_IDLE_THREAD
        bool
 
+config GENERIC_IDLE_POLL_SETUP
+       bool
+
 # Select if arch init_task initializer is different to init/init_task.c
 config ARCH_INIT_TASK
        bool
index c0fd362..0fa0d4a 100644 (file)
@@ -37,7 +37,7 @@
 
        soc100 {
                uart@FF100000 {
-                       pinctrl-names = "abilis,simple-default";
+                       pinctrl-names = "default";
                        pinctrl-0 = <&pctl_uart0>;
                };
                ethernet@FE100000 {
index 6f8c381..a4d80ce 100644 (file)
@@ -37,7 +37,7 @@
 
        soc100 {
                uart@FF100000 {
-                       pinctrl-names = "abilis,simple-default";
+                       pinctrl-names = "default";
                        pinctrl-0 = <&pctl_uart0>;
                };
                ethernet@FE100000 {
index a6139fc..b97e305 100644 (file)
@@ -88,8 +88,7 @@
                };
 
                uart@FF100000 {
-                       compatible = "snps,dw-apb-uart",
-                                       "abilis,simple-pinctrl";
+                       compatible = "snps,dw-apb-uart";
                        reg = <0xFF100000 0x100>;
                        clock-frequency = <166666666>;
                        interrupts = <25 1>;
                        #address-cells = <1>;
                        #size-cells = <0>;
                        cell-index = <1>;
-                       compatible = "abilis,tb100-spi",
-                                       "abilis,simple-pinctrl";
+                       compatible = "abilis,tb100-spi";
                        num-cs = <2>;
                        reg = <0xFE011000 0x20>;
                        interrupt-parent = <&tb10x_ictl>;
index 9f841af..ef62682 100644 (file)
@@ -93,14 +93,16 @@ static inline int cache_is_vipt_aliasing(void)
 #endif
 }
 
-#define CACHE_COLOR(addr)      (((unsigned long)(addr) >> (PAGE_SHIFT)) & 3)
+#define CACHE_COLOR(addr)      (((unsigned long)(addr) >> (PAGE_SHIFT)) & 1)
 
 /*
  * checks if two addresses (after page aligning) index into same cache set
  */
 #define addr_not_cache_congruent(addr1, addr2)                         \
+({                                                                     \
        cache_is_vipt_aliasing() ?                                      \
-               (CACHE_COLOR(addr1) != CACHE_COLOR(addr2)) : 0          \
+               (CACHE_COLOR(addr1) != CACHE_COLOR(addr2)) : 0;         \
+})
 
 #define copy_to_user_page(vma, page, vaddr, dst, src, len)             \
 do {                                                                   \
index 374a355..ab84bf1 100644 (file)
 #define clear_page(paddr)              memset((paddr), 0, PAGE_SIZE)
 #define copy_page(to, from)            memcpy((to), (from), PAGE_SIZE)
 
-#ifndef CONFIG_ARC_CACHE_VIPT_ALIASING
-
-#define clear_user_page(addr, vaddr, pg)       clear_page(addr)
-#define copy_user_page(vto, vfrom, vaddr, pg)  copy_page(vto, vfrom)
-
-#else  /* VIPT aliasing dcache */
-
 struct vm_area_struct;
 struct page;
 
@@ -35,8 +28,6 @@ void copy_user_highpage(struct page *to, struct page *from,
                        unsigned long u_vaddr, struct vm_area_struct *vma);
 void clear_user_page(void *to, unsigned long u_vaddr, struct page *page);
 
-#endif /* CONFIG_ARC_CACHE_VIPT_ALIASING */
-
 #undef STRICT_MM_TYPECHECKS
 
 #ifdef STRICT_MM_TYPECHECKS
index 1cc4720..95b1522 100644 (file)
@@ -57,9 +57,9 @@
 
 #define _PAGE_ACCESSED      (1<<1)     /* Page is accessed (S) */
 #define _PAGE_CACHEABLE     (1<<2)     /* Page is cached (H) */
-#define _PAGE_EXECUTE       (1<<3)     /* Page has user execute perm (H) */
-#define _PAGE_WRITE         (1<<4)     /* Page has user write perm (H) */
-#define _PAGE_READ          (1<<5)     /* Page has user read perm (H) */
+#define _PAGE_U_EXECUTE     (1<<3)     /* Page has user execute perm (H) */
+#define _PAGE_U_WRITE       (1<<4)     /* Page has user write perm (H) */
+#define _PAGE_U_READ        (1<<5)     /* Page has user read perm (H) */
 #define _PAGE_K_EXECUTE     (1<<6)     /* Page has kernel execute perm (H) */
 #define _PAGE_K_WRITE       (1<<7)     /* Page has kernel write perm (H) */
 #define _PAGE_K_READ        (1<<8)     /* Page has kernel perm (H) */
@@ -72,9 +72,9 @@
 
 /* PD1 */
 #define _PAGE_CACHEABLE     (1<<0)     /* Page is cached (H) */
-#define _PAGE_EXECUTE       (1<<1)     /* Page has user execute perm (H) */
-#define _PAGE_WRITE         (1<<2)     /* Page has user write perm (H) */
-#define _PAGE_READ          (1<<3)     /* Page has user read perm (H) */
+#define _PAGE_U_EXECUTE     (1<<1)     /* Page has user execute perm (H) */
+#define _PAGE_U_WRITE       (1<<2)     /* Page has user write perm (H) */
+#define _PAGE_U_READ        (1<<3)     /* Page has user read perm (H) */
 #define _PAGE_K_EXECUTE     (1<<4)     /* Page has kernel execute perm (H) */
 #define _PAGE_K_WRITE       (1<<5)     /* Page has kernel write perm (H) */
 #define _PAGE_K_READ        (1<<6)     /* Page has kernel perm (H) */
@@ -93,7 +93,8 @@
 #endif
 
 /* Kernel allowed all permissions for all pages */
-#define _K_PAGE_PERMS  (_PAGE_K_EXECUTE | _PAGE_K_WRITE | _PAGE_K_READ)
+#define _K_PAGE_PERMS  (_PAGE_K_EXECUTE | _PAGE_K_WRITE | _PAGE_K_READ | \
+                       _PAGE_GLOBAL | _PAGE_PRESENT)
 
 #ifdef CONFIG_ARC_CACHE_PAGES
 #define _PAGE_DEF_CACHEABLE _PAGE_CACHEABLE
  * -by default cached, unless config otherwise
  * -present in memory
  */
-#define ___DEF (_PAGE_PRESENT | _K_PAGE_PERMS | _PAGE_DEF_CACHEABLE)
+#define ___DEF (_PAGE_PRESENT | _PAGE_DEF_CACHEABLE)
+
+#define _PAGE_READ     (_PAGE_U_READ    | _PAGE_K_READ)
+#define _PAGE_WRITE    (_PAGE_U_WRITE   | _PAGE_K_WRITE)
+#define _PAGE_EXECUTE  (_PAGE_U_EXECUTE | _PAGE_K_EXECUTE)
 
 /* Set of bits not changed in pte_modify */
 #define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_MODIFIED)
  * kernel vaddr space - visible in all addr spaces, but kernel mode only
  * Thus Global, all-kernel-access, no-user-access, cached
  */
-#define PAGE_KERNEL          __pgprot(___DEF | _PAGE_GLOBAL)
+#define PAGE_KERNEL          __pgprot(_K_PAGE_PERMS | _PAGE_DEF_CACHEABLE)
 
 /* ioremap */
-#define PAGE_KERNEL_NO_CACHE __pgprot(_PAGE_PRESENT | _K_PAGE_PERMS | \
-                                                    _PAGE_GLOBAL)
+#define PAGE_KERNEL_NO_CACHE __pgprot(_K_PAGE_PERMS)
 
 /**************************************************************************
  * Mapping of vm_flags (Generic VM) to PTE flags (arch specific)
index 85b6df8..cb0c708 100644 (file)
@@ -16,7 +16,7 @@
 /* Masks for actual TLB "PD"s */
 #define PTE_BITS_IN_PD0        (_PAGE_GLOBAL | _PAGE_PRESENT)
 #define PTE_BITS_IN_PD1        (PAGE_MASK | _PAGE_CACHEABLE | \
-                        _PAGE_EXECUTE | _PAGE_WRITE | _PAGE_READ | \
+                        _PAGE_U_EXECUTE | _PAGE_U_WRITE | _PAGE_U_READ | \
                         _PAGE_K_EXECUTE | _PAGE_K_WRITE | _PAGE_K_READ)
 
 #ifndef __ASSEMBLY__
index 2f12bca..aedce19 100644 (file)
@@ -610,7 +610,7 @@ void __sync_icache_dcache(unsigned long paddr, unsigned long vaddr, int len)
 
        local_irq_save(flags);
        __ic_line_inv_vaddr(paddr, vaddr, len);
-       __dc_line_op(paddr, vaddr, len, OP_FLUSH);
+       __dc_line_op(paddr, vaddr, len, OP_FLUSH_N_INV);
        local_irq_restore(flags);
 }
 
@@ -676,6 +676,17 @@ void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
        flush_cache_all();
 }
 
+void flush_anon_page(struct vm_area_struct *vma, struct page *page,
+                    unsigned long u_vaddr)
+{
+       /* TBD: do we really need to clear the kernel mapping */
+       __flush_dcache_page(page_address(page), u_vaddr);
+       __flush_dcache_page(page_address(page), page_address(page));
+
+}
+
+#endif
+
 void copy_user_highpage(struct page *to, struct page *from,
        unsigned long u_vaddr, struct vm_area_struct *vma)
 {
@@ -725,16 +736,6 @@ void clear_user_page(void *to, unsigned long u_vaddr, struct page *page)
        set_bit(PG_arch_1, &page->flags);
 }
 
-void flush_anon_page(struct vm_area_struct *vma, struct page *page,
-                    unsigned long u_vaddr)
-{
-       /* TBD: do we really need to clear the kernel mapping */
-       __flush_dcache_page(page_address(page), u_vaddr);
-       __flush_dcache_page(page_address(page), page_address(page));
-
-}
-
-#endif
 
 /**********************************************************************
  * Explicit Cache flush request from user space via syscall
index 066145b..fe1c5a0 100644 (file)
@@ -444,7 +444,8 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long vaddr_unaligned,
         *             so userspace sees the right data.
         *  (Avoids the flush for Non-exec + congruent mapping case)
         */
-       if (vma->vm_flags & VM_EXEC || addr_not_cache_congruent(paddr, vaddr)) {
+       if ((vma->vm_flags & VM_EXEC) ||
+            addr_not_cache_congruent(paddr, vaddr)) {
                struct page *page = pfn_to_page(pte_pfn(*ptep));
 
                int dirty = test_and_clear_bit(PG_arch_1, &page->flags);
index 9df765d..3357d26 100644 (file)
@@ -277,7 +277,7 @@ ARC_ENTRY EV_TLBMissI
        ;----------------------------------------------------------------
        ; VERIFY_PTE: Check if PTE permissions approp for executing code
        cmp_s   r2, VMALLOC_START
-       mov.lo  r2, (_PAGE_PRESENT | _PAGE_READ | _PAGE_EXECUTE)
+       mov.lo  r2, (_PAGE_PRESENT | _PAGE_U_READ | _PAGE_U_EXECUTE)
        mov.hs  r2, (_PAGE_PRESENT | _PAGE_K_READ | _PAGE_K_EXECUTE)
 
        and     r3, r0, r2  ; Mask out NON Flag bits from PTE
@@ -320,9 +320,9 @@ ARC_ENTRY EV_TLBMissD
        mov_s   r2, 0
        lr      r3, [ecr]
        btst_s  r3, ECR_C_BIT_DTLB_LD_MISS      ; Read Access
-       or.nz   r2, r2, _PAGE_READ              ; chk for Read flag in PTE
+       or.nz   r2, r2, _PAGE_U_READ            ; chk for Read flag in PTE
        btst_s  r3, ECR_C_BIT_DTLB_ST_MISS      ; Write Access
-       or.nz   r2, r2, _PAGE_WRITE             ; chk for Write flag in PTE
+       or.nz   r2, r2, _PAGE_U_WRITE           ; chk for Write flag in PTE
        ; Above laddering takes care of XCHG access
        ;   which is both Read and Write
 
index d356769..06cb309 100644 (file)
@@ -34,31 +34,6 @@ static void __init tb10x_platform_init(void)
        of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
-static void __init tb10x_platform_late_init(void)
-{
-       struct device_node *dn;
-
-       /*
-        * Pinctrl documentation recommends setting up the iomux here for
-        * all modules which don't require control over the pins themselves.
-        * Modules which need this kind of assistance are compatible with
-        * "abilis,simple-pinctrl", i.e. we can easily iterate over them.
-        * TODO: Does this recommended method work cleanly with pins required
-        * by modules?
-        */
-       for_each_compatible_node(dn, NULL, "abilis,simple-pinctrl") {
-               struct platform_device *pd = of_find_device_by_node(dn);
-               struct pinctrl *pctl;
-
-               pctl = pinctrl_get_select(&pd->dev, "abilis,simple-default");
-               if (IS_ERR(pctl)) {
-                       int ret = PTR_ERR(pctl);
-                       dev_err(&pd->dev, "Could not set up pinctrl: %d\n",
-                               ret);
-               }
-       }
-}
-
 static const char *tb10x_compat[] __initdata = {
        "abilis,arc-tb10x",
        NULL,
@@ -67,5 +42,4 @@ static const char *tb10x_compat[] __initdata = {
 MACHINE_START(TB10x, "tb10x")
        .dt_compat      = tb10x_compat,
        .init_machine   = tb10x_platform_init,
-       .init_late      = tb10x_platform_late_init,
 MACHINE_END
index d423d58..49d993c 100644 (file)
@@ -38,6 +38,7 @@ config ARM
        select HAVE_GENERIC_HARDIRQS
        select HAVE_HW_BREAKPOINT if (PERF_EVENTS && (CPU_V6 || CPU_V6K || CPU_V7))
        select HAVE_IDE if PCI || ISA || PCMCIA
+       select HAVE_IRQ_TIME_ACCOUNTING
        select HAVE_KERNEL_GZIP
        select HAVE_KERNEL_LZMA
        select HAVE_KERNEL_LZO
@@ -488,7 +489,7 @@ config ARCH_IXP4XX
 config ARCH_DOVE
        bool "Marvell Dove"
        select ARCH_REQUIRE_GPIOLIB
-       select CPU_V7
+       select CPU_PJ4
        select GENERIC_CLOCKEVENTS
        select MIGHT_HAVE_PCI
        select PINCTRL
index 4737408..1ba358b 100644 (file)
@@ -309,7 +309,7 @@ define archhelp
   echo  '  Image         - Uncompressed kernel image (arch/$(ARCH)/boot/Image)'
   echo  '* xipImage      - XIP kernel image, if configured (arch/$(ARCH)/boot/xipImage)'
   echo  '  uImage        - U-Boot wrapped zImage'
-  echo  '  bootpImage    - Combined zImage and initial RAM disk' 
+  echo  '  bootpImage    - Combined zImage and initial RAM disk'
   echo  '                  (supply initrd image via make variable INITRD=<path>)'
   echo  '* dtbs          - Build device tree blobs for enabled boards'
   echo  '  install       - Install uncompressed kernel'
index 3580d57..79e9bdb 100644 (file)
@@ -124,7 +124,7 @@ KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CFLAGS))
 endif
 
 ccflags-y := -fpic -mno-single-pic-base -fno-builtin -I$(obj)
-asflags-y := -Wa,-march=all -DZIMAGE
+asflags-y := -DZIMAGE
 
 # Supply kernel BSS size to the decompressor via a linker symbol.
 KBSS_SZ = $(shell $(CROSS_COMPILE)size $(obj)/../../../../vmlinux | \
index 6e8382d..5392ee6 100644 (file)
@@ -1,6 +1,8 @@
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 
+#ifndef CONFIG_DEBUG_SEMIHOSTING
+
 #include CONFIG_DEBUG_LL_INCLUDE
 
 ENTRY(putc)
@@ -10,3 +12,29 @@ ENTRY(putc)
        busyuart r3, r1
        mov      pc, lr
 ENDPROC(putc)
+
+#else
+
+ENTRY(putc)
+       adr     r1, 1f
+       ldmia   r1, {r2, r3}
+       add     r2, r2, r1
+       ldr     r1, [r2, r3]
+       strb    r0, [r1]
+       mov     r0, #0x03               @ SYS_WRITEC
+   ARM(        svc     #0x123456       )
+ THUMB(        svc     #0xab           )
+       mov     pc, lr
+       .align  2
+1:     .word   _GLOBAL_OFFSET_TABLE_ - .
+       .word   semi_writec_buf(GOT)
+ENDPROC(putc)
+
+       .bss
+       .global semi_writec_buf
+       .type   semi_writec_buf, %object
+semi_writec_buf:
+       .space  4
+       .size   semi_writec_buf, 4
+
+#endif
index 6179d94..3115e31 100644 (file)
@@ -11,6 +11,7 @@
 #include <asm/mach-types.h>
 
                .section        ".start", "ax"
+               .arch   armv4
 
 __SA1100_start:
 
index 089c560..92b5689 100644 (file)
@@ -18,6 +18,7 @@
        
                .section        ".start", "ax"
 
+               .arch armv4
                b       __beginning
        
 __ofw_data:    .long   0                               @ the number of memory blocks
index fe4d9c3..032a8d9 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 
+       .arch   armv7-a
 /*
  * Debugging stuff
  *
@@ -805,8 +806,8 @@ call_cache_fn:      adr     r12, proc_types
                .align  2
                .type   proc_types,#object
 proc_types:
-               .word   0x00000000              @ old ARM ID
-               .word   0x0000f000
+               .word   0x41000000              @ old ARM ID
+               .word   0xff00f000
                mov     pc, lr
  THUMB(                nop                             )
                mov     pc, lr
index b9f7121..f0895c5 100644 (file)
@@ -177,7 +177,9 @@ dtb-$(CONFIG_ARCH_SPEAR3XX)+= spear300-evb.dtb \
        spear320-evb.dtb \
        spear320-hmi.dtb
 dtb-$(CONFIG_ARCH_SPEAR6XX)+= spear600-evb.dtb
-dtb-$(CONFIG_ARCH_SUNXI) += sun4i-a10-cubieboard.dtb \
+dtb-$(CONFIG_ARCH_SUNXI) += \
+       sun4i-a10-cubieboard.dtb \
+       sun4i-a10-mini-xplus.dtb \
        sun4i-a10-hackberry.dtb \
        sun5i-a13-olinuxino.dtb
 dtb-$(CONFIG_ARCH_TEGRA) += tegra20-harmony.dtb \
index 272bbc6..550eb77 100644 (file)
@@ -33,7 +33,8 @@
                #size-cells = <1>;
                compatible = "simple-bus";
                interrupt-parent = <&mpic>;
-               ranges = <0 0 0xd0000000 0x100000>;
+               ranges = <0          0 0xd0000000 0x0100000 /* internal registers */
+                         0xe0000000 0 0xe0000000 0x8100000 /* PCIe */>;
 
                internal-regs {
                        compatible = "simple-bus";
index b2c1b5a..aee2b18 100644 (file)
@@ -29,7 +29,8 @@
        };
 
        soc {
-               ranges = <0 0xd0000000 0x100000>;
+               ranges = <0          0xd0000000 0x0100000 /* internal registers */
+                         0xe0000000 0xe0000000 0x8100000 /* PCIe */>;
                internal-regs {
                        system-controller@18200 {
                                compatible = "marvell,armada-370-xp-system-controller";
 
                        L2: l2-cache {
                                compatible = "marvell,aurora-outer-cache";
-                               reg = <0xd0008000 0x1000>;
+                               reg = <0x08000 0x1000>;
                                cache-id-part = <0x100>;
                                wt-override;
                        };
 
-                       mpic: interrupt-controller@20000 {
+                       interrupt-controller@20000 {
                                reg = <0x20a00 0x1d0>, <0x21870 0x58>;
                        };
 
index 26ad06f..3ee63d1 100644 (file)
@@ -39,6 +39,9 @@
        };
 
        soc {
+               ranges = <0          0 0xd0000000 0x100000
+                         0xf0000000 0 0xf0000000 0x1000000>;
+
                internal-regs {
                        serial@12000 {
                                clock-frequency = <250000000>;
index f14d36c..46b7850 100644 (file)
@@ -27,6 +27,9 @@
        };
 
        soc {
+               ranges = <0          0 0xd0000000 0x100000
+                         0xf0000000 0 0xf0000000 0x8000000>;
+
                internal-regs {
                        serial@12000 {
                                clock-frequency = <250000000>;
index bacab11..5b902f9 100644 (file)
@@ -31,7 +31,7 @@
                                wt-override;
                        };
 
-                       mpic: interrupt-controller@20000 {
+                       interrupt-controller@20000 {
                              reg = <0x20a00 0x2d0>, <0x21070 0x58>;
                        };
 
index 70b5ccb..84c4bef 100644 (file)
                                                atmel,pins =
                                                        <0 10 0x2 0x0   /* PA10 periph B */
                                                         0 11 0x2 0x0   /* PA11 periph B */
-                                                        0 24 0x2 0x0   /* PA24 periph B */
+                                                        0 22 0x2 0x0   /* PA22 periph B */
                                                         0 25 0x2 0x0   /* PA25 periph B */
                                                         0 26 0x2 0x0   /* PA26 periph B */
                                                         0 27 0x2 0x0   /* PA27 periph B */
index 3de8e6d..8d25f88 100644 (file)
@@ -57,6 +57,7 @@
                                compatible = "atmel,at91rm9200-aic";
                                interrupt-controller;
                                reg = <0xfffff000 0x200>;
+                               atmel,external-irqs = <31>;
                        };
 
                        ramc0: ramc@ffffe800 {
index 3b40d11..315250b 100644 (file)
@@ -11,7 +11,7 @@
 /include/ "at91sam9x5ek.dtsi"
 
 / {
-       model = "Atmel AT91SAM9G25-EK";
+       model = "Atmel AT91SAM9X25-EK";
        compatible = "atmel,at91sam9x25ek", "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9";
 
        ahb {
index f0052dc..1e12aef 100644 (file)
@@ -44,6 +44,7 @@
                        reg = <0x7e201000 0x1000>;
                        interrupts = <2 25>;
                        clock-frequency = <3000000>;
+                       arm,primecell-periphid = <0x00241011>;
                };
 
                gpio: gpio {
index 98dfc3e..0673524 100644 (file)
                clock-names = "usbhost";
        };
 
+       usbphy@12130000 {
+               compatible = "samsung,exynos5250-usb2phy";
+               reg = <0x12130000 0x100>;
+               clocks = <&clock 1>, <&clock 285>;
+               clock-names = "ext_xtal", "usbhost";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+
+               usbphy-sys {
+                       reg = <0x10040704 0x8>,
+                             <0x10050230 0x4>;
+               };
+       };
+
        amba {
                #address-cells = <1>;
                #size-cells = <1>;
index d2550e0..7011539 100644 (file)
                                #size-cells = <0>;
                                compatible = "fsl,imx25-cspi", "fsl,imx35-cspi";
                                reg = <0x43fa4000 0x4000>;
-                               clocks = <&clks 62>;
-                               clock-names = "ipg";
+                               clocks = <&clks 62>, <&clks 62>;
+                               clock-names = "ipg", "per";
                                interrupts = <14>;
                                status = "disabled";
                        };
                                compatible = "fsl,imx25-cspi", "fsl,imx35-cspi";
                                reg = <0x50004000 0x4000>;
                                interrupts = <0>;
-                               clocks = <&clks 80>;
-                               clock-names = "ipg";
+                               clocks = <&clks 80>, <&clks 80>;
+                               clock-names = "ipg", "per";
                                status = "disabled";
                        };
 
                                #size-cells = <0>;
                                compatible = "fsl,imx25-cspi", "fsl,imx35-cspi";
                                reg = <0x50010000 0x4000>;
-                               clocks = <&clks 79>;
-                               clock-names = "ipg";
+                               clocks = <&clks 79>, <&clks 79>;
+                               clock-names = "ipg", "per";
                                interrupts = <13>;
                                status = "disabled";
                        };
index ff4bd48..75bd113 100644 (file)
                                compatible = "fsl,imx27-cspi";
                                reg = <0x1000e000 0x1000>;
                                interrupts = <16>;
-                               clocks = <&clks 53>, <&clks 0>;
+                               clocks = <&clks 53>, <&clks 53>;
                                clock-names = "ipg", "per";
                                status = "disabled";
                        };
                                compatible = "fsl,imx27-cspi";
                                reg = <0x1000f000 0x1000>;
                                interrupts = <15>;
-                               clocks = <&clks 52>, <&clks 0>;
+                               clocks = <&clks 52>, <&clks 52>;
                                clock-names = "ipg", "per";
                                status = "disabled";
                        };
                                compatible = "fsl,imx27-cspi";
                                reg = <0x10017000 0x1000>;
                                interrupts = <6>;
-                               clocks = <&clks 51>, <&clks 0>;
+                               clocks = <&clks 51>, <&clks 51>;
                                clock-names = "ipg", "per";
                                status = "disabled";
                        };
index 21bb786..53fdde6 100644 (file)
                                compatible = "fsl,imx51-cspi", "fsl,imx35-cspi";
                                reg = <0x83fc0000 0x4000>;
                                interrupts = <38>;
-                               clocks = <&clks 55>, <&clks 0>;
+                               clocks = <&clks 55>, <&clks 55>;
                                clock-names = "ipg", "per";
                                status = "disabled";
                        };
index 845982e..eb83aa0 100644 (file)
                                compatible = "fsl,imx53-cspi", "fsl,imx35-cspi";
                                reg = <0x63fc0000 0x4000>;
                                interrupts = <38>;
-                               clocks = <&clks 55>, <&clks 0>;
+                               clocks = <&clks 55>, <&clks 55>;
                                clock-names = "ipg", "per";
                                status = "disabled";
                        };
index 82a404d..99ba6e1 100644 (file)
                usb_otg_hs: usb_otg_hs@480ab000 {
                        compatible = "ti,omap3-musb";
                        reg = <0x480ab000 0x1000>;
-                       interrupts = <0 92 0x4>, <0 93 0x4>;
+                       interrupts = <92>, <93>;
                        interrupt-names = "mc", "dma";
                        ti,hwmods = "usb_otg_hs";
                        multipoint = <1>;
index 2e643ea..5000e0d 100644 (file)
                                compatible = "atmel,at91sam9x5-spi";
                                reg = <0xf0004000 0x100>;
                                interrupts = <24 4 3>;
-                               cs-gpios = <&pioD 13 0
-                                           &pioD 14 0 /* conflicts with SCK0 and CANRX0 */
-                                           &pioD 15 0 /* conflicts with CTS0 and CANTX0 */
-                                           &pioD 16 0 /* conflicts with RTS0 and PWMFI3 */
-                                          >;
                                pinctrl-names = "default";
                                pinctrl-0 = <&pinctrl_spi0>;
                                status = "disabled";
                        };
 
                        macb0: ethernet@f0028000 {
-                               compatible = "cnds,pc302-gem", "cdns,gem";
+                               compatible = "cdns,pc302-gem", "cdns,gem";
                                reg = <0xf0028000 0x100>;
                                interrupts = <34 4 3>;
                                pinctrl-names = "default";
                                compatible = "atmel,at91sam9x5-spi";
                                reg = <0xf8008000 0x100>;
                                interrupts = <25 4 3>;
-                               cs-gpios = <&pioC 25 0
-                                           &pioC 26 0 /* conflitcs with TWD1 and ISI_D11 */
-                                           &pioC 27 0 /* conflitcs with TWCK1 and ISI_D10 */
-                                           &pioC 28 0 /* conflitcs with PWMFI0 and ISI_D9 */
-                                          >;
                                pinctrl-names = "default";
                                pinctrl-0 = <&pinctrl_spi1>;
                                status = "disabled";
index 1f8ed40..b336e77 100644 (file)
 
        ahb {
                apb {
+                       spi0: spi@f0004000 {
+                               cs-gpios = <&pioD 13 0>, <0>, <0>, <0>;
+                       };
+
                        macb0: ethernet@f0028000 {
                                phy-mode = "rgmii";
                        };
index b28fbf3..6f82d93 100644 (file)
                bootargs = "root=/dev/ram0 console=ttyAMA1,115200n8 earlyprintk";
        };
 
+       /* This is where the interrupt is routed on the S8815 board */
+       external-bus@34000000 {
+               ethernet@300 {
+                       interrupt-parent = <&gpio3>;
+                       interrupts = <8 0x1>;
+               };
+       };
+
        /* Custom board node with GPIO pins to active etc */
        usb-s8815 {
                /* The S8815 is using this very GPIO pin for the SMSC91x IRQs */
                ethernet-gpio {
-                       gpios = <&gpio3 19 0x1>;
-                       interrupts = <19 0x1>;
-                       interrupt-parent = <&gpio3>;
+                       gpios = <&gpio3 8 0x1>;
                };
                /* This will bias the MMC/SD card detect line */
                mmcsd-gpio {
index 4a7c35d..078ed7f 100644 (file)
@@ -22,8 +22,8 @@
                bootargs = "earlyprintk console=ttyS0,115200";
        };
 
-       soc {
-               uart0: uart@01c28000 {
+       soc@01c20000 {
+               uart0: serial@01c28000 {
                        pinctrl-names = "default";
                        pinctrl-0 = <&uart0_pins_a>;
                        status = "okay";
index 52b88d8..3caed0d 100644 (file)
@@ -15,8 +15,6 @@
 #include <linux/smp.h>
 #include <linux/spinlock.h>
 
-#include <linux/irqchip/arm-gic.h>
-
 #include <asm/mcpm.h>
 #include <asm/smp.h>
 #include <asm/smp_plat.h>
@@ -49,7 +47,6 @@ static int __cpuinit mcpm_boot_secondary(unsigned int cpu, struct task_struct *i
 static void __cpuinit mcpm_secondary_init(unsigned int cpu)
 {
        mcpm_cpu_powered_up();
-       gic_secondary_init(0);
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
index e40b435..227abf9 100644 (file)
@@ -1,4 +1,4 @@
-CONFIG_EXPERIMENTAL=y
+CONFIG_SYSVIPC=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_BLK_DEV_INITRD=y
@@ -7,17 +7,18 @@ CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
 CONFIG_PARTITION_ADVANCED=y
-CONFIG_EFI_PARTITION=y
 CONFIG_ARCH_EXYNOS=y
-CONFIG_S3C_LOWLEVEL_UART_PORT=1
+CONFIG_S3C_LOWLEVEL_UART_PORT=3
 CONFIG_S3C24XX_PWM=y
 CONFIG_ARCH_EXYNOS5=y
 CONFIG_MACH_EXYNOS4_DT=y
-CONFIG_MACH_EXYNOS5_DT=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=2
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
+CONFIG_HIGHMEM=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
 CONFIG_ARM_APPENDED_DTB=y
 CONFIG_ARM_ATAG_DTB_COMPAT=y
 CONFIG_CMDLINE="root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC1,115200 init=/linuxrc mem=256M"
@@ -30,35 +31,58 @@ CONFIG_NET_KEY=y
 CONFIG_INET=y
 CONFIG_RFKILL_REGULATOR=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=8192
 CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_SG=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=y
+CONFIG_DM_CRYPT=m
 CONFIG_NETDEVICES=y
 CONFIG_SMSC911X=y
 CONFIG_USB_USBNET=y
 CONFIG_USB_NET_SMSC75XX=y
 CONFIG_USB_NET_SMSC95XX=y
 CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
+CONFIG_KEYBOARD_CROS_EC=y
+# CONFIG_MOUSE_PS2 is not set
+CONFIG_MOUSE_CYAPA=y
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_SAMSUNG=y
 CONFIG_SERIAL_SAMSUNG_CONSOLE=y
 CONFIG_SERIAL_OF_PLATFORM=y
 CONFIG_HW_RANDOM=y
+CONFIG_TCG_TPM=y
+CONFIG_TCG_TIS_I2C_INFINEON=y
 CONFIG_I2C=y
+CONFIG_I2C_MUX=y
+CONFIG_I2C_ARB_GPIO_CHALLENGE=y
+CONFIG_I2C_S3C2410=y
+CONFIG_DEBUG_GPIO=y
 # CONFIG_HWMON is not set
+CONFIG_MFD_CROS_EC=y
+CONFIG_MFD_CROS_EC_I2C=y
+CONFIG_MFD_MAX77686=y
+CONFIG_MFD_MAX8997=y
+CONFIG_MFD_SEC_CORE=y
 CONFIG_MFD_TPS65090=y
 CONFIG_REGULATOR=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
 CONFIG_REGULATOR_GPIO=y
+CONFIG_REGULATOR_MAX8997=y
+CONFIG_REGULATOR_MAX77686=y
+CONFIG_REGULATOR_S5M8767=y
 CONFIG_REGULATOR_TPS65090=y
 CONFIG_FB=y
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_SIMPLE=y
 CONFIG_EXYNOS_VIDEO=y
 CONFIG_EXYNOS_MIPI_DSI=y
 CONFIG_EXYNOS_DP=y
@@ -67,6 +91,20 @@ CONFIG_FONTS=y
 CONFIG_FONT_7x14=y
 CONFIG_LOGO=y
 CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_S5P=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_DWC3=y
+CONFIG_USB_PHY=y
+CONFIG_SAMSUNG_USB2PHY=y
+CONFIG_SAMSUNG_USB3PHY=y
+CONFIG_MMC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_S3C=y
+CONFIG_MMC_DW=y
+CONFIG_MMC_DW_IDMAC=y
+CONFIG_MMC_DW_EXYNOS=y
+CONFIG_COMMON_CLK_MAX77686=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 CONFIG_EXT4_FS=y
@@ -79,6 +117,7 @@ CONFIG_ROMFS_FS=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ASCII=y
 CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_KERNEL=y
 CONFIG_DETECT_HUNG_TASK=y
@@ -87,6 +126,5 @@ CONFIG_DEBUG_SPINLOCK=y
 CONFIG_DEBUG_MUTEXES=y
 CONFIG_DEBUG_INFO=y
 CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_LL=y
-CONFIG_EARLY_PRINTK=y
+CONFIG_CRYPTO_SHA256=y
 CONFIG_CRC_CCITT=y
index 7e0ebb6..9940f7b 100644 (file)
@@ -199,7 +199,6 @@ CONFIG_USB_PHY=y
 CONFIG_USB_DEBUG=y
 CONFIG_USB_DEVICEFS=y
 # CONFIG_USB_DEVICE_CLASS is not set
-CONFIG_USB_SUSPEND=y
 CONFIG_USB_MON=y
 CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_STORAGE=y
index c1ef64b..abbe319 100644 (file)
@@ -20,6 +20,7 @@ CONFIG_MODULE_FORCE_UNLOAD=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 # CONFIG_BLK_DEV_BSG is not set
+CONFIG_ARCH_MULTI_V6=y
 CONFIG_ARCH_OMAP2PLUS=y
 CONFIG_OMAP_RESET_CLOCKS=y
 CONFIG_OMAP_MUX_DEBUG=y
@@ -204,7 +205,6 @@ CONFIG_USB=y
 CONFIG_USB_DEBUG=y
 CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
 CONFIG_USB_DEVICEFS=y
-CONFIG_USB_SUSPEND=y
 CONFIG_USB_MON=y
 CONFIG_USB_WDM=y
 CONFIG_USB_STORAGE=y
index a5f0485..f7ba316 100644 (file)
@@ -153,6 +153,7 @@ CONFIG_MEDIA_CAMERA_SUPPORT=y
 CONFIG_MEDIA_USB_SUPPORT=y
 CONFIG_USB_VIDEO_CLASS=m
 CONFIG_DRM=y
+CONFIG_TEGRA_HOST1X=y
 CONFIG_DRM_TEGRA=y
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
 # CONFIG_LCD_CLASS_DEVICE is not set
@@ -202,7 +203,7 @@ CONFIG_TEGRA20_APB_DMA=y
 CONFIG_STAGING=y
 CONFIG_SENSORS_ISL29018=y
 CONFIG_SENSORS_ISL29028=y
-CONFIG_SENSORS_AK8975=y
+CONFIG_AK8975=y
 CONFIG_MFD_NVEC=y
 CONFIG_KEYBOARD_NVEC=y
 CONFIG_SERIO_NVEC_PS2=y
index 92c6eed..99207c4 100644 (file)
@@ -195,6 +195,7 @@ ENTRY(sha1_block_data_order)
        add     r3,r3,r10                       @ E+=F_00_19(B,C,D)
        cmp     r14,sp
        bne     .L_00_15                @ [((11+4)*5+2)*3]
+       sub     sp,sp,#25*4
 #if __ARM_ARCH__<7
        ldrb    r10,[r1,#2]
        ldrb    r9,[r1,#3]
@@ -290,7 +291,6 @@ ENTRY(sha1_block_data_order)
        add     r3,r3,r10                       @ E+=F_00_19(B,C,D)
 
        ldr     r8,.LK_20_39            @ [+15+16*4]
-       sub     sp,sp,#25*4
        cmn     sp,#0                   @ [+3], clear carry to denote 20_39
 .L_20_39_or_60_79:
        ldr     r9,[r14,#15*4]
index 7eb18c1..4f009c1 100644 (file)
@@ -233,15 +233,15 @@ static inline unsigned long __cmpxchg_local(volatile void *ptr,
        ((__typeof__(*(ptr)))atomic64_cmpxchg(container_of((ptr),       \
                                                atomic64_t,             \
                                                counter),               \
-                                             (unsigned long)(o),       \
-                                             (unsigned long)(n)))
+                                             (unsigned long long)(o),  \
+                                             (unsigned long long)(n)))
 
 #define cmpxchg64_local(ptr, o, n)                                     \
        ((__typeof__(*(ptr)))local64_cmpxchg(container_of((ptr),        \
                                                local64_t,              \
                                                a),                     \
-                                            (unsigned long)(o),        \
-                                            (unsigned long)(n)))
+                                            (unsigned long long)(o),   \
+                                            (unsigned long long)(n)))
 
 #endif /* __LINUX_ARM_ARCH__ >= 6 */
 
index 968c0a1..209e650 100644 (file)
@@ -30,8 +30,15 @@ static inline void set_my_cpu_offset(unsigned long off)
 static inline unsigned long __my_cpu_offset(void)
 {
        unsigned long off;
-       /* Read TPIDRPRW */
-       asm("mrc p15, 0, %0, c13, c0, 4" : "=r" (off) : : "memory");
+       register unsigned long *sp asm ("sp");
+
+       /*
+        * Read TPIDRPRW.
+        * We want to allow caching the value, so avoid using volatile and
+        * instead use a fake stack read to hazard against barrier().
+        */
+       asm("mrc p15, 0, %0, c13, c0, 4" : "=r" (off) : "Q" (*sp));
+
        return off;
 }
 #define __my_cpu_offset __my_cpu_offset()
index 99a1951..bdf2b84 100644 (file)
 #include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
 
-/*
- * We need to delay page freeing for SMP as other CPUs can access pages
- * which have been removed but not yet had their TLB entries invalidated.
- * Also, as ARMv7 speculative prefetch can drag new entries into the TLB,
- * we need to apply this same delaying tactic to ensure correct operation.
- */
-#if defined(CONFIG_SMP) || defined(CONFIG_CPU_32v7)
-#define tlb_fast_mode(tlb)     0
-#else
-#define tlb_fast_mode(tlb)     1
-#endif
-
 #define MMU_GATHER_BUNDLE      8
 
 /*
@@ -112,12 +100,10 @@ static inline void __tlb_alloc_page(struct mmu_gather *tlb)
 static inline void tlb_flush_mmu(struct mmu_gather *tlb)
 {
        tlb_flush(tlb);
-       if (!tlb_fast_mode(tlb)) {
-               free_pages_and_swap_cache(tlb->pages, tlb->nr);
-               tlb->nr = 0;
-               if (tlb->pages == tlb->local)
-                       __tlb_alloc_page(tlb);
-       }
+       free_pages_and_swap_cache(tlb->pages, tlb->nr);
+       tlb->nr = 0;
+       if (tlb->pages == tlb->local)
+               __tlb_alloc_page(tlb);
 }
 
 static inline void
@@ -178,11 +164,6 @@ tlb_end_vma(struct mmu_gather *tlb, struct vm_area_struct *vma)
 
 static inline int __tlb_remove_page(struct mmu_gather *tlb, struct page *page)
 {
-       if (tlb_fast_mode(tlb)) {
-               free_page_and_swap_cache(page);
-               return 1; /* avoid calling tlb_flush_mmu */
-       }
-
        tlb->pages[tlb->nr++] = page;
        VM_BUG_ON(tlb->nr > tlb->max);
        return tlb->max - tlb->nr;
index 2848857..fbd24be 100644 (file)
@@ -24,9 +24,9 @@
 #define U8500_UART0_PHYS_BASE  (0x80120000)
 #define U8500_UART1_PHYS_BASE  (0x80121000)
 #define U8500_UART2_PHYS_BASE  (0x80007000)
-#define U8500_UART0_VIRT_BASE  (0xa8120000)
-#define U8500_UART1_VIRT_BASE  (0xa8121000)
-#define U8500_UART2_VIRT_BASE  (0xa8007000)
+#define U8500_UART0_VIRT_BASE  (0xf8120000)
+#define U8500_UART1_VIRT_BASE  (0xf8121000)
+#define U8500_UART2_VIRT_BASE  (0xf8007000)
 #define __UX500_PHYS_UART(n)   U8500_UART##n##_PHYS_BASE
 #define __UX500_VIRT_UART(n)   U8500_UART##n##_VIRT_BASE
 #endif
index f219703..282de48 100644 (file)
@@ -411,7 +411,6 @@ static struct vm_area_struct gate_vma = {
        .vm_start       = 0xffff0000,
        .vm_end         = 0xffff0000 + PAGE_SIZE,
        .vm_flags       = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYEXEC,
-       .vm_mm          = &init_mm,
 };
 
 static int __init gate_vma_init(void)
index 47ab905..550d63c 100644 (file)
@@ -251,7 +251,7 @@ void __ref cpu_die(void)
         * this returns, power and/or clocks can be removed at any point
         * from this CPU and its cache by platform_cpu_kill().
         */
-       RCU_NONIDLE(complete(&cpu_died));
+       complete(&cpu_died);
 
        /*
         * Ensure that the cache lines associated with that completion are
index f10316b..c5a5954 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <linux/cpu.h>
 #include <linux/cpumask.h>
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/percpu.h>
 #include <linux/node.h>
@@ -200,6 +201,7 @@ static inline void update_cpu_power(unsigned int cpuid, unsigned int mpidr) {}
  * cpu topology table
  */
 struct cputopo_arm cpu_topology[NR_CPUS];
+EXPORT_SYMBOL_GPL(cpu_topology);
 
 const struct cpumask *cpu_coregroup_mask(int cpu)
 {
index 37d216d..ef1703b 100644 (file)
@@ -492,6 +492,11 @@ static void vcpu_pause(struct kvm_vcpu *vcpu)
        wait_event_interruptible(*wq, !vcpu->arch.pause);
 }
 
+static int kvm_vcpu_initialized(struct kvm_vcpu *vcpu)
+{
+       return vcpu->arch.target >= 0;
+}
+
 /**
  * kvm_arch_vcpu_ioctl_run - the main VCPU run function to execute guest code
  * @vcpu:      The VCPU pointer
@@ -508,8 +513,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
        int ret;
        sigset_t sigsaved;
 
-       /* Make sure they initialize the vcpu with KVM_ARM_VCPU_INIT */
-       if (unlikely(vcpu->arch.target < 0))
+       if (unlikely(!kvm_vcpu_initialized(vcpu)))
                return -ENOEXEC;
 
        ret = kvm_vcpu_first_run_init(vcpu);
@@ -710,6 +714,10 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
        case KVM_SET_ONE_REG:
        case KVM_GET_ONE_REG: {
                struct kvm_one_reg reg;
+
+               if (unlikely(!kvm_vcpu_initialized(vcpu)))
+                       return -ENOEXEC;
+
                if (copy_from_user(&reg, argp, sizeof(reg)))
                        return -EFAULT;
                if (ioctl == KVM_SET_ONE_REG)
@@ -722,6 +730,9 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
                struct kvm_reg_list reg_list;
                unsigned n;
 
+               if (unlikely(!kvm_vcpu_initialized(vcpu)))
+                       return -ENOEXEC;
+
                if (copy_from_user(&reg_list, user_list, sizeof(reg_list)))
                        return -EFAULT;
                n = reg_list.n;
index 9657065..84ba67b 100644 (file)
@@ -43,7 +43,14 @@ static phys_addr_t hyp_idmap_vector;
 
 static void kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa)
 {
-       kvm_call_hyp(__kvm_tlb_flush_vmid_ipa, kvm, ipa);
+       /*
+        * This function also gets called when dealing with HYP page
+        * tables. As HYP doesn't have an associated struct kvm (and
+        * the HYP page tables are fairly static), we don't do
+        * anything there.
+        */
+       if (kvm)
+               kvm_call_hyp(__kvm_tlb_flush_vmid_ipa, kvm, ipa);
 }
 
 static int mmu_topup_memory_cache(struct kvm_mmu_memory_cache *cache,
@@ -78,18 +85,20 @@ static void *mmu_memory_cache_alloc(struct kvm_mmu_memory_cache *mc)
        return p;
 }
 
-static void clear_pud_entry(pud_t *pud)
+static void clear_pud_entry(struct kvm *kvm, pud_t *pud, phys_addr_t addr)
 {
        pmd_t *pmd_table = pmd_offset(pud, 0);
        pud_clear(pud);
+       kvm_tlb_flush_vmid_ipa(kvm, addr);
        pmd_free(NULL, pmd_table);
        put_page(virt_to_page(pud));
 }
 
-static void clear_pmd_entry(pmd_t *pmd)
+static void clear_pmd_entry(struct kvm *kvm, pmd_t *pmd, phys_addr_t addr)
 {
        pte_t *pte_table = pte_offset_kernel(pmd, 0);
        pmd_clear(pmd);
+       kvm_tlb_flush_vmid_ipa(kvm, addr);
        pte_free_kernel(NULL, pte_table);
        put_page(virt_to_page(pmd));
 }
@@ -100,11 +109,12 @@ static bool pmd_empty(pmd_t *pmd)
        return page_count(pmd_page) == 1;
 }
 
-static void clear_pte_entry(pte_t *pte)
+static void clear_pte_entry(struct kvm *kvm, pte_t *pte, phys_addr_t addr)
 {
        if (pte_present(*pte)) {
                kvm_set_pte(pte, __pte(0));
                put_page(virt_to_page(pte));
+               kvm_tlb_flush_vmid_ipa(kvm, addr);
        }
 }
 
@@ -114,7 +124,8 @@ static bool pte_empty(pte_t *pte)
        return page_count(pte_page) == 1;
 }
 
-static void unmap_range(pgd_t *pgdp, unsigned long long start, u64 size)
+static void unmap_range(struct kvm *kvm, pgd_t *pgdp,
+                       unsigned long long start, u64 size)
 {
        pgd_t *pgd;
        pud_t *pud;
@@ -138,15 +149,15 @@ static void unmap_range(pgd_t *pgdp, unsigned long long start, u64 size)
                }
 
                pte = pte_offset_kernel(pmd, addr);
-               clear_pte_entry(pte);
+               clear_pte_entry(kvm, pte, addr);
                range = PAGE_SIZE;
 
                /* If we emptied the pte, walk back up the ladder */
                if (pte_empty(pte)) {
-                       clear_pmd_entry(pmd);
+                       clear_pmd_entry(kvm, pmd, addr);
                        range = PMD_SIZE;
                        if (pmd_empty(pmd)) {
-                               clear_pud_entry(pud);
+                               clear_pud_entry(kvm, pud, addr);
                                range = PUD_SIZE;
                        }
                }
@@ -165,14 +176,14 @@ void free_boot_hyp_pgd(void)
        mutex_lock(&kvm_hyp_pgd_mutex);
 
        if (boot_hyp_pgd) {
-               unmap_range(boot_hyp_pgd, hyp_idmap_start, PAGE_SIZE);
-               unmap_range(boot_hyp_pgd, TRAMPOLINE_VA, PAGE_SIZE);
+               unmap_range(NULL, boot_hyp_pgd, hyp_idmap_start, PAGE_SIZE);
+               unmap_range(NULL, boot_hyp_pgd, TRAMPOLINE_VA, PAGE_SIZE);
                kfree(boot_hyp_pgd);
                boot_hyp_pgd = NULL;
        }
 
        if (hyp_pgd)
-               unmap_range(hyp_pgd, TRAMPOLINE_VA, PAGE_SIZE);
+               unmap_range(NULL, hyp_pgd, TRAMPOLINE_VA, PAGE_SIZE);
 
        kfree(init_bounce_page);
        init_bounce_page = NULL;
@@ -200,9 +211,10 @@ void free_hyp_pgds(void)
 
        if (hyp_pgd) {
                for (addr = PAGE_OFFSET; virt_addr_valid(addr); addr += PGDIR_SIZE)
-                       unmap_range(hyp_pgd, KERN_TO_HYP(addr), PGDIR_SIZE);
+                       unmap_range(NULL, hyp_pgd, KERN_TO_HYP(addr), PGDIR_SIZE);
                for (addr = VMALLOC_START; is_vmalloc_addr((void*)addr); addr += PGDIR_SIZE)
-                       unmap_range(hyp_pgd, KERN_TO_HYP(addr), PGDIR_SIZE);
+                       unmap_range(NULL, hyp_pgd, KERN_TO_HYP(addr), PGDIR_SIZE);
+
                kfree(hyp_pgd);
                hyp_pgd = NULL;
        }
@@ -393,7 +405,7 @@ int kvm_alloc_stage2_pgd(struct kvm *kvm)
  */
 static void unmap_stage2_range(struct kvm *kvm, phys_addr_t start, u64 size)
 {
-       unmap_range(kvm->arch.pgd, start, size);
+       unmap_range(kvm, kvm->arch.pgd, start, size);
 }
 
 /**
@@ -675,7 +687,6 @@ static void handle_hva_to_gpa(struct kvm *kvm,
 static void kvm_unmap_hva_handler(struct kvm *kvm, gpa_t gpa, void *data)
 {
        unmap_stage2_range(kvm, gpa, PAGE_SIZE);
-       kvm_tlb_flush_vmid_ipa(kvm, gpa);
 }
 
 int kvm_unmap_hva(struct kvm *kvm, unsigned long hva)
index 2acdff4..180b302 100644 (file)
@@ -174,6 +174,7 @@ clkevt32k_next_event(unsigned long delta, struct clock_event_device *dev)
 static struct clock_event_device clkevt = {
        .name           = "at91_tick",
        .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+       .shift          = 32,
        .rating         = 150,
        .set_next_event = clkevt32k_next_event,
        .set_mode       = clkevt32k_mode,
@@ -264,9 +265,11 @@ void __init at91rm9200_timer_init(void)
        at91_st_write(AT91_ST_RTMR, 1);
 
        /* Setup timer clockevent, with minimum of two ticks (important!!) */
+       clkevt.mult = div_sc(AT91_SLOW_CLOCK, NSEC_PER_SEC, clkevt.shift);
+       clkevt.max_delta_ns = clockevent_delta2ns(AT91_ST_ALMV, &clkevt);
+       clkevt.min_delta_ns = clockevent_delta2ns(2, &clkevt) + 1;
        clkevt.cpumask = cpumask_of(0);
-       clockevents_config_and_register(&clkevt, AT91_SLOW_CLOCK,
-                                       2, AT91_ST_ALMV);
+       clockevents_register_device(&clkevt);
 
        /* register clocksource */
        clocksource_register_hz(&clk32k, AT91_SLOW_CLOCK);
index 13cdbcd..c7d670d 100644 (file)
@@ -223,13 +223,7 @@ static void __init at91sam9n12_map_io(void)
        at91_init_sram(0, AT91SAM9N12_SRAM_BASE, AT91SAM9N12_SRAM_SIZE);
 }
 
-void __init at91sam9n12_initialize(void)
-{
-       at91_extern_irq = (1 << AT91SAM9N12_ID_IRQ0);
-}
-
 AT91_SOC_START(at91sam9n12)
        .map_io = at91sam9n12_map_io,
        .register_clocks = at91sam9n12_register_clocks,
-       .init = at91sam9n12_initialize,
 AT91_SOC_END
index 31df120..2bd7f51 100644 (file)
@@ -179,9 +179,9 @@ extern void __iomem *at91_pmc_base;
 #define                AT91_PMC_PCR_CMD        (0x1  <<  12)           /* Command (read=0, write=1) */
 #define                AT91_PMC_PCR_DIV(n)     ((n)  <<  16)           /* Divisor Value */
 #define                        AT91_PMC_PCR_DIV0       0x0                     /* Peripheral clock is MCK */
-#define                        AT91_PMC_PCR_DIV2       0x2                     /* Peripheral clock is MCK/2 */
-#define                        AT91_PMC_PCR_DIV4       0x4                     /* Peripheral clock is MCK/4 */
-#define                        AT91_PMC_PCR_DIV8       0x8                     /* Peripheral clock is MCK/8 */
+#define                        AT91_PMC_PCR_DIV2       0x1                     /* Peripheral clock is MCK/2 */
+#define                        AT91_PMC_PCR_DIV4       0x2                     /* Peripheral clock is MCK/4 */
+#define                        AT91_PMC_PCR_DIV8       0x3                     /* Peripheral clock is MCK/8 */
 #define                AT91_PMC_PCR_EN         (0x1  <<  28)           /* Enable */
 
 #endif
index d19edff..ff18fc2 100644 (file)
@@ -250,6 +250,7 @@ config MACH_ARMLEX4210
 config MACH_UNIVERSAL_C210
        bool "Mobile UNIVERSAL_C210 Board"
        select CLKSRC_MMIO
+       select CLKSRC_SAMSUNG_PWM
        select CPU_EXYNOS4210
        select EXYNOS4_SETUP_FIMC
        select EXYNOS4_SETUP_FIMD0
@@ -281,7 +282,6 @@ config MACH_UNIVERSAL_C210
        select S5P_DEV_TV
        select S5P_GPIO_INT
        select S5P_SETUP_MIPIPHY
-       select SAMSUNG_HRT
        help
          Machine support for Samsung Mobile Universal S5PC210 Reference
          Board.
@@ -410,6 +410,7 @@ config MACH_EXYNOS4_DT
        depends on ARCH_EXYNOS4
        select ARM_AMBA
        select CLKSRC_OF
+       select CLKSRC_SAMSUNG_PWM if CPU_EXYNOS4210
        select CPU_EXYNOS4210
        select KEYBOARD_SAMSUNG if INPUT_KEYBOARD
        select PINCTRL
index 745e304..f7e504b 100644 (file)
  */
 
 #include <linux/kernel.h>
+#include <linux/bitops.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/irqchip.h>
 #include <linux/io.h>
 #include <linux/device.h>
 #include <linux/gpio.h>
+#include <clocksource/samsung_pwm.h>
 #include <linux/sched.h>
 #include <linux/serial_core.h>
 #include <linux/of.h>
@@ -302,6 +304,13 @@ static struct map_desc exynos5440_iodesc0[] __initdata = {
        },
 };
 
+static struct samsung_pwm_variant exynos4_pwm_variant = {
+       .bits           = 32,
+       .div_base       = 0,
+       .has_tint_cstat = true,
+       .tclk_mask      = 0,
+};
+
 void exynos4_restart(char mode, const char *cmd)
 {
        __raw_writel(0x1, S5P_SWRESET);
@@ -317,9 +326,16 @@ void exynos5_restart(char mode, const char *cmd)
                val = 0x1;
                addr = EXYNOS_SWRESET;
        } else if (of_machine_is_compatible("samsung,exynos5440")) {
+               u32 status;
                np = of_find_compatible_node(NULL, NULL, "samsung,exynos5440-clock");
+
+               addr = of_iomap(np, 0) + 0xbc;
+               status = __raw_readl(addr);
+
                addr = of_iomap(np, 0) + 0xcc;
-               val = (0xfff << 20) | (0x1 << 16);
+               val = __raw_readl(addr);
+
+               val = (val & 0xffff0000) | (status & 0xffff);
        } else {
                pr_err("%s: cannot support non-DT\n", __func__);
                return;
@@ -370,6 +386,8 @@ int __init exynos_fdt_map_chipid(unsigned long node, const char *uname,
 
 void __init exynos_init_io(struct map_desc *mach_desc, int size)
 {
+       debug_ll_io_init();
+
 #ifdef CONFIG_OF
        if (initial_boot_params)
                of_scan_flat_dt(exynos_fdt_map_chipid, NULL);
@@ -442,8 +460,20 @@ static void __init exynos5440_map_io(void)
        iotable_init(exynos5440_iodesc0, ARRAY_SIZE(exynos5440_iodesc0));
 }
 
+void __init exynos_set_timer_source(u8 channels)
+{
+       exynos4_pwm_variant.output_mask = BIT(SAMSUNG_PWM_NUM) - 1;
+       exynos4_pwm_variant.output_mask &= ~channels;
+}
+
 void __init exynos_init_time(void)
 {
+       unsigned int timer_irqs[SAMSUNG_PWM_NUM] = {
+               EXYNOS4_IRQ_TIMER0_VIC, EXYNOS4_IRQ_TIMER1_VIC,
+               EXYNOS4_IRQ_TIMER2_VIC, EXYNOS4_IRQ_TIMER3_VIC,
+               EXYNOS4_IRQ_TIMER4_VIC,
+       };
+
        if (of_have_populated_dt()) {
 #ifdef CONFIG_OF
                of_clk_init(NULL);
@@ -455,7 +485,14 @@ void __init exynos_init_time(void)
                exynos4_clk_init(NULL, !soc_is_exynos4210(), S5P_VA_CMU, readl(S5P_VA_CHIPID + 8) & 1);
                exynos4_clk_register_fixed_ext(xxti_f, xusbxti_f);
 #endif
-               mct_init(S5P_VA_SYSTIMER, EXYNOS4_IRQ_MCT_G0, EXYNOS4_IRQ_MCT_L0, EXYNOS4_IRQ_MCT_L1);
+#ifdef CONFIG_CLKSRC_SAMSUNG_PWM
+               if (soc_is_exynos4210() && samsung_rev() == EXYNOS4210_REV_0)
+                       samsung_pwm_clocksource_init(S3C_VA_TIMER,
+                                       timer_irqs, &exynos4_pwm_variant);
+               else
+#endif
+                       mct_init(S5P_VA_SYSTIMER, EXYNOS4_IRQ_MCT_G0,
+                                       EXYNOS4_IRQ_MCT_L0, EXYNOS4_IRQ_MCT_L1);
        }
 }
 
index 60dd35c..11fc1e2 100644 (file)
@@ -32,6 +32,8 @@ void exynos4_clk_register_fixed_ext(unsigned long, unsigned long);
 
 void exynos_firmware_init(void);
 
+void exynos_set_timer_source(u8 channels);
+
 #ifdef CONFIG_PM_GENERIC_DOMAINS
 int exynos_pm_late_initcall(void);
 #else
index 7dbbfec..296090e 100644 (file)
 #ifndef __ASM_ARCH_PM_CORE_H
 #define __ASM_ARCH_PM_CORE_H __FILE__
 
+#include <linux/of.h>
 #include <mach/regs-pmu.h>
 
+#ifdef CONFIG_PINCTRL_EXYNOS
+extern u32 exynos_get_eint_wake_mask(void);
+#else
+static inline u32 exynos_get_eint_wake_mask(void) { return 0xffffffff; }
+#endif
+
 static inline void s3c_pm_debug_init_uart(void)
 {
        /* nothing here yet */
@@ -27,7 +34,12 @@ static inline void s3c_pm_debug_init_uart(void)
 
 static inline void s3c_pm_arch_prepare_irqs(void)
 {
-       __raw_writel(s3c_irqwake_eintmask, S5P_EINT_WAKEUP_MASK);
+       u32 eintmask = s3c_irqwake_eintmask;
+
+       if (of_have_populated_dt())
+               eintmask = exynos_get_eint_wake_mask();
+
+       __raw_writel(eintmask, S5P_EINT_WAKEUP_MASK);
        __raw_writel(s3c_irqwake_intmask & ~(1 << 31), S5P_WAKEUP_MASK);
 }
 
index 327d50d..74ddb2b 100644 (file)
@@ -41,7 +41,6 @@
 #include <plat/mfc.h>
 #include <plat/sdhci.h>
 #include <plat/fimc-core.h>
-#include <plat/samsung-time.h>
 #include <plat/camport.h>
 
 #include <mach/map.h>
@@ -1094,7 +1093,7 @@ static void __init universal_map_io(void)
 {
        exynos_init_io(NULL, 0);
        s3c24xx_init_uarts(universal_uartcfgs, ARRAY_SIZE(universal_uartcfgs));
-       samsung_set_timer_source(SAMSUNG_PWM2, SAMSUNG_PWM4);
+       exynos_set_timer_source(BIT(2) | BIT(4));
        xxti_f = 0;
        xusbxti_f = 24000000;
 }
@@ -1154,7 +1153,7 @@ MACHINE_START(UNIVERSAL_C210, "UNIVERSAL_C210")
        .map_io         = universal_map_io,
        .init_machine   = universal_machine_init,
        .init_late      = exynos_init_late,
-       .init_time      = samsung_timer_init,
+       .init_time      = exynos_init_time,
        .reserve        = &universal_reserve,
        .restart        = exynos4_restart,
 MACHINE_END
index 1512590..4e3148c 100644 (file)
@@ -177,17 +177,18 @@ int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode)
 static const char *step_sels[] = { "osc", "pll2_pfd2_396m", };
 static const char *pll1_sw_sels[]      = { "pll1_sys", "step", };
 static const char *periph_pre_sels[]   = { "pll2_bus", "pll2_pfd2_396m", "pll2_pfd0_352m", "pll2_198m", };
-static const char *periph_clk2_sels[]  = { "pll3_usb_otg", "osc", };
+static const char *periph_clk2_sels[]  = { "pll3_usb_otg", "osc", "osc", "dummy", };
+static const char *periph2_clk2_sels[] = { "pll3_usb_otg", "pll2_bus", };
 static const char *periph_sels[]       = { "periph_pre", "periph_clk2", };
 static const char *periph2_sels[]      = { "periph2_pre", "periph2_clk2", };
-static const char *axi_sels[]          = { "periph", "pll2_pfd2_396m", "pll3_pfd1_540m", };
+static const char *axi_sels[]          = { "periph", "pll2_pfd2_396m", "periph", "pll3_pfd1_540m", };
 static const char *audio_sels[]        = { "pll4_post_div", "pll3_pfd2_508m", "pll3_pfd3_454m", "pll3_usb_otg", };
 static const char *gpu_axi_sels[]      = { "axi", "ahb", };
 static const char *gpu2d_core_sels[]   = { "axi", "pll3_usb_otg", "pll2_pfd0_352m", "pll2_pfd2_396m", };
 static const char *gpu3d_core_sels[]   = { "mmdc_ch0_axi", "pll3_usb_otg", "pll2_pfd1_594m", "pll2_pfd2_396m", };
-static const char *gpu3d_shader_sels[] = { "mmdc_ch0_axi", "pll3_usb_otg", "pll2_pfd1_594m", "pll2_pfd9_720m", };
+static const char *gpu3d_shader_sels[] = { "mmdc_ch0_axi", "pll3_usb_otg", "pll2_pfd1_594m", "pll3_pfd0_720m", };
 static const char *ipu_sels[]          = { "mmdc_ch0_axi", "pll2_pfd2_396m", "pll3_120m", "pll3_pfd1_540m", };
-static const char *ldb_di_sels[]       = { "pll5_video", "pll2_pfd0_352m", "pll2_pfd2_396m", "mmdc_ch1_axi", "pll3_usb_otg", };
+static const char *ldb_di_sels[]       = { "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd2_396m", "mmdc_ch1_axi", "pll3_usb_otg", };
 static const char *ipu_di_pre_sels[]   = { "mmdc_ch0_axi", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll3_pfd1_540m", };
 static const char *ipu1_di0_sels[]     = { "ipu1_di0_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", };
 static const char *ipu1_di1_sels[]     = { "ipu1_di1_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", };
@@ -369,8 +370,8 @@ int __init mx6q_clocks_init(void)
        clk[pll1_sw]          = imx_clk_mux("pll1_sw",          base + 0xc,  2,  1, pll1_sw_sels,      ARRAY_SIZE(pll1_sw_sels));
        clk[periph_pre]       = imx_clk_mux("periph_pre",       base + 0x18, 18, 2, periph_pre_sels,   ARRAY_SIZE(periph_pre_sels));
        clk[periph2_pre]      = imx_clk_mux("periph2_pre",      base + 0x18, 21, 2, periph_pre_sels,   ARRAY_SIZE(periph_pre_sels));
-       clk[periph_clk2_sel]  = imx_clk_mux("periph_clk2_sel",  base + 0x18, 12, 1, periph_clk2_sels,  ARRAY_SIZE(periph_clk2_sels));
-       clk[periph2_clk2_sel] = imx_clk_mux("periph2_clk2_sel", base + 0x18, 20, 1, periph_clk2_sels,  ARRAY_SIZE(periph_clk2_sels));
+       clk[periph_clk2_sel]  = imx_clk_mux("periph_clk2_sel",  base + 0x18, 12, 2, periph_clk2_sels,  ARRAY_SIZE(periph_clk2_sels));
+       clk[periph2_clk2_sel] = imx_clk_mux("periph2_clk2_sel", base + 0x18, 20, 1, periph2_clk2_sels, ARRAY_SIZE(periph2_clk2_sels));
        clk[axi_sel]          = imx_clk_mux("axi_sel",          base + 0x14, 6,  2, axi_sels,          ARRAY_SIZE(axi_sels));
        clk[esai_sel]         = imx_clk_mux("esai_sel",         base + 0x20, 19, 2, audio_sels,        ARRAY_SIZE(audio_sels));
        clk[asrc_sel]         = imx_clk_mux("asrc_sel",         base + 0x30, 7,  2, audio_sels,        ARRAY_SIZE(audio_sels));
@@ -498,7 +499,7 @@ int __init mx6q_clocks_init(void)
        clk[ldb_di1]      = imx_clk_gate2("ldb_di1",       "ldb_di1_podf",      base + 0x74, 14);
        clk[ipu2_di1]     = imx_clk_gate2("ipu2_di1",      "ipu2_di1_sel",      base + 0x74, 10);
        clk[hsi_tx]       = imx_clk_gate2("hsi_tx",        "hsi_tx_podf",       base + 0x74, 16);
-       clk[mlb]          = imx_clk_gate2("mlb",           "pll8_mlb",          base + 0x74, 18);
+       clk[mlb]          = imx_clk_gate2("mlb",           "axi",               base + 0x74, 18);
        clk[mmdc_ch0_axi] = imx_clk_gate2("mmdc_ch0_axi",  "mmdc_ch0_axi_podf", base + 0x74, 20);
        clk[mmdc_ch1_axi] = imx_clk_gate2("mmdc_ch1_axi",  "mmdc_ch1_axi_podf", base + 0x74, 22);
        clk[ocram]        = imx_clk_gate2("ocram",         "ahb",               base + 0x74, 28);
index 67b9c48..627f16f 100644 (file)
        .section ".text.head", "ax"
 
 #ifdef CONFIG_SMP
+diag_reg_offset:
+       .word   g_diag_reg - .
+
+       .macro  set_diag_reg
+       adr     r0, diag_reg_offset
+       ldr     r1, [r0]
+       add     r1, r1, r0              @ r1 = physical &g_diag_reg
+       ldr     r0, [r1]
+       mcr     p15, 0, r0, c15, c0, 1  @ write diagnostic register
+       .endm
+
 ENTRY(v7_secondary_startup)
        bl      v7_invalidate_l1
+       set_diag_reg
        b       secondary_startup
 ENDPROC(v7_secondary_startup)
 #endif
index 4a69305..c6e1ab5 100644 (file)
@@ -12,6 +12,7 @@
 
 #include <linux/init.h>
 #include <linux/smp.h>
+#include <asm/cacheflush.h>
 #include <asm/page.h>
 #include <asm/smp_scu.h>
 #include <asm/mach/map.h>
@@ -21,6 +22,7 @@
 
 #define SCU_STANDBY_ENABLE     (1 << 5)
 
+u32 g_diag_reg;
 static void __iomem *scu_base;
 
 static struct map_desc scu_io_desc __initdata = {
@@ -80,6 +82,18 @@ void imx_smp_prepare(void)
 static void __init imx_smp_prepare_cpus(unsigned int max_cpus)
 {
        imx_smp_prepare();
+
+       /*
+        * The diagnostic register holds the errata bits.  Mostly bootloader
+        * does not bring up secondary cores, so that when errata bits are set
+        * in bootloader, they are set only for boot cpu.  But on a SMP
+        * configuration, it should be equally done on every single core.
+        * Read the register from boot cpu here, and will replicate it into
+        * secondary cores when booting them.
+        */
+       asm("mrc p15, 0, %0, c15, c0, 1" : "=r" (g_diag_reg) : : "cc");
+       __cpuc_flush_dcache_area(&g_diag_reg, sizeof(g_diag_reg));
+       outer_clean_range(__pa(&g_diag_reg), __pa(&g_diag_reg + 1));
 }
 
 struct smp_operations  imx_smp_ops __initdata = {
index acb0187..4695d5f 100644 (file)
@@ -41,13 +41,3 @@ void __init qnap_dt_ts219_init(void)
 
        pm_power_off = qnap_tsx1x_power_off;
 }
-
-/* FIXME: Will not work with DT. Maybe use MPP40_GPIO? */
-static int __init ts219_pci_init(void)
-{
-       if (machine_is_ts219())
-               kirkwood_pcie_init(KW_PCIE0);
-
-       return 0;
-}
-subsys_initcall(ts219_pci_init);
index c2cae69..f389228 100644 (file)
@@ -528,12 +528,6 @@ void __init kirkwood_init_early(void)
 {
        orion_time_set_base(TIMER_VIRT_BASE);
 
-       /*
-        * Some Kirkwood devices allocate their coherent buffers from atomic
-        * context. Increase size of atomic coherent pool to make sure such
-        * the allocations won't fail.
-        */
-       init_dma_coherent_pool_size(SZ_1M);
        mvebu_mbus_init("marvell,kirkwood-mbus",
                        BRIDGE_WINS_BASE, BRIDGE_WINS_SZ,
                        DDR_WINDOW_CPU_BASE, DDR_WINDOW_CPU_SZ);
index 283abff..e1267d6 100644 (file)
@@ -124,7 +124,7 @@ static void __init qnap_ts219_init(void)
 static int __init ts219_pci_init(void)
 {
        if (machine_is_ts219())
-               kirkwood_pcie_init(KW_PCIE0);
+               kirkwood_pcie_init(KW_PCIE1 | KW_PCIE0);
 
        return 0;
 }
index e11acbb..80a8bca 100644 (file)
@@ -15,6 +15,7 @@ config ARCH_MVEBU
        select MVEBU_CLK_GATING
        select MVEBU_MBUS
        select ZONE_DMA if ARM_LPAE
+       select ARCH_REQUIRE_GPIOLIB
 
 if ARCH_MVEBU
 
index 42a4cb3..1c48890 100644 (file)
@@ -53,13 +53,6 @@ void __init armada_370_xp_init_early(void)
 {
        char *mbus_soc_name;
 
-       /*
-        * Some Armada 370/XP devices allocate their coherent buffers
-        * from atomic context. Increase size of atomic coherent pool
-        * to make sure such the allocations won't fail.
-        */
-       init_dma_coherent_pool_size(SZ_1M);
-
        /*
         * This initialization will be replaced by a DT-based
         * initialization once the mvebu-mbus driver gains DT support.
index 53e8391..5476669 100644 (file)
@@ -32,15 +32,21 @@ ENTRY(ll_set_cpu_coherent)
 
        /* Add CPU to SMP group - Atomic */
        add     r3, r0, #ARMADA_XP_CFB_CTL_REG_OFFSET
-       ldr     r2, [r3]
+1:
+       ldrex   r2, [r3]
        orr     r2, r2, r1
-       str     r2, [r3]
+       strex   r0, r2, [r3]
+       cmp     r0, #0
+       bne 1b
 
        /* Enable coherency on CPU - Atomic */
-       add     r3, r0, #ARMADA_XP_CFB_CFG_REG_OFFSET
-       ldr     r2, [r3]
+       add     r3, r3, #ARMADA_XP_CFB_CFG_REG_OFFSET
+1:
+       ldrex   r2, [r3]
        orr     r2, r2, r1
-       str     r2, [r3]
+       strex   r0, r2, [r3]
+       cmp     r0, #0
+       bne 1b
 
        dsb
 
index 68ab858..a94b3a7 100644 (file)
@@ -345,6 +345,7 @@ static int __init omap1_system_dma_init(void)
                dev_err(&pdev->dev,
                        "%s: Memory allocation failed for d->chan!\n",
                        __func__);
+               ret = -ENOMEM;
                goto exit_release_d;
        }
 
index 6ebc780..af3544c 100644 (file)
@@ -454,9 +454,29 @@ DEFINE_CLK_GATE(cefuse_fck, "sys_clkin_ck", &sys_clkin_ck, 0x0,
  */
 DEFINE_CLK_FIXED_FACTOR(clkdiv32k_ck, "clk_24mhz", &clk_24mhz, 0x0, 1, 732);
 
-DEFINE_CLK_GATE(clkdiv32k_ick, "clkdiv32k_ck", &clkdiv32k_ck, 0x0,
-               AM33XX_CM_PER_CLKDIV32K_CLKCTRL, AM33XX_MODULEMODE_SWCTRL_SHIFT,
-               0x0, NULL);
+static struct clk clkdiv32k_ick;
+
+static const char *clkdiv32k_ick_parent_names[] = {
+       "clkdiv32k_ck",
+};
+
+static const struct clk_ops clkdiv32k_ick_ops = {
+       .enable         = &omap2_dflt_clk_enable,
+       .disable        = &omap2_dflt_clk_disable,
+       .is_enabled     = &omap2_dflt_clk_is_enabled,
+       .init           = &omap2_init_clk_clkdm,
+};
+
+static struct clk_hw_omap clkdiv32k_ick_hw = {
+       .hw     = {
+               .clk    = &clkdiv32k_ick,
+       },
+       .enable_reg     = AM33XX_CM_PER_CLKDIV32K_CLKCTRL,
+       .enable_bit     = AM33XX_MODULEMODE_SWCTRL_SHIFT,
+       .clkdm_name     = "clk_24mhz_clkdm",
+};
+
+DEFINE_STRUCT_CLK(clkdiv32k_ick, clkdiv32k_ick_parent_names, clkdiv32k_ick_ops);
 
 /* "usbotg_fck" is an additional clock and not really a modulemode */
 DEFINE_CLK_GATE(usbotg_fck, "dpll_per_ck", &dpll_per_ck, 0x0,
index d25a95f..7341eff 100644 (file)
@@ -1356,13 +1356,27 @@ static void _enable_sysc(struct omap_hwmod *oh)
 
        clkdm = _get_clkdm(oh);
        if (sf & SYSC_HAS_SIDLEMODE) {
+               if (oh->flags & HWMOD_SWSUP_SIDLE ||
+                   oh->flags & HWMOD_SWSUP_SIDLE_ACT) {
+                       idlemode = HWMOD_IDLEMODE_NO;
+               } else {
+                       if (sf & SYSC_HAS_ENAWAKEUP)
+                               _enable_wakeup(oh, &v);
+                       if (oh->class->sysc->idlemodes & SIDLE_SMART_WKUP)
+                               idlemode = HWMOD_IDLEMODE_SMART_WKUP;
+                       else
+                               idlemode = HWMOD_IDLEMODE_SMART;
+               }
+
+               /*
+                * This is special handling for some IPs like
+                * 32k sync timer. Force them to idle!
+                */
                clkdm_act = (clkdm && clkdm->flags & CLKDM_ACTIVE_WITH_MPU);
                if (clkdm_act && !(oh->class->sysc->idlemodes &
                                   (SIDLE_SMART | SIDLE_SMART_WKUP)))
                        idlemode = HWMOD_IDLEMODE_FORCE;
-               else
-                       idlemode = (oh->flags & HWMOD_SWSUP_SIDLE) ?
-                               HWMOD_IDLEMODE_NO : HWMOD_IDLEMODE_SMART;
+
                _set_slave_idlemode(oh, idlemode, &v);
        }
 
@@ -1391,10 +1405,6 @@ static void _enable_sysc(struct omap_hwmod *oh)
            (sf & SYSC_HAS_CLOCKACTIVITY))
                _set_clockactivity(oh, oh->class->sysc->clockact, &v);
 
-       /* If slave is in SMARTIDLE, also enable wakeup */
-       if ((sf & SYSC_HAS_SIDLEMODE) && !(oh->flags & HWMOD_SWSUP_SIDLE))
-               _enable_wakeup(oh, &v);
-
        _write_sysconfig(v, oh);
 
        /*
@@ -1430,13 +1440,16 @@ static void _idle_sysc(struct omap_hwmod *oh)
        sf = oh->class->sysc->sysc_flags;
 
        if (sf & SYSC_HAS_SIDLEMODE) {
-               /* XXX What about HWMOD_IDLEMODE_SMART_WKUP? */
-               if (oh->flags & HWMOD_SWSUP_SIDLE ||
-                   !(oh->class->sysc->idlemodes &
-                     (SIDLE_SMART | SIDLE_SMART_WKUP)))
+               if (oh->flags & HWMOD_SWSUP_SIDLE) {
                        idlemode = HWMOD_IDLEMODE_FORCE;
-               else
-                       idlemode = HWMOD_IDLEMODE_SMART;
+               } else {
+                       if (sf & SYSC_HAS_ENAWAKEUP)
+                               _enable_wakeup(oh, &v);
+                       if (oh->class->sysc->idlemodes & SIDLE_SMART_WKUP)
+                               idlemode = HWMOD_IDLEMODE_SMART_WKUP;
+                       else
+                               idlemode = HWMOD_IDLEMODE_SMART;
+               }
                _set_slave_idlemode(oh, idlemode, &v);
        }
 
@@ -1455,10 +1468,6 @@ static void _idle_sysc(struct omap_hwmod *oh)
                _set_master_standbymode(oh, idlemode, &v);
        }
 
-       /* If slave is in SMARTIDLE, also enable wakeup */
-       if ((sf & SYSC_HAS_SIDLEMODE) && !(oh->flags & HWMOD_SWSUP_SIDLE))
-               _enable_wakeup(oh, &v);
-
        _write_sysconfig(v, oh);
 }
 
@@ -2065,7 +2074,7 @@ static int _omap4_get_context_lost(struct omap_hwmod *oh)
  * do so is present in the hwmod data, then call it and pass along the
  * return value; otherwise, return 0.
  */
-static int __init _enable_preprogram(struct omap_hwmod *oh)
+static int _enable_preprogram(struct omap_hwmod *oh)
 {
        if (!oh->class->enable_preprogram)
                return 0;
@@ -2245,42 +2254,6 @@ static int _idle(struct omap_hwmod *oh)
        return 0;
 }
 
-/**
- * omap_hwmod_set_ocp_autoidle - set the hwmod's OCP autoidle bit
- * @oh: struct omap_hwmod *
- * @autoidle: desired AUTOIDLE bitfield value (0 or 1)
- *
- * Sets the IP block's OCP autoidle bit in hardware, and updates our
- * local copy. Intended to be used by drivers that require
- * direct manipulation of the AUTOIDLE bits.
- * Returns -EINVAL if @oh is null or is not in the ENABLED state, or passes
- * along the return value from _set_module_autoidle().
- *
- * Any users of this function should be scrutinized carefully.
- */
-int omap_hwmod_set_ocp_autoidle(struct omap_hwmod *oh, u8 autoidle)
-{
-       u32 v;
-       int retval = 0;
-       unsigned long flags;
-
-       if (!oh || oh->_state != _HWMOD_STATE_ENABLED)
-               return -EINVAL;
-
-       spin_lock_irqsave(&oh->_lock, flags);
-
-       v = oh->_sysc_cache;
-
-       retval = _set_module_autoidle(oh, autoidle, &v);
-
-       if (!retval)
-               _write_sysconfig(v, oh);
-
-       spin_unlock_irqrestore(&oh->_lock, flags);
-
-       return retval;
-}
-
 /**
  * _shutdown - shutdown an omap_hwmod
  * @oh: struct omap_hwmod *
@@ -3179,38 +3152,6 @@ error:
        return ret;
 }
 
-/**
- * omap_hwmod_set_slave_idlemode - set the hwmod's OCP slave idlemode
- * @oh: struct omap_hwmod *
- * @idlemode: SIDLEMODE field bits (shifted to bit 0)
- *
- * Sets the IP block's OCP slave idlemode in hardware, and updates our
- * local copy.  Intended to be used by drivers that have some erratum
- * that requires direct manipulation of the SIDLEMODE bits.  Returns
- * -EINVAL if @oh is null, or passes along the return value from
- * _set_slave_idlemode().
- *
- * XXX Does this function have any current users?  If not, we should
- * remove it; it is better to let the rest of the hwmod code handle this.
- * Any users of this function should be scrutinized carefully.
- */
-int omap_hwmod_set_slave_idlemode(struct omap_hwmod *oh, u8 idlemode)
-{
-       u32 v;
-       int retval = 0;
-
-       if (!oh)
-               return -EINVAL;
-
-       v = oh->_sysc_cache;
-
-       retval = _set_slave_idlemode(oh, idlemode, &v);
-       if (!retval)
-               _write_sysconfig(v, oh);
-
-       return retval;
-}
-
 /**
  * omap_hwmod_lookup - look up a registered omap_hwmod by name
  * @name: name of the omap_hwmod to look up
index fe59629..0c898f5 100644 (file)
@@ -463,6 +463,9 @@ struct omap_hwmod_omap4_prcm {
  *     is kept in force-standby mode. Failing to do so causes PM problems
  *     with musb on OMAP3630 at least. Note that musb has a dedicated register
  *     to control MSTANDBY signal when MIDLEMODE is set to force-standby.
+ * HWMOD_SWSUP_SIDLE_ACT: omap_hwmod code should manually bring the module
+ *     out of idle, but rely on smart-idle to the put it back in idle,
+ *     so the wakeups are still functional (Only known case for now is UART)
  */
 #define HWMOD_SWSUP_SIDLE                      (1 << 0)
 #define HWMOD_SWSUP_MSTANDBY                   (1 << 1)
@@ -476,6 +479,7 @@ struct omap_hwmod_omap4_prcm {
 #define HWMOD_EXT_OPT_MAIN_CLK                 (1 << 9)
 #define HWMOD_BLOCK_WFI                                (1 << 10)
 #define HWMOD_FORCE_MSTANDBY                   (1 << 11)
+#define HWMOD_SWSUP_SIDLE_ACT                  (1 << 12)
 
 /*
  * omap_hwmod._int_flags definitions
@@ -641,9 +645,6 @@ int omap_hwmod_read_hardreset(struct omap_hwmod *oh, const char *name);
 int omap_hwmod_enable_clocks(struct omap_hwmod *oh);
 int omap_hwmod_disable_clocks(struct omap_hwmod *oh);
 
-int omap_hwmod_set_slave_idlemode(struct omap_hwmod *oh, u8 idlemode);
-int omap_hwmod_set_ocp_autoidle(struct omap_hwmod *oh, u8 autoidle);
-
 int omap_hwmod_reset(struct omap_hwmod *oh);
 void omap_hwmod_ocp_barrier(struct omap_hwmod *oh);
 
index c8c64b3..d05fc7b 100644 (file)
@@ -512,6 +512,7 @@ struct omap_hwmod omap2xxx_uart1_hwmod = {
        .mpu_irqs       = omap2_uart1_mpu_irqs,
        .sdma_reqs      = omap2_uart1_sdma_reqs,
        .main_clk       = "uart1_fck",
+       .flags          = HWMOD_SWSUP_SIDLE_ACT,
        .prcm           = {
                .omap2 = {
                        .module_offs = CORE_MOD,
@@ -531,6 +532,7 @@ struct omap_hwmod omap2xxx_uart2_hwmod = {
        .mpu_irqs       = omap2_uart2_mpu_irqs,
        .sdma_reqs      = omap2_uart2_sdma_reqs,
        .main_clk       = "uart2_fck",
+       .flags          = HWMOD_SWSUP_SIDLE_ACT,
        .prcm           = {
                .omap2 = {
                        .module_offs = CORE_MOD,
@@ -550,6 +552,7 @@ struct omap_hwmod omap2xxx_uart3_hwmod = {
        .mpu_irqs       = omap2_uart3_mpu_irqs,
        .sdma_reqs      = omap2_uart3_sdma_reqs,
        .main_clk       = "uart3_fck",
+       .flags          = HWMOD_SWSUP_SIDLE_ACT,
        .prcm           = {
                .omap2 = {
                        .module_offs = CORE_MOD,
index 01d8f32..075f7cc 100644 (file)
@@ -1995,6 +1995,7 @@ static struct omap_hwmod am33xx_uart1_hwmod = {
        .name           = "uart1",
        .class          = &uart_class,
        .clkdm_name     = "l4_wkup_clkdm",
+       .flags          = HWMOD_SWSUP_SIDLE_ACT,
        .mpu_irqs       = am33xx_uart1_irqs,
        .sdma_reqs      = uart1_edma_reqs,
        .main_clk       = "dpll_per_m2_div4_wkupdm_ck",
@@ -2015,6 +2016,7 @@ static struct omap_hwmod am33xx_uart2_hwmod = {
        .name           = "uart2",
        .class          = &uart_class,
        .clkdm_name     = "l4ls_clkdm",
+       .flags          = HWMOD_SWSUP_SIDLE_ACT,
        .mpu_irqs       = am33xx_uart2_irqs,
        .sdma_reqs      = uart1_edma_reqs,
        .main_clk       = "dpll_per_m2_div4_ck",
@@ -2042,6 +2044,7 @@ static struct omap_hwmod am33xx_uart3_hwmod = {
        .name           = "uart3",
        .class          = &uart_class,
        .clkdm_name     = "l4ls_clkdm",
+       .flags          = HWMOD_SWSUP_SIDLE_ACT,
        .mpu_irqs       = am33xx_uart3_irqs,
        .sdma_reqs      = uart3_edma_reqs,
        .main_clk       = "dpll_per_m2_div4_ck",
@@ -2062,6 +2065,7 @@ static struct omap_hwmod am33xx_uart4_hwmod = {
        .name           = "uart4",
        .class          = &uart_class,
        .clkdm_name     = "l4ls_clkdm",
+       .flags          = HWMOD_SWSUP_SIDLE_ACT,
        .mpu_irqs       = am33xx_uart4_irqs,
        .sdma_reqs      = uart1_edma_reqs,
        .main_clk       = "dpll_per_m2_div4_ck",
@@ -2082,6 +2086,7 @@ static struct omap_hwmod am33xx_uart5_hwmod = {
        .name           = "uart5",
        .class          = &uart_class,
        .clkdm_name     = "l4ls_clkdm",
+       .flags          = HWMOD_SWSUP_SIDLE_ACT,
        .mpu_irqs       = am33xx_uart5_irqs,
        .sdma_reqs      = uart1_edma_reqs,
        .main_clk       = "dpll_per_m2_div4_ck",
@@ -2102,6 +2107,7 @@ static struct omap_hwmod am33xx_uart6_hwmod = {
        .name           = "uart6",
        .class          = &uart_class,
        .clkdm_name     = "l4ls_clkdm",
+       .flags          = HWMOD_SWSUP_SIDLE_ACT,
        .mpu_irqs       = am33xx_uart6_irqs,
        .sdma_reqs      = uart1_edma_reqs,
        .main_clk       = "dpll_per_m2_div4_ck",
index 4083606..31c7126 100644 (file)
@@ -490,6 +490,7 @@ static struct omap_hwmod omap3xxx_uart1_hwmod = {
        .mpu_irqs       = omap2_uart1_mpu_irqs,
        .sdma_reqs      = omap2_uart1_sdma_reqs,
        .main_clk       = "uart1_fck",
+       .flags          = HWMOD_SWSUP_SIDLE_ACT,
        .prcm           = {
                .omap2 = {
                        .module_offs = CORE_MOD,
@@ -508,6 +509,7 @@ static struct omap_hwmod omap3xxx_uart2_hwmod = {
        .mpu_irqs       = omap2_uart2_mpu_irqs,
        .sdma_reqs      = omap2_uart2_sdma_reqs,
        .main_clk       = "uart2_fck",
+       .flags          = HWMOD_SWSUP_SIDLE_ACT,
        .prcm           = {
                .omap2 = {
                        .module_offs = CORE_MOD,
@@ -526,6 +528,7 @@ static struct omap_hwmod omap3xxx_uart3_hwmod = {
        .mpu_irqs       = omap2_uart3_mpu_irqs,
        .sdma_reqs      = omap2_uart3_sdma_reqs,
        .main_clk       = "uart3_fck",
+       .flags          = HWMOD_SWSUP_SIDLE_ACT,
        .prcm           = {
                .omap2 = {
                        .module_offs = OMAP3430_PER_MOD,
@@ -555,6 +558,7 @@ static struct omap_hwmod omap36xx_uart4_hwmod = {
        .mpu_irqs       = uart4_mpu_irqs,
        .sdma_reqs      = uart4_sdma_reqs,
        .main_clk       = "uart4_fck",
+       .flags          = HWMOD_SWSUP_SIDLE_ACT,
        .prcm           = {
                .omap2 = {
                        .module_offs = OMAP3430_PER_MOD,
index eaba9dc..848b6dc 100644 (file)
@@ -3434,6 +3434,7 @@ static struct omap_hwmod omap44xx_uart1_hwmod = {
        .name           = "uart1",
        .class          = &omap44xx_uart_hwmod_class,
        .clkdm_name     = "l4_per_clkdm",
+       .flags          = HWMOD_SWSUP_SIDLE_ACT,
        .mpu_irqs       = omap44xx_uart1_irqs,
        .sdma_reqs      = omap44xx_uart1_sdma_reqs,
        .main_clk       = "func_48m_fclk",
@@ -3462,6 +3463,7 @@ static struct omap_hwmod omap44xx_uart2_hwmod = {
        .name           = "uart2",
        .class          = &omap44xx_uart_hwmod_class,
        .clkdm_name     = "l4_per_clkdm",
+       .flags          = HWMOD_SWSUP_SIDLE_ACT,
        .mpu_irqs       = omap44xx_uart2_irqs,
        .sdma_reqs      = omap44xx_uart2_sdma_reqs,
        .main_clk       = "func_48m_fclk",
@@ -3490,7 +3492,8 @@ static struct omap_hwmod omap44xx_uart3_hwmod = {
        .name           = "uart3",
        .class          = &omap44xx_uart_hwmod_class,
        .clkdm_name     = "l4_per_clkdm",
-       .flags          = HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET,
+       .flags          = HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET |
+                               HWMOD_SWSUP_SIDLE_ACT,
        .mpu_irqs       = omap44xx_uart3_irqs,
        .sdma_reqs      = omap44xx_uart3_sdma_reqs,
        .main_clk       = "func_48m_fclk",
@@ -3519,6 +3522,7 @@ static struct omap_hwmod omap44xx_uart4_hwmod = {
        .name           = "uart4",
        .class          = &omap44xx_uart_hwmod_class,
        .clkdm_name     = "l4_per_clkdm",
+       .flags          = HWMOD_SWSUP_SIDLE_ACT,
        .mpu_irqs       = omap44xx_uart4_irqs,
        .sdma_reqs      = omap44xx_uart4_sdma_reqs,
        .main_clk       = "func_48m_fclk",
index 8396b5b..f660156 100644 (file)
@@ -95,38 +95,9 @@ static void omap_uart_enable_wakeup(struct device *dev, bool enable)
                omap_hwmod_disable_wakeup(od->hwmods[0]);
 }
 
-/*
- * Errata i291: [UART]:Cannot Acknowledge Idle Requests
- * in Smartidle Mode When Configured for DMA Operations.
- * WA: configure uart in force idle mode.
- */
-static void omap_uart_set_noidle(struct device *dev)
-{
-       struct platform_device *pdev = to_platform_device(dev);
-       struct omap_device *od = to_omap_device(pdev);
-
-       omap_hwmod_set_slave_idlemode(od->hwmods[0], HWMOD_IDLEMODE_NO);
-}
-
-static void omap_uart_set_smartidle(struct device *dev)
-{
-       struct platform_device *pdev = to_platform_device(dev);
-       struct omap_device *od = to_omap_device(pdev);
-       u8 idlemode;
-
-       if (od->hwmods[0]->class->sysc->idlemodes & SIDLE_SMART_WKUP)
-               idlemode = HWMOD_IDLEMODE_SMART_WKUP;
-       else
-               idlemode = HWMOD_IDLEMODE_SMART;
-
-       omap_hwmod_set_slave_idlemode(od->hwmods[0], idlemode);
-}
-
 #else
 static void omap_uart_enable_wakeup(struct device *dev, bool enable)
 {}
-static void omap_uart_set_noidle(struct device *dev) {}
-static void omap_uart_set_smartidle(struct device *dev) {}
 #endif /* CONFIG_PM */
 
 #ifdef CONFIG_OMAP_MUX
@@ -299,8 +270,6 @@ void __init omap_serial_init_port(struct omap_board_data *bdata,
        omap_up.uartclk = OMAP24XX_BASE_BAUD * 16;
        omap_up.flags = UPF_BOOT_AUTOCONF;
        omap_up.get_context_loss_count = omap_pm_get_dev_context_loss_count;
-       omap_up.set_forceidle = omap_uart_set_smartidle;
-       omap_up.set_noidle = omap_uart_set_noidle;
        omap_up.enable_wakeup = omap_uart_enable_wakeup;
        omap_up.dma_rx_buf_size = info->dma_rx_buf_size;
        omap_up.dma_rx_timeout = info->dma_rx_timeout;
index b97fd67..f8a6db9 100644 (file)
@@ -199,13 +199,6 @@ void __init orion5x_init_early(void)
 
        orion_time_set_base(TIMER_VIRT_BASE);
 
-       /*
-        * Some Orion5x devices allocate their coherent buffers from atomic
-        * context. Increase size of atomic coherent pool to make sure such
-        * the allocations won't fail.
-        */
-       init_dma_coherent_pool_size(SZ_1M);
-
        /* Initialize the MBUS driver */
        orion5x_pcie_id(&dev, &rev);
        if (dev == MV88F5281_DEV_ID)
index 9105285..b9594e9 100644 (file)
@@ -212,8 +212,8 @@ static struct platform_device *marzen_devices[] __initdata = {
 static struct usb_phy *phy;
 static int usb_power_on(struct platform_device *pdev)
 {
-       if (!phy)
-               return -EIO;
+       if (IS_ERR(phy))
+               return PTR_ERR(phy);
 
        pm_runtime_enable(&pdev->dev);
        pm_runtime_get_sync(&pdev->dev);
@@ -225,7 +225,7 @@ static int usb_power_on(struct platform_device *pdev)
 
 static void usb_power_off(struct platform_device *pdev)
 {
-       if (!phy)
+       if (IS_ERR(phy))
                return;
 
        usb_phy_shutdown(phy);
index fdf3894..9696f36 100644 (file)
@@ -252,7 +252,7 @@ static struct sh_timer_config cmt10_platform_data = {
        .name = "CMT10",
        .channel_offset = 0x10,
        .timer_bit = 0,
-       .clockevent_rating = 125,
+       .clockevent_rating = 80,
        .clocksource_rating = 125,
 };
 
index d259c78..5b045e3 100644 (file)
@@ -1,5 +1,6 @@
 config ARCH_SUNXI
        bool "Allwinner A1X SOCs" if ARCH_MULTI_V7
+       select ARCH_REQUIRE_GPIOLIB
        select CLKSRC_MMIO
        select CLKSRC_OF
        select COMMON_CLK
index 9e8bdfa..31e69a0 100644 (file)
@@ -307,11 +307,6 @@ static int tegra_emc_probe(struct platform_device *pdev)
        }
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(&pdev->dev, "missing register base\n");
-               return -ENOMEM;
-       }
-
        emc_regbase = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(emc_regbase))
                return PTR_ERR(emc_regbase);
index 6a4387e..b19b072 100644 (file)
@@ -51,6 +51,7 @@ config MACH_MOP500
        bool "U8500 Development platform, MOP500 versions"
        select I2C
        select I2C_NOMADIK
+       select REGULATOR
        select REGULATOR_FIXED_VOLTAGE
        select SOC_BUS
        select UX500_SOC_DB8500
index 33c353b..d6b7c85 100644 (file)
@@ -374,6 +374,7 @@ static struct ab8500_regulator_reg_init ab8500_reg_init[] = {
 static struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS] = {
        /* supplies to the display/camera */
        [AB8500_LDO_AUX1] = {
+               .supply_regulator = "ab8500-ext-supply3",
                .constraints = {
                        .name = "V-DISPLAY",
                        .min_uV = 2800000,
@@ -387,6 +388,7 @@ static struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS] = {
        },
        /* supplies to the on-board eMMC */
        [AB8500_LDO_AUX2] = {
+               .supply_regulator = "ab8500-ext-supply3",
                .constraints = {
                        .name = "V-eMMC1",
                        .min_uV = 1100000,
@@ -402,6 +404,7 @@ static struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS] = {
        },
        /* supply for VAUX3, supplies to SDcard slots */
        [AB8500_LDO_AUX3] = {
+               .supply_regulator = "ab8500-ext-supply3",
                .constraints = {
                        .name = "V-MMC-SD",
                        .min_uV = 1100000,
index 3cd555a..78389de 100644 (file)
@@ -623,7 +623,7 @@ static void __init mop500_init_machine(void)
        sdi0_reg_info.gpios[0].gpio = GPIO_SDMMC_1V8_3V_SEL;
 
        mop500_pinmaps_init();
-       parent = u8500_init_devices(&ab8500_platdata);
+       parent = u8500_init_devices();
 
        for (i = 0; i < ARRAY_SIZE(mop500_platform_devs); i++)
                mop500_platform_devs[i]->dev.parent = parent;
@@ -660,7 +660,7 @@ static void __init snowball_init_machine(void)
        sdi0_reg_info.gpios[0].gpio = SNOWBALL_SDMMC_1V8_3V_GPIO;
 
        snowball_pinmaps_init();
-       parent = u8500_init_devices(&ab8500_platdata);
+       parent = u8500_init_devices();
 
        for (i = 0; i < ARRAY_SIZE(snowball_platform_devs); i++)
                snowball_platform_devs[i]->dev.parent = parent;
@@ -698,7 +698,7 @@ static void __init hrefv60_init_machine(void)
        sdi0_reg_info.gpios[0].gpio = HREFV60_SDMMC_1V8_3V_GPIO;
 
        hrefv60_pinmaps_init();
-       parent = u8500_init_devices(&ab8500_platdata);
+       parent = u8500_init_devices();
 
        for (i = 0; i < ARRAY_SIZE(mop500_platform_devs); i++)
                mop500_platform_devs[i]->dev.parent = parent;
index e90b5ab..46cca52 100644 (file)
@@ -206,7 +206,7 @@ static struct device * __init db8500_soc_device_init(void)
 /*
  * This function is called from the board init
  */
-struct device * __init u8500_init_devices(struct ab8500_platform_data *ab8500)
+struct device * __init u8500_init_devices(void)
 {
        struct device *parent;
        int i;
@@ -220,8 +220,6 @@ struct device * __init u8500_init_devices(struct ab8500_platform_data *ab8500)
        for (i = 0; i < ARRAY_SIZE(platform_devs); i++)
                platform_devs[i]->dev.parent = parent;
 
-       db8500_prcmu_device.dev.platform_data = ab8500;
-
        platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs));
 
        return parent;
@@ -278,7 +276,7 @@ static struct of_dev_auxdata u8500_auxdata_lookup[] __initdata = {
        OF_DEV_AUXDATA("st,nomadik-i2c", 0x8012a000, "nmk-i2c.4", NULL),
        OF_DEV_AUXDATA("stericsson,db8500-prcmu", 0x80157000, "db8500-prcmu",
                        &db8500_prcmu_pdata),
-       OF_DEV_AUXDATA("smsc,lan9115", 0x50000000, "smsc911x", NULL),
+       OF_DEV_AUXDATA("smsc,lan9115", 0x50000000, "smsc911x.0", NULL),
        /* Requires device name bindings. */
        OF_DEV_AUXDATA("stericsson,nmk-pinctrl", U8500_PRCMU_BASE,
                "pinctrl-db8500", NULL),
index 317a2be..a45dd09 100644 (file)
@@ -21,6 +21,7 @@
 #include <asm/proc-fns.h>
 
 #include "db8500-regs.h"
+#include "id.h"
 
 static atomic_t master = ATOMIC_INIT(0);
 static DEFINE_SPINLOCK(master_lock);
@@ -114,6 +115,9 @@ static struct cpuidle_driver ux500_idle_driver = {
 
 int __init ux500_idle_init(void)
 {
+       if (!(cpu_is_u8500_family() || cpu_is_ux540_family()))
+               return -ENODEV;
+
        /* Configure wake up reasons */
        prcmu_enable_wakeups(PRCMU_WAKEUP(ARM) | PRCMU_WAKEUP(RTC) |
                             PRCMU_WAKEUP(ABB));
index bddce2b..cad3ca8 100644 (file)
@@ -18,7 +18,7 @@
 void __init ux500_map_io(void);
 extern void __init u8500_map_io(void);
 
-extern struct device * __init u8500_init_devices(struct ab8500_platform_data *ab8500);
+extern struct device * __init u8500_init_devices(void);
 
 extern void __init ux500_init_irq(void);
 extern void __init ux500_init_late(void);
index 1dd281e..f5c33df 100644 (file)
@@ -173,6 +173,7 @@ static const char * const vt8500_dt_compat[] = {
        "wm,wm8505",
        "wm,wm8750",
        "wm,wm8850",
+       NULL
 };
 
 DT_MACHINE_START(WMT_DT, "VIA/Wondermedia SoC (Device Tree Support)")
index 251f827..c019b7a 100644 (file)
@@ -383,7 +383,7 @@ static struct resource orion_ge10_shared_resources[] = {
 
 static struct platform_device orion_ge10_shared = {
        .name           = MV643XX_ETH_SHARED_NAME,
-       .id             = 1,
+       .id             = 2,
        .dev            = {
                .platform_data  = &orion_ge10_shared_data,
        },
@@ -398,8 +398,8 @@ static struct resource orion_ge10_resources[] = {
 
 static struct platform_device orion_ge10 = {
        .name           = MV643XX_ETH_NAME,
-       .id             = 1,
-       .num_resources  = 2,
+       .id             = 2,
+       .num_resources  = 1,
        .resource       = orion_ge10_resources,
        .dev            = {
                .coherent_dma_mask      = DMA_BIT_MASK(32),
@@ -432,7 +432,7 @@ static struct resource orion_ge11_shared_resources[] = {
 
 static struct platform_device orion_ge11_shared = {
        .name           = MV643XX_ETH_SHARED_NAME,
-       .id             = 1,
+       .id             = 3,
        .dev            = {
                .platform_data  = &orion_ge11_shared_data,
        },
@@ -447,8 +447,8 @@ static struct resource orion_ge11_resources[] = {
 
 static struct platform_device orion_ge11 = {
        .name           = MV643XX_ETH_NAME,
-       .id             = 1,
-       .num_resources  = 2,
+       .id             = 3,
+       .num_resources  = 1,
        .resource       = orion_ge11_resources,
        .dev            = {
                .coherent_dma_mask      = DMA_BIT_MASK(32),
index e06fc5f..d9a24f6 100644 (file)
@@ -10,6 +10,7 @@
 
 #ifndef __PLAT_COMMON_H
 #include <linux/mv643xx_eth.h>
+#include <linux/platform_data/usb-ehci-orion.h>
 
 struct dsa_platform_data;
 struct mv_sata_platform_data;
index ca07cb1..79690f2 100644 (file)
@@ -381,11 +381,6 @@ static int s3c_adc_probe(struct platform_device *pdev)
        }
 
        regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!regs) {
-               dev_err(dev, "failed to find registers\n");
-               return -ENXIO;
-       }
-
        adc->regs = devm_ioremap_resource(dev, regs);
        if (IS_ERR(adc->regs))
                return PTR_ERR(adc->regs);
index 30c2fe2..0f9c3f4 100644 (file)
@@ -311,9 +311,9 @@ struct platform_device s5p_device_jpeg = {
 #ifdef CONFIG_S5P_DEV_FIMD0
 static struct resource s5p_fimd0_resource[] = {
        [0] = DEFINE_RES_MEM(S5P_PA_FIMD0, SZ_32K),
-       [1] = DEFINE_RES_IRQ(IRQ_FIMD0_VSYNC),
-       [2] = DEFINE_RES_IRQ(IRQ_FIMD0_FIFO),
-       [3] = DEFINE_RES_IRQ(IRQ_FIMD0_SYSTEM),
+       [1] = DEFINE_RES_IRQ_NAMED(IRQ_FIMD0_VSYNC, "vsync"),
+       [2] = DEFINE_RES_IRQ_NAMED(IRQ_FIMD0_FIFO, "fifo"),
+       [3] = DEFINE_RES_IRQ_NAMED(IRQ_FIMD0_SYSTEM, "lcd_sys"),
 };
 
 struct platform_device s5p_device_fimd0 = {
index 438b248..02b66d7 100644 (file)
@@ -66,6 +66,9 @@ uart_rd(unsigned int reg)
 
 static void putc(int ch)
 {
+       if (!config_enabled(CONFIG_DEBUG_LL))
+               return;
+
        if (uart_rd(S3C2410_UFCON) & S3C2410_UFCON_FIFOMODE) {
                int level;
 
@@ -118,7 +121,12 @@ static void arch_decomp_error(const char *x)
 #ifdef CONFIG_S3C_BOOT_UART_FORCE_FIFO
 static inline void arch_enable_uart_fifo(void)
 {
-       u32 fifocon = uart_rd(S3C2410_UFCON);
+       u32 fifocon;
+
+       if (!config_enabled(CONFIG_DEBUG_LL))
+               return;
+
+       fifocon = uart_rd(S3C2410_UFCON);
 
        if (!(fifocon & S3C2410_UFCON_FIFOMODE)) {
                fifocon |= S3C2410_UFCON_RESETBOTH;
index 323ce1a..46e1749 100644 (file)
@@ -60,7 +60,7 @@ ENTRY(vfp_testing_entry)
        str     r11, [r10, #TI_PREEMPT]
 #endif
        ldr     r0, VFP_arch_address
-       str     r5, [r0]                @ known non-zero value
+       str     r0, [r0]                @ set to non-zero value
        mov     pc, r9                  @ we have handled the fault
 ENDPROC(vfp_testing_entry)
 
index d30042e..13609e0 100644 (file)
@@ -152,11 +152,12 @@ int xen_unmap_domain_mfn_range(struct vm_area_struct *vma,
 }
 EXPORT_SYMBOL_GPL(xen_unmap_domain_mfn_range);
 
-static int __init xen_secondary_init(unsigned int cpu)
+static void __init xen_percpu_init(void *unused)
 {
        struct vcpu_register_vcpu_info info;
        struct vcpu_info *vcpup;
        int err;
+       int cpu = get_cpu();
 
        pr_info("Xen: initializing cpu%d\n", cpu);
        vcpup = per_cpu_ptr(xen_vcpu_info, cpu);
@@ -165,14 +166,10 @@ static int __init xen_secondary_init(unsigned int cpu)
        info.offset = offset_in_page(vcpup);
 
        err = HYPERVISOR_vcpu_op(VCPUOP_register_vcpu_info, cpu, &info);
-       if (err) {
-               pr_debug("register_vcpu_info failed: err=%d\n", err);
-       } else {
-               /* This cpu is using the registered vcpu info, even if
-                  later ones fail to. */
-               per_cpu(xen_vcpu, cpu) = vcpup;
-       }
-       return 0;
+       BUG_ON(err);
+       per_cpu(xen_vcpu, cpu) = vcpup;
+
+       enable_percpu_irq(xen_events_irq, 0);
 }
 
 static void xen_restart(char str, const char *cmd)
@@ -208,7 +205,6 @@ static int __init xen_guest_init(void)
        const char *version = NULL;
        const char *xen_prefix = "xen,xen-";
        struct resource res;
-       int i;
 
        node = of_find_compatible_node(NULL, NULL, "xen,xen");
        if (!node) {
@@ -265,19 +261,23 @@ static int __init xen_guest_init(void)
                                               sizeof(struct vcpu_info));
        if (xen_vcpu_info == NULL)
                return -ENOMEM;
-       for_each_online_cpu(i)
-               xen_secondary_init(i);
 
        gnttab_init();
        if (!xen_initial_domain())
                xenbus_probe(NULL);
 
+       return 0;
+}
+core_initcall(xen_guest_init);
+
+static int __init xen_pm_init(void)
+{
        pm_power_off = xen_power_off;
        arm_pm_restart = xen_restart;
 
        return 0;
 }
-core_initcall(xen_guest_init);
+subsys_initcall(xen_pm_init);
 
 static irqreturn_t xen_arm_callback(int irq, void *arg)
 {
@@ -285,11 +285,6 @@ static irqreturn_t xen_arm_callback(int irq, void *arg)
        return IRQ_HANDLED;
 }
 
-static __init void xen_percpu_enable_events(void *unused)
-{
-       enable_percpu_irq(xen_events_irq, 0);
-}
-
 static int __init xen_init_events(void)
 {
        if (!xen_domain() || xen_events_irq < 0)
@@ -303,7 +298,7 @@ static int __init xen_init_events(void)
                return -EINVAL;
        }
 
-       on_each_cpu(xen_percpu_enable_events, NULL, 0);
+       on_each_cpu(xen_percpu_init, NULL, 0);
 
        return 0;
 }
index 48347dc..56b3f6d 100644 (file)
@@ -122,8 +122,6 @@ endmenu
 
 menu "Kernel Features"
 
-source "kernel/time/Kconfig"
-
 config ARM64_64K_PAGES
        bool "Enable 64KB pages support"
        help
index c8eedc6..5aceb83 100644 (file)
@@ -82,7 +82,7 @@
 
        .macro  enable_dbg_if_not_stepping, tmp
        mrs     \tmp, mdscr_el1
-       tbnz    \tmp, #1, 9990f
+       tbnz    \tmp, #0, 9990f
        enable_dbg
 9990:
        .endm
index 12f2249..58125bf 100644 (file)
@@ -389,7 +389,7 @@ __SYSCALL(364, sys_perf_event_open)
 __SYSCALL(365, compat_sys_recvmmsg)
 __SYSCALL(366, sys_accept4)
 __SYSCALL(367, sys_fanotify_init)
-__SYSCALL(368, compat_sys_fanotify_mark_wrapper)
+__SYSCALL(368, compat_sys_fanotify_mark)
 __SYSCALL(369, sys_prlimit64)
 __SYSCALL(370, sys_name_to_handle_at)
 __SYSCALL(371, compat_sys_open_by_handle_at)
index 7df1aad..41b4f62 100644 (file)
@@ -34,6 +34,7 @@ EXPORT_SYMBOL(__strnlen_user);
 EXPORT_SYMBOL(__strncpy_from_user);
 
 EXPORT_SYMBOL(copy_page);
+EXPORT_SYMBOL(clear_page);
 
 EXPORT_SYMBOL(__copy_from_user);
 EXPORT_SYMBOL(__copy_to_user);
index 0c3ba9f..f4726dc 100644 (file)
@@ -136,8 +136,6 @@ void disable_debug_monitors(enum debug_el el)
  */
 static void clear_os_lock(void *unused)
 {
-       asm volatile("msr mdscr_el1, %0" : : "r" (0));
-       isb();
        asm volatile("msr oslar_el1, %0" : : "r" (0));
        isb();
 }
index ac974f4..fbb6e18 100644 (file)
@@ -95,7 +95,7 @@ static void early_write(struct console *con, const char *s, unsigned n)
        }
 }
 
-static struct console early_console = {
+static struct console early_console_dev = {
        .name =         "earlycon",
        .write =        early_write,
        .flags =        CON_PRINTBUFFER | CON_BOOT,
@@ -145,7 +145,8 @@ static int __init setup_early_printk(char *buf)
                early_base = early_io_map(paddr, EARLYCON_IOBASE);
 
        printch = match->printch;
-       register_console(&early_console);
+       early_console = &early_console_dev;
+       register_console(&early_console_dev);
 
        return 0;
 }
index c7e0470..1d13142 100644 (file)
@@ -390,6 +390,16 @@ el0_sync_compat:
        b.eq    el0_fpsimd_exc
        cmp     x24, #ESR_EL1_EC_UNKNOWN        // unknown exception in EL0
        b.eq    el0_undef
+       cmp     x24, #ESR_EL1_EC_CP15_32        // CP15 MRC/MCR trap
+       b.eq    el0_undef
+       cmp     x24, #ESR_EL1_EC_CP15_64        // CP15 MRRC/MCRR trap
+       b.eq    el0_undef
+       cmp     x24, #ESR_EL1_EC_CP14_MR        // CP14 MRC/MCR trap
+       b.eq    el0_undef
+       cmp     x24, #ESR_EL1_EC_CP14_LS        // CP14 LDC/STC trap
+       b.eq    el0_undef
+       cmp     x24, #ESR_EL1_EC_CP14_64        // CP14 MRRC/MCRR trap
+       b.eq    el0_undef
        cmp     x24, #ESR_EL1_EC_BREAKPT_EL0    // debug exception in EL0
        b.ge    el0_dbg
        b       el0_inv
index 6a9a532..add6ea6 100644 (file)
@@ -282,12 +282,13 @@ void __init setup_arch(char **cmdline_p)
 #endif
 }
 
-static int __init arm64_of_clk_init(void)
+static int __init arm64_device_init(void)
 {
        of_clk_init(NULL);
+       of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
        return 0;
 }
-arch_initcall(arm64_of_clk_init);
+arch_initcall(arm64_device_init);
 
 static DEFINE_PER_CPU(struct cpu, cpu_data);
 
@@ -305,13 +306,6 @@ static int __init topology_init(void)
 }
 subsys_initcall(topology_init);
 
-static int __init arm64_device_probe(void)
-{
-       of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-       return 0;
-}
-device_initcall(arm64_device_probe);
-
 static const char *hwcap_str[] = {
        "fp",
        "asimd",
index db01aa9..a1b19ed 100644 (file)
@@ -104,13 +104,6 @@ compat_sys_fallocate_wrapper:
        b       sys_fallocate
 ENDPROC(compat_sys_fallocate_wrapper)
 
-compat_sys_fanotify_mark_wrapper:
-       orr     x2, x2, x3, lsl #32
-       mov     w3, w4
-       mov     w4, w5
-       b       sys_fanotify_mark
-ENDPROC(compat_sys_fanotify_mark_wrapper)
-
 #undef __SYSCALL
 #define __SYSCALL(x, y)                .quad   y       // x
 
index 61d7dd2..f30852d 100644 (file)
@@ -267,7 +267,8 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
                return;
 #endif
 
-       if (show_unhandled_signals) {
+       if (show_unhandled_signals && unhandled_signal(current, SIGILL) &&
+           printk_ratelimit()) {
                pr_info("%s[%d]: undefined instruction: pc=%p\n",
                        current->comm, task_pid_nr(current), pc);
                dump_instr(KERN_INFO, regs);
@@ -294,7 +295,7 @@ asmlinkage long do_ni_syscall(struct pt_regs *regs)
        }
 #endif
 
-       if (show_unhandled_signals) {
+       if (show_unhandled_signals && printk_ratelimit()) {
                pr_info("%s[%d]: syscall %d\n", current->comm,
                        task_pid_nr(current), (int)regs->syscallno);
                dump_instr("", regs);
@@ -310,14 +311,20 @@ asmlinkage long do_ni_syscall(struct pt_regs *regs)
  */
 asmlinkage void bad_mode(struct pt_regs *regs, int reason, unsigned int esr)
 {
+       siginfo_t info;
+       void __user *pc = (void __user *)instruction_pointer(regs);
        console_verbose();
 
        pr_crit("Bad mode in %s handler detected, code 0x%08x\n",
                handler[reason], esr);
+       __show_regs(regs);
+
+       info.si_signo = SIGILL;
+       info.si_errno = 0;
+       info.si_code  = ILL_ILLOPC;
+       info.si_addr  = pc;
 
-       die("Oops - bad mode", regs, 0);
-       local_irq_disable();
-       panic("bad mode");
+       arm64_notify_die("Oops - bad mode", regs, &info, 0);
 }
 
 void __pte_error(const char *file, int line, unsigned long val)
index abe69b8..48a3860 100644 (file)
@@ -52,7 +52,7 @@ loop1:
        add     x2, x2, #4                      // add 4 (line length offset)
        mov     x4, #0x3ff
        and     x4, x4, x1, lsr #3              // find maximum number on the way size
-       clz     x5, x4                          // find bit position of way size increment
+       clz     w5, w4                          // find bit position of way size increment
        mov     x7, #0x7fff
        and     x7, x7, x1, lsr #13             // extract max number of the index size
 loop2:
index 98af6e7..1426468 100644 (file)
@@ -113,7 +113,8 @@ static void __do_user_fault(struct task_struct *tsk, unsigned long addr,
 {
        struct siginfo si;
 
-       if (show_unhandled_signals) {
+       if (show_unhandled_signals && unhandled_signal(tsk, sig) &&
+           printk_ratelimit()) {
                pr_info("%s[%d]: unhandled %s (%d) at 0x%08lx, esr 0x%03x\n",
                        tsk->comm, task_pid_nr(tsk), fault_name(esr), sig,
                        addr, esr);
index f1d8b9b..a82ae88 100644 (file)
@@ -119,8 +119,7 @@ ENTRY(__cpu_setup)
 
        mov     x0, #3 << 20
        msr     cpacr_el1, x0                   // Enable FP/ASIMD
-       mov     x0, #1
-       msr     oslar_el1, x0                   // Set the debug OS lock
+       msr     mdscr_el1, xzr                  // Reset mdscr_el1
        tlbi    vmalle1is                       // invalidate I + D TLBs
        /*
         * Memory region attributes for LPAE:
index bdc3558..549903c 100644 (file)
@@ -205,6 +205,11 @@ config ARCH_DISCONTIGMEM_ENABLE
 config ARCH_SPARSEMEM_ENABLE
        def_bool n
 
+config NODES_SHIFT
+       int
+       default "2"
+       depends on NEED_MULTIPLE_NODES
+
 source "mm/Kconfig"
 
 config OWNERSHIP_TRACE
index 4dd4f78..d22af85 100644 (file)
@@ -2,3 +2,4 @@
 generic-y      += clkdev.h
 generic-y      += exec.h
 generic-y      += trace_clock.h
+generic-y      += param.h
diff --git a/arch/avr32/include/asm/numnodes.h b/arch/avr32/include/asm/numnodes.h
deleted file mode 100644 (file)
index 0b864d7..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __ASM_AVR32_NUMNODES_H
-#define __ASM_AVR32_NUMNODES_H
-
-/* Max 4 nodes */
-#define NODES_SHIFT    2
-
-#endif /* __ASM_AVR32_NUMNODES_H */
diff --git a/arch/avr32/include/asm/param.h b/arch/avr32/include/asm/param.h
deleted file mode 100644 (file)
index 009a167..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef __ASM_AVR32_PARAM_H
-#define __ASM_AVR32_PARAM_H
-
-#include <uapi/asm/param.h>
-
-# define HZ            CONFIG_HZ
-# define USER_HZ       100             /* User interfaces are in "ticks" */
-# define CLOCKS_PER_SEC        (USER_HZ)       /* frequency at which times() counts */
-#endif /* __ASM_AVR32_PARAM_H */
index df53e7a..3b85ead 100644 (file)
@@ -33,3 +33,4 @@ header-y += termbits.h
 header-y += termios.h
 header-y += types.h
 header-y += unistd.h
+generic-y += param.h
diff --git a/arch/avr32/include/uapi/asm/param.h b/arch/avr32/include/uapi/asm/param.h
deleted file mode 100644 (file)
index d28aa5e..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef _UAPI__ASM_AVR32_PARAM_H
-#define _UAPI__ASM_AVR32_PARAM_H
-
-
-#ifndef HZ
-# define HZ            100
-#endif
-
-/* TODO: Should be configurable */
-#define EXEC_PAGESIZE  4096
-
-#ifndef NOGROUP
-# define NOGROUP       (-1)
-#endif
-
-#define MAXHOSTNAMELEN 64
-
-#endif /* _UAPI__ASM_AVR32_PARAM_H */
index 596f730..2c94129 100644 (file)
@@ -264,7 +264,7 @@ int apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab,
                        break;
                case R_AVR32_GOT18SW:
                        if ((relocation & 0xfffe0003) != 0
-                           && (relocation & 0xfffc0003) != 0xffff0000)
+                           && (relocation & 0xfffc0000) != 0xfffc0000)
                                return reloc_overflow(module, "R_AVR32_GOT18SW",
                                                     relocation);
                        relocation >>= 2;
index c3ffe3e..ef3a9de 100644 (file)
 #include <asm/tlbflush.h>
 #include <asm/machvec.h>
 
-#ifdef CONFIG_SMP
-# define tlb_fast_mode(tlb)    ((tlb)->nr == ~0U)
-#else
-# define tlb_fast_mode(tlb)    (1)
-#endif
-
 /*
  * If we can't allocate a page to make a big batch of page pointers
  * to work on, then just handle a few from the on-stack structure.
@@ -60,7 +54,7 @@
 
 struct mmu_gather {
        struct mm_struct        *mm;
-       unsigned int            nr;             /* == ~0U => fast mode */
+       unsigned int            nr;
        unsigned int            max;
        unsigned char           fullmm;         /* non-zero means full mm flush */
        unsigned char           need_flush;     /* really unmapped some PTEs? */
@@ -103,6 +97,7 @@ extern struct ia64_tr_entry *ia64_idtrs[NR_CPUS];
 static inline void
 ia64_tlb_flush_mmu (struct mmu_gather *tlb, unsigned long start, unsigned long end)
 {
+       unsigned long i;
        unsigned int nr;
 
        if (!tlb->need_flush)
@@ -141,13 +136,11 @@ ia64_tlb_flush_mmu (struct mmu_gather *tlb, unsigned long start, unsigned long e
 
        /* lastly, release the freed pages */
        nr = tlb->nr;
-       if (!tlb_fast_mode(tlb)) {
-               unsigned long i;
-               tlb->nr = 0;
-               tlb->start_addr = ~0UL;
-               for (i = 0; i < nr; ++i)
-                       free_page_and_swap_cache(tlb->pages[i]);
-       }
+
+       tlb->nr = 0;
+       tlb->start_addr = ~0UL;
+       for (i = 0; i < nr; ++i)
+               free_page_and_swap_cache(tlb->pages[i]);
 }
 
 static inline void __tlb_alloc_page(struct mmu_gather *tlb)
@@ -167,20 +160,7 @@ tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned int full_m
        tlb->mm = mm;
        tlb->max = ARRAY_SIZE(tlb->local);
        tlb->pages = tlb->local;
-       /*
-        * Use fast mode if only 1 CPU is online.
-        *
-        * It would be tempting to turn on fast-mode for full_mm_flush as well.  But this
-        * doesn't work because of speculative accesses and software prefetching: the page
-        * table of "mm" may (and usually is) the currently active page table and even
-        * though the kernel won't do any user-space accesses during the TLB shoot down, a
-        * compiler might use speculation or lfetch.fault on what happens to be a valid
-        * user-space address.  This in turn could trigger a TLB miss fault (or a VHPT
-        * walk) and re-insert a TLB entry we just removed.  Slow mode avoids such
-        * problems.  (We could make fast-mode work by switching the current task to a
-        * different "mm" during the shootdown.) --davidm 08/02/2002
-        */
-       tlb->nr = (num_online_cpus() == 1) ? ~0U : 0;
+       tlb->nr = 0;
        tlb->fullmm = full_mm_flush;
        tlb->start_addr = ~0UL;
 }
@@ -214,11 +194,6 @@ static inline int __tlb_remove_page(struct mmu_gather *tlb, struct page *page)
 {
        tlb->need_flush = 1;
 
-       if (tlb_fast_mode(tlb)) {
-               free_page_and_swap_cache(page);
-               return 1; /* avoid calling tlb_flush_mmu */
-       }
-
        if (!tlb->nr && tlb->pages == tlb->local)
                __tlb_alloc_page(tlb);
 
index 90d3109..19325e1 100644 (file)
@@ -1,55 +1,78 @@
-CONFIG_EXPERIMENTAL=y
 CONFIG_LOCALVERSION="-amiga"
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_FHANDLE=y
 CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_RELAY=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_LOG_BUF_SHIFT=16
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
-CONFIG_AMIGA=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_ATARI_PARTITION=y
+CONFIG_MAC_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+CONFIG_SUN_PARTITION=y
+# CONFIG_EFI_PARTITION is not set
+CONFIG_SYSV68_PARTITION=y
+CONFIG_IOSCHED_DEADLINE=m
 CONFIG_M68020=y
 CONFIG_M68030=y
 CONFIG_M68040=y
 CONFIG_M68060=y
-CONFIG_BINFMT_AOUT=m
-CONFIG_BINFMT_MISC=m
+CONFIG_AMIGA=y
 CONFIG_ZORRO=y
 CONFIG_AMIGA_PCMCIA=y
-CONFIG_HEARTBEAT=y
-CONFIG_PROC_HARDWARE=y
 CONFIG_ZORRO_NAMES=y
+# CONFIG_COMPACTION is not set
+CONFIG_CLEANCACHE=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_BINFMT_AOUT=m
+CONFIG_BINFMT_MISC=m
 CONFIG_NET=y
 CONFIG_PACKET=y
+CONFIG_PACKET_DIAG=m
 CONFIG_UNIX=y
+CONFIG_UNIX_DIAG=m
+CONFIG_XFRM_MIGRATE=y
 CONFIG_NET_KEY=y
-CONFIG_NET_KEY_MIGRATE=y
 CONFIG_INET=y
 CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
 CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE_DEMUX=m
 CONFIG_NET_IPGRE=m
 CONFIG_SYN_COOKIES=y
+CONFIG_NET_IPVTI=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
 CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
 CONFIG_INET_XFRM_MODE_BEET=m
+# CONFIG_INET_LRO is not set
 CONFIG_INET_DIAG=m
+CONFIG_INET_UDP_DIAG=m
 CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
-CONFIG_IPV6_ROUTE_INFO=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
-CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
-CONFIG_IPV6_TUNNEL=m
+CONFIG_IPV6_GRE=m
 CONFIG_NETFILTER=y
-CONFIG_NETFILTER_NETLINK_QUEUE=m
 CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CONNTRACK_ZONES=y
+# CONFIG_NF_CONNTRACK_PROCFS is not set
 # CONFIG_NF_CT_PROTO_DCCP is not set
 CONFIG_NF_CT_PROTO_UDPLITE=m
 CONFIG_NF_CONNTRACK_AMANDA=m
@@ -57,25 +80,37 @@ CONFIG_NF_CONNTRACK_FTP=m
 CONFIG_NF_CONNTRACK_H323=m
 CONFIG_NF_CONNTRACK_IRC=m
 CONFIG_NF_CONNTRACK_NETBIOS_NS=m
+CONFIG_NF_CONNTRACK_SNMP=m
 CONFIG_NF_CONNTRACK_PPTP=m
 CONFIG_NF_CONNTRACK_SANE=m
 CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NETFILTER_XT_SET=m
+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
 CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
 CONFIG_NETFILTER_XT_TARGET_DSCP=m
+CONFIG_NETFILTER_XT_TARGET_HMARK=m
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m
+CONFIG_NETFILTER_XT_TARGET_LOG=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_TEE=m
 CONFIG_NETFILTER_XT_TARGET_TRACE=m
 CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
+CONFIG_NETFILTER_XT_MATCH_BPF=m
 CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
 CONFIG_NETFILTER_XT_MATCH_COMMENT=m
 CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m
 CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
 CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
 CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m
 CONFIG_NETFILTER_XT_MATCH_DSCP=m
 CONFIG_NETFILTER_XT_MATCH_ESP=m
 CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
@@ -86,6 +121,8 @@ CONFIG_NETFILTER_XT_MATCH_LIMIT=m
 CONFIG_NETFILTER_XT_MATCH_MAC=m
 CONFIG_NETFILTER_XT_MATCH_MARK=m
 CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_NFACCT=m
+CONFIG_NETFILTER_XT_MATCH_OSF=m
 CONFIG_NETFILTER_XT_MATCH_OWNER=m
 CONFIG_NETFILTER_XT_MATCH_POLICY=m
 CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
@@ -99,22 +136,31 @@ CONFIG_NETFILTER_XT_MATCH_STRING=m
 CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
 CONFIG_NETFILTER_XT_MATCH_TIME=m
 CONFIG_NETFILTER_XT_MATCH_U32=m
+CONFIG_IP_SET=m
+CONFIG_IP_SET_BITMAP_IP=m
+CONFIG_IP_SET_BITMAP_IPMAC=m
+CONFIG_IP_SET_BITMAP_PORT=m
+CONFIG_IP_SET_HASH_IP=m
+CONFIG_IP_SET_HASH_IPPORT=m
+CONFIG_IP_SET_HASH_IPPORTIP=m
+CONFIG_IP_SET_HASH_IPPORTNET=m
+CONFIG_IP_SET_HASH_NET=m
+CONFIG_IP_SET_HASH_NETPORT=m
+CONFIG_IP_SET_HASH_NETIFACE=m
+CONFIG_IP_SET_LIST_SET=m
 CONFIG_NF_CONNTRACK_IPV4=m
-CONFIG_IP_NF_QUEUE=m
 CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_ADDRTYPE=m
 CONFIG_IP_NF_MATCH_AH=m
 CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_RPFILTER=m
 CONFIG_IP_NF_MATCH_TTL=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
-CONFIG_IP_NF_TARGET_LOG=m
 CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_NF_NAT=m
+CONFIG_NF_NAT_IPV4=m
 CONFIG_IP_NF_TARGET_MASQUERADE=m
 CONFIG_IP_NF_TARGET_NETMAP=m
 CONFIG_IP_NF_TARGET_REDIRECT=m
-CONFIG_NF_NAT_SNMP_BASIC=m
 CONFIG_IP_NF_MANGLE=m
 CONFIG_IP_NF_TARGET_CLUSTERIP=m
 CONFIG_IP_NF_TARGET_ECN=m
@@ -124,7 +170,6 @@ CONFIG_IP_NF_ARPTABLES=m
 CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
 CONFIG_NF_CONNTRACK_IPV6=m
-CONFIG_IP6_NF_QUEUE=m
 CONFIG_IP6_NF_IPTABLES=m
 CONFIG_IP6_NF_MATCH_AH=m
 CONFIG_IP6_NF_MATCH_EUI64=m
@@ -133,18 +178,30 @@ CONFIG_IP6_NF_MATCH_OPTS=m
 CONFIG_IP6_NF_MATCH_HL=m
 CONFIG_IP6_NF_MATCH_IPV6HEADER=m
 CONFIG_IP6_NF_MATCH_MH=m
+CONFIG_IP6_NF_MATCH_RPFILTER=m
 CONFIG_IP6_NF_MATCH_RT=m
 CONFIG_IP6_NF_TARGET_HL=m
-CONFIG_IP6_NF_TARGET_LOG=m
 CONFIG_IP6_NF_FILTER=m
 CONFIG_IP6_NF_TARGET_REJECT=m
 CONFIG_IP6_NF_MANGLE=m
 CONFIG_IP6_NF_RAW=m
+CONFIG_NF_NAT_IPV6=m
+CONFIG_IP6_NF_TARGET_MASQUERADE=m
+CONFIG_IP6_NF_TARGET_NPT=m
 CONFIG_IP_DCCP=m
 # CONFIG_IP_DCCP_CCID3 is not set
+CONFIG_SCTP_COOKIE_HMAC_SHA1=y
+CONFIG_RDS=m
+CONFIG_RDS_TCP=m
+CONFIG_L2TP=m
 CONFIG_ATALK=m
+CONFIG_BATMAN_ADV=m
+CONFIG_BATMAN_ADV_DAT=y
+# CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
 # CONFIG_FIRMWARE_IN_KERNEL is not set
+# CONFIG_FW_LOADER_USER_HELPER is not set
 CONFIG_CONNECTOR=m
 CONFIG_PARPORT=m
 CONFIG_PARPORT_AMIGA=m
@@ -154,11 +211,13 @@ CONFIG_AMIGA_FLOPPY=y
 CONFIG_AMIGA_Z2RAM=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_DRBD=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_ATA_OVER_ETH=m
 CONFIG_IDE=y
+CONFIG_IDE_GD_ATAPI=y
 CONFIG_BLK_DEV_IDECD=y
 CONFIG_BLK_DEV_GAYLE=y
 CONFIG_BLK_DEV_BUDDHA=y
@@ -172,57 +231,77 @@ CONFIG_BLK_DEV_SR=y
 CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
 CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_SAS_LIBSAS=m
-# CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set
-CONFIG_SCSI_SRP_ATTRS=m
-CONFIG_SCSI_SRP_TGT_ATTRS=y
+CONFIG_SCSI_SAS_ATTRS=m
 CONFIG_ISCSI_TCP=m
+CONFIG_ISCSI_BOOT_SYSFS=m
 CONFIG_A3000_SCSI=y
 CONFIG_A2091_SCSI=y
 CONFIG_GVP11_SCSI=y
 CONFIG_SCSI_A4000T=y
 CONFIG_SCSI_ZORRO7XX=y
 CONFIG_MD=y
-CONFIG_BLK_DEV_MD=m
 CONFIG_MD_LINEAR=m
 CONFIG_MD_RAID0=m
-CONFIG_MD_RAID1=m
-CONFIG_MD_RAID456=m
 CONFIG_BLK_DEV_DM=m
 CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_THIN_PROVISIONING=m
+CONFIG_DM_CACHE=m
 CONFIG_DM_MIRROR=m
+CONFIG_DM_RAID=m
 CONFIG_DM_ZERO=m
 CONFIG_DM_MULTIPATH=m
 CONFIG_DM_UEVENT=y
+CONFIG_TARGET_CORE=m
+CONFIG_TCM_IBLOCK=m
+CONFIG_TCM_FILEIO=m
+CONFIG_TCM_PSCSI=m
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=m
-CONFIG_MACVLAN=m
 CONFIG_EQUALIZER=m
+CONFIG_NET_TEAM=m
+CONFIG_NET_TEAM_MODE_BROADCAST=m
+CONFIG_NET_TEAM_MODE_ROUNDROBIN=m
+CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m
+CONFIG_NET_TEAM_MODE_LOADBALANCE=m
+CONFIG_VXLAN=m
+CONFIG_NETCONSOLE=m
+CONFIG_NETCONSOLE_DYNAMIC=y
 CONFIG_VETH=m
-CONFIG_NET_ETHERNET=y
-CONFIG_ARIADNE=y
+# CONFIG_NET_VENDOR_3COM is not set
 CONFIG_A2065=y
+CONFIG_ARIADNE=y
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_NET_VENDOR_FUJITSU is not set
+# CONFIG_NET_VENDOR_HP is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
 CONFIG_HYDRA=y
-CONFIG_ZORRO8390=y
 CONFIG_APNE=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
+CONFIG_ZORRO8390=y
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
 CONFIG_PPP=m
-CONFIG_PPP_FILTER=y
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=m
 CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_FILTER=y
 CONFIG_PPP_MPPE=m
 CONFIG_PPPOE=m
+CONFIG_PPTP=m
+CONFIG_PPPOL2TP=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
 CONFIG_SLIP=m
 CONFIG_SLIP_COMPRESSED=y
 CONFIG_SLIP_SMART=y
 CONFIG_SLIP_MODE_SLIP6=y
-CONFIG_NETCONSOLE=m
-CONFIG_NETCONSOLE_DYNAMIC=y
-CONFIG_INPUT_FF_MEMLESS=m
+# CONFIG_WLAN is not set
+CONFIG_INPUT_EVDEV=m
 CONFIG_KEYBOARD_AMIGA=y
 # CONFIG_KEYBOARD_ATKBD is not set
 # CONFIG_MOUSE_PS2 is not set
@@ -233,11 +312,14 @@ CONFIG_INPUT_MISC=y
 CONFIG_INPUT_M68K_BEEP=m
 # CONFIG_SERIO is not set
 CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_LEGACY_PTYS is not set
 # CONFIG_DEVKMEM is not set
 CONFIG_PRINTER=m
 # CONFIG_HW_RANDOM is not set
-CONFIG_GEN_RTC=m
-CONFIG_GEN_RTC_X=y
+CONFIG_NTP_PPS=y
+CONFIG_PPS_CLIENT_LDISC=m
+CONFIG_PPS_CLIENT_PARPORT=m
+CONFIG_PTP_1588_CLOCK=m
 # CONFIG_HWMON is not set
 CONFIG_FB=y
 CONFIG_FB_CIRRUS=y
@@ -252,48 +334,64 @@ CONFIG_SOUND=m
 CONFIG_DMASOUND_PAULA=m
 CONFIG_HID=m
 CONFIG_HIDRAW=y
+CONFIG_UHID=m
+# CONFIG_HID_GENERIC is not set
 # CONFIG_USB_SUPPORT is not set
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_MSM6242=m
+CONFIG_RTC_DRV_RP5C01=m
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_HEARTBEAT=y
+CONFIG_PROC_HARDWARE=y
 CONFIG_AMIGA_BUILTIN_SERIAL=y
 CONFIG_SERIAL_CONSOLE=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 # CONFIG_EXT3_FS_XATTR is not set
+CONFIG_EXT4_FS=y
 CONFIG_REISERFS_FS=m
 CONFIG_JFS_FS=m
 CONFIG_XFS_FS=m
 CONFIG_OCFS2_FS=m
-# CONFIG_OCFS2_FS_STATS is not set
 # CONFIG_OCFS2_DEBUG_MASKLOG is not set
+CONFIG_FANOTIFY=y
 CONFIG_QUOTA_NETLINK_INTERFACE=y
 # CONFIG_PRINT_QUOTA_WARNING is not set
-CONFIG_AUTOFS_FS=m
 CONFIG_AUTOFS4_FS=m
 CONFIG_FUSE_FS=m
+CONFIG_CUSE=m
 CONFIG_ISO9660_FS=y
 CONFIG_JOLIET=y
 CONFIG_ZISOFS=y
 CONFIG_UDF_FS=m
-CONFIG_MSDOS_FS=y
+CONFIG_MSDOS_FS=m
 CONFIG_VFAT_FS=m
 CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
 CONFIG_AFFS_FS=m
+CONFIG_ECRYPT_FS=m
+CONFIG_ECRYPT_FS_MESSAGING=y
 CONFIG_HFS_FS=m
 CONFIG_HFSPLUS_FS=m
 CONFIG_CRAMFS=m
 CONFIG_SQUASHFS=m
-CONFIG_MINIX_FS=y
+CONFIG_SQUASHFS_LZO=y
+CONFIG_MINIX_FS=m
+CONFIG_OMFS_FS=m
 CONFIG_HPFS_FS=m
+CONFIG_QNX4FS_FS=m
+CONFIG_QNX6FS_FS=m
 CONFIG_SYSV_FS=m
 CONFIG_UFS_FS=m
 CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
 CONFIG_NFS_V4=y
+CONFIG_NFS_SWAP=y
+CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
 CONFIG_NFSD_V3=y
-CONFIG_SMB_FS=m
-CONFIG_SMB_NLS_DEFAULT=y
+CONFIG_CIFS=m
+# CONFIG_CIFS_DEBUG is not set
 CONFIG_CODA_FS=m
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_CODEPAGE_737=m
@@ -332,10 +430,23 @@ CONFIG_NLS_ISO8859_14=m
 CONFIG_NLS_ISO8859_15=m
 CONFIG_NLS_KOI8_R=m
 CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_MAC_ROMAN=m
+CONFIG_NLS_MAC_CELTIC=m
+CONFIG_NLS_MAC_CENTEURO=m
+CONFIG_NLS_MAC_CROATIAN=m
+CONFIG_NLS_MAC_CYRILLIC=m
+CONFIG_NLS_MAC_GAELIC=m
+CONFIG_NLS_MAC_GREEK=m
+CONFIG_NLS_MAC_ICELAND=m
+CONFIG_NLS_MAC_INUIT=m
+CONFIG_NLS_MAC_ROMANIAN=m
+CONFIG_NLS_MAC_TURKISH=m
 CONFIG_DLM=m
 CONFIG_MAGIC_SYSRQ=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_ASYNC_RAID6_TEST=m
+CONFIG_ENCRYPTED_KEYS=m
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_USER=m
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_CRYPTD=m
 CONFIG_CRYPTO_TEST=m
@@ -345,19 +456,16 @@ CONFIG_CRYPTO_CTS=m
 CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_XTS=m
-CONFIG_CRYPTO_HMAC=y
 CONFIG_CRYPTO_XCBC=m
-CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_VMAC=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_RMD128=m
 CONFIG_CRYPTO_RMD160=m
 CONFIG_CRYPTO_RMD256=m
 CONFIG_CRYPTO_RMD320=m
-CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_ANUBIS=m
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_CAMELLIA=m
@@ -373,6 +481,14 @@ CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_ZLIB=m
 CONFIG_CRYPTO_LZO=m
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_USER_API_HASH=m
+CONFIG_CRYPTO_USER_API_SKCIPHER=m
 # CONFIG_CRYPTO_HW is not set
-CONFIG_CRC16=m
 CONFIG_CRC_T10DIF=y
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
+CONFIG_XZ_DEC_TEST=m
index 8f4f657..14dc6cc 100644 (file)
@@ -1,55 +1,76 @@
-CONFIG_EXPERIMENTAL=y
 CONFIG_LOCALVERSION="-apollo"
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_FHANDLE=y
 CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_RELAY=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_LOG_BUF_SHIFT=16
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
-CONFIG_APOLLO=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_AMIGA_PARTITION=y
+CONFIG_ATARI_PARTITION=y
+CONFIG_MAC_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+CONFIG_SUN_PARTITION=y
+# CONFIG_EFI_PARTITION is not set
+CONFIG_SYSV68_PARTITION=y
+CONFIG_IOSCHED_DEADLINE=m
 CONFIG_M68020=y
 CONFIG_M68030=y
 CONFIG_M68040=y
 CONFIG_M68060=y
+CONFIG_APOLLO=y
+# CONFIG_COMPACTION is not set
+CONFIG_CLEANCACHE=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_BINFMT_AOUT=m
 CONFIG_BINFMT_MISC=m
-CONFIG_HEARTBEAT=y
-CONFIG_PROC_HARDWARE=y
 CONFIG_NET=y
 CONFIG_PACKET=y
+CONFIG_PACKET_DIAG=m
 CONFIG_UNIX=y
+CONFIG_UNIX_DIAG=m
+CONFIG_XFRM_MIGRATE=y
 CONFIG_NET_KEY=y
-CONFIG_NET_KEY_MIGRATE=y
 CONFIG_INET=y
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=y
 CONFIG_IP_PNP_BOOTP=y
 CONFIG_IP_PNP_RARP=y
 CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE_DEMUX=m
 CONFIG_NET_IPGRE=m
 CONFIG_SYN_COOKIES=y
+CONFIG_NET_IPVTI=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
 CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
 CONFIG_INET_XFRM_MODE_BEET=m
+# CONFIG_INET_LRO is not set
 CONFIG_INET_DIAG=m
+CONFIG_INET_UDP_DIAG=m
 CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
-CONFIG_IPV6_ROUTE_INFO=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
-CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
-CONFIG_IPV6_TUNNEL=m
+CONFIG_IPV6_GRE=m
 CONFIG_NETFILTER=y
-CONFIG_NETFILTER_NETLINK_QUEUE=m
 CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CONNTRACK_ZONES=y
+# CONFIG_NF_CONNTRACK_PROCFS is not set
 # CONFIG_NF_CT_PROTO_DCCP is not set
 CONFIG_NF_CT_PROTO_UDPLITE=m
 CONFIG_NF_CONNTRACK_AMANDA=m
@@ -57,25 +78,37 @@ CONFIG_NF_CONNTRACK_FTP=m
 CONFIG_NF_CONNTRACK_H323=m
 CONFIG_NF_CONNTRACK_IRC=m
 CONFIG_NF_CONNTRACK_NETBIOS_NS=m
+CONFIG_NF_CONNTRACK_SNMP=m
 CONFIG_NF_CONNTRACK_PPTP=m
 CONFIG_NF_CONNTRACK_SANE=m
 CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NETFILTER_XT_SET=m
+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
 CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
 CONFIG_NETFILTER_XT_TARGET_DSCP=m
+CONFIG_NETFILTER_XT_TARGET_HMARK=m
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m
+CONFIG_NETFILTER_XT_TARGET_LOG=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_TEE=m
 CONFIG_NETFILTER_XT_TARGET_TRACE=m
 CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
+CONFIG_NETFILTER_XT_MATCH_BPF=m
 CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
 CONFIG_NETFILTER_XT_MATCH_COMMENT=m
 CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m
 CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
 CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
 CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m
 CONFIG_NETFILTER_XT_MATCH_DSCP=m
 CONFIG_NETFILTER_XT_MATCH_ESP=m
 CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
@@ -86,6 +119,8 @@ CONFIG_NETFILTER_XT_MATCH_LIMIT=m
 CONFIG_NETFILTER_XT_MATCH_MAC=m
 CONFIG_NETFILTER_XT_MATCH_MARK=m
 CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_NFACCT=m
+CONFIG_NETFILTER_XT_MATCH_OSF=m
 CONFIG_NETFILTER_XT_MATCH_OWNER=m
 CONFIG_NETFILTER_XT_MATCH_POLICY=m
 CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
@@ -99,22 +134,31 @@ CONFIG_NETFILTER_XT_MATCH_STRING=m
 CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
 CONFIG_NETFILTER_XT_MATCH_TIME=m
 CONFIG_NETFILTER_XT_MATCH_U32=m
+CONFIG_IP_SET=m
+CONFIG_IP_SET_BITMAP_IP=m
+CONFIG_IP_SET_BITMAP_IPMAC=m
+CONFIG_IP_SET_BITMAP_PORT=m
+CONFIG_IP_SET_HASH_IP=m
+CONFIG_IP_SET_HASH_IPPORT=m
+CONFIG_IP_SET_HASH_IPPORTIP=m
+CONFIG_IP_SET_HASH_IPPORTNET=m
+CONFIG_IP_SET_HASH_NET=m
+CONFIG_IP_SET_HASH_NETPORT=m
+CONFIG_IP_SET_HASH_NETIFACE=m
+CONFIG_IP_SET_LIST_SET=m
 CONFIG_NF_CONNTRACK_IPV4=m
-CONFIG_IP_NF_QUEUE=m
 CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_ADDRTYPE=m
 CONFIG_IP_NF_MATCH_AH=m
 CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_RPFILTER=m
 CONFIG_IP_NF_MATCH_TTL=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
-CONFIG_IP_NF_TARGET_LOG=m
 CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_NF_NAT=m
+CONFIG_NF_NAT_IPV4=m
 CONFIG_IP_NF_TARGET_MASQUERADE=m
 CONFIG_IP_NF_TARGET_NETMAP=m
 CONFIG_IP_NF_TARGET_REDIRECT=m
-CONFIG_NF_NAT_SNMP_BASIC=m
 CONFIG_IP_NF_MANGLE=m
 CONFIG_IP_NF_TARGET_CLUSTERIP=m
 CONFIG_IP_NF_TARGET_ECN=m
@@ -124,7 +168,6 @@ CONFIG_IP_NF_ARPTABLES=m
 CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
 CONFIG_NF_CONNTRACK_IPV6=m
-CONFIG_IP6_NF_QUEUE=m
 CONFIG_IP6_NF_IPTABLES=m
 CONFIG_IP6_NF_MATCH_AH=m
 CONFIG_IP6_NF_MATCH_EUI64=m
@@ -133,21 +176,34 @@ CONFIG_IP6_NF_MATCH_OPTS=m
 CONFIG_IP6_NF_MATCH_HL=m
 CONFIG_IP6_NF_MATCH_IPV6HEADER=m
 CONFIG_IP6_NF_MATCH_MH=m
+CONFIG_IP6_NF_MATCH_RPFILTER=m
 CONFIG_IP6_NF_MATCH_RT=m
 CONFIG_IP6_NF_TARGET_HL=m
-CONFIG_IP6_NF_TARGET_LOG=m
 CONFIG_IP6_NF_FILTER=m
 CONFIG_IP6_NF_TARGET_REJECT=m
 CONFIG_IP6_NF_MANGLE=m
 CONFIG_IP6_NF_RAW=m
+CONFIG_NF_NAT_IPV6=m
+CONFIG_IP6_NF_TARGET_MASQUERADE=m
+CONFIG_IP6_NF_TARGET_NPT=m
 CONFIG_IP_DCCP=m
 # CONFIG_IP_DCCP_CCID3 is not set
+CONFIG_SCTP_COOKIE_HMAC_SHA1=y
+CONFIG_RDS=m
+CONFIG_RDS_TCP=m
+CONFIG_L2TP=m
 CONFIG_ATALK=m
+CONFIG_BATMAN_ADV=m
+CONFIG_BATMAN_ADV_DAT=y
+# CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
 # CONFIG_FIRMWARE_IN_KERNEL is not set
+# CONFIG_FW_LOADER_USER_HELPER is not set
 CONFIG_CONNECTOR=m
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_DRBD=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_CDROM_PKTCDVD=m
@@ -162,57 +218,74 @@ CONFIG_BLK_DEV_SR=y
 CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
 CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_SAS_LIBSAS=m
-# CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set
-CONFIG_SCSI_SRP_ATTRS=m
-CONFIG_SCSI_SRP_TGT_ATTRS=y
+CONFIG_SCSI_SAS_ATTRS=m
 CONFIG_ISCSI_TCP=m
+CONFIG_ISCSI_BOOT_SYSFS=m
 CONFIG_MD=y
-CONFIG_BLK_DEV_MD=m
 CONFIG_MD_LINEAR=m
 CONFIG_MD_RAID0=m
-CONFIG_MD_RAID1=m
-CONFIG_MD_RAID456=m
 CONFIG_BLK_DEV_DM=m
 CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_THIN_PROVISIONING=m
+CONFIG_DM_CACHE=m
 CONFIG_DM_MIRROR=m
+CONFIG_DM_RAID=m
 CONFIG_DM_ZERO=m
 CONFIG_DM_MULTIPATH=m
 CONFIG_DM_UEVENT=y
+CONFIG_TARGET_CORE=m
+CONFIG_TCM_IBLOCK=m
+CONFIG_TCM_FILEIO=m
+CONFIG_TCM_PSCSI=m
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=m
-CONFIG_MACVLAN=m
 CONFIG_EQUALIZER=m
+CONFIG_NET_TEAM=m
+CONFIG_NET_TEAM_MODE_BROADCAST=m
+CONFIG_NET_TEAM_MODE_ROUNDROBIN=m
+CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m
+CONFIG_NET_TEAM_MODE_LOADBALANCE=m
+CONFIG_VXLAN=m
+CONFIG_NETCONSOLE=m
+CONFIG_NETCONSOLE_DYNAMIC=y
 CONFIG_VETH=m
-CONFIG_NET_ETHERNET=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
 CONFIG_PPP=m
-CONFIG_PPP_FILTER=y
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=m
 CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_FILTER=y
 CONFIG_PPP_MPPE=m
 CONFIG_PPPOE=m
+CONFIG_PPTP=m
+CONFIG_PPPOL2TP=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
 CONFIG_SLIP=m
 CONFIG_SLIP_COMPRESSED=y
 CONFIG_SLIP_SMART=y
 CONFIG_SLIP_MODE_SLIP6=y
-CONFIG_NETCONSOLE=m
-CONFIG_NETCONSOLE_DYNAMIC=y
-CONFIG_INPUT_FF_MEMLESS=m
+# CONFIG_WLAN is not set
+CONFIG_INPUT_EVDEV=m
 # CONFIG_KEYBOARD_ATKBD is not set
-CONFIG_MOUSE_PS2=m
+# CONFIG_MOUSE_PS2 is not set
 CONFIG_MOUSE_SERIAL=m
 CONFIG_SERIO=m
-# CONFIG_SERIO_SERPORT is not set
 CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_LEGACY_PTYS is not set
 # CONFIG_DEVKMEM is not set
 # CONFIG_HW_RANDOM is not set
-CONFIG_GEN_RTC=m
-CONFIG_GEN_RTC_X=y
+CONFIG_NTP_PPS=y
+CONFIG_PPS_CLIENT_LDISC=m
+CONFIG_PTP_1588_CLOCK=m
 # CONFIG_HWMON is not set
 CONFIG_FB=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
@@ -221,47 +294,61 @@ CONFIG_LOGO=y
 # CONFIG_LOGO_LINUX_CLUT224 is not set
 CONFIG_HID=m
 CONFIG_HIDRAW=y
+CONFIG_UHID=m
+# CONFIG_HID_GENERIC is not set
 # CONFIG_USB_SUPPORT is not set
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_GENERIC=m
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_HEARTBEAT=y
+CONFIG_PROC_HARDWARE=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 # CONFIG_EXT3_FS_XATTR is not set
+CONFIG_EXT4_FS=y
 CONFIG_REISERFS_FS=m
 CONFIG_JFS_FS=m
 CONFIG_XFS_FS=m
 CONFIG_OCFS2_FS=m
-# CONFIG_OCFS2_FS_STATS is not set
 # CONFIG_OCFS2_DEBUG_MASKLOG is not set
+CONFIG_FANOTIFY=y
 CONFIG_QUOTA_NETLINK_INTERFACE=y
 # CONFIG_PRINT_QUOTA_WARNING is not set
-CONFIG_AUTOFS_FS=m
 CONFIG_AUTOFS4_FS=m
 CONFIG_FUSE_FS=m
+CONFIG_CUSE=m
 CONFIG_ISO9660_FS=y
 CONFIG_JOLIET=y
 CONFIG_ZISOFS=y
 CONFIG_UDF_FS=m
-CONFIG_MSDOS_FS=y
+CONFIG_MSDOS_FS=m
 CONFIG_VFAT_FS=m
 CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
 CONFIG_AFFS_FS=m
+CONFIG_ECRYPT_FS=m
+CONFIG_ECRYPT_FS_MESSAGING=y
 CONFIG_HFS_FS=m
 CONFIG_HFSPLUS_FS=m
 CONFIG_CRAMFS=m
 CONFIG_SQUASHFS=m
-CONFIG_MINIX_FS=y
+CONFIG_SQUASHFS_LZO=y
+CONFIG_MINIX_FS=m
+CONFIG_OMFS_FS=m
 CONFIG_HPFS_FS=m
+CONFIG_QNX4FS_FS=m
+CONFIG_QNX6FS_FS=m
 CONFIG_SYSV_FS=m
 CONFIG_UFS_FS=m
 CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
 CONFIG_NFS_V4=y
+CONFIG_NFS_SWAP=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
 CONFIG_NFSD_V3=y
-CONFIG_SMB_FS=m
-CONFIG_SMB_NLS_DEFAULT=y
+CONFIG_CIFS=m
+# CONFIG_CIFS_DEBUG is not set
 CONFIG_CODA_FS=m
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_CODEPAGE_737=m
@@ -300,10 +387,23 @@ CONFIG_NLS_ISO8859_14=m
 CONFIG_NLS_ISO8859_15=m
 CONFIG_NLS_KOI8_R=m
 CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_MAC_ROMAN=m
+CONFIG_NLS_MAC_CELTIC=m
+CONFIG_NLS_MAC_CENTEURO=m
+CONFIG_NLS_MAC_CROATIAN=m
+CONFIG_NLS_MAC_CYRILLIC=m
+CONFIG_NLS_MAC_GAELIC=m
+CONFIG_NLS_MAC_GREEK=m
+CONFIG_NLS_MAC_ICELAND=m
+CONFIG_NLS_MAC_INUIT=m
+CONFIG_NLS_MAC_ROMANIAN=m
+CONFIG_NLS_MAC_TURKISH=m
 CONFIG_DLM=m
 CONFIG_MAGIC_SYSRQ=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_ASYNC_RAID6_TEST=m
+CONFIG_ENCRYPTED_KEYS=m
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_USER=m
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_CRYPTD=m
 CONFIG_CRYPTO_TEST=m
@@ -313,19 +413,16 @@ CONFIG_CRYPTO_CTS=m
 CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_XTS=m
-CONFIG_CRYPTO_HMAC=y
 CONFIG_CRYPTO_XCBC=m
-CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_VMAC=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_RMD128=m
 CONFIG_CRYPTO_RMD160=m
 CONFIG_CRYPTO_RMD256=m
 CONFIG_CRYPTO_RMD320=m
-CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_ANUBIS=m
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_CAMELLIA=m
@@ -341,6 +438,14 @@ CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_ZLIB=m
 CONFIG_CRYPTO_LZO=m
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_USER_API_HASH=m
+CONFIG_CRYPTO_USER_API_SKCIPHER=m
 # CONFIG_CRYPTO_HW is not set
-CONFIG_CRC16=m
 CONFIG_CRC_T10DIF=y
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
+CONFIG_XZ_DEC_TEST=m
index 4571d33..6d5370c 100644 (file)
@@ -1,53 +1,75 @@
-CONFIG_EXPERIMENTAL=y
 CONFIG_LOCALVERSION="-atari"
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_FHANDLE=y
 CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_RELAY=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_LOG_BUF_SHIFT=16
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
-CONFIG_ATARI=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_AMIGA_PARTITION=y
+CONFIG_MAC_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+CONFIG_SUN_PARTITION=y
+# CONFIG_EFI_PARTITION is not set
+CONFIG_SYSV68_PARTITION=y
+CONFIG_IOSCHED_DEADLINE=m
 CONFIG_M68020=y
 CONFIG_M68030=y
 CONFIG_M68040=y
 CONFIG_M68060=y
+CONFIG_ATARI=y
+# CONFIG_COMPACTION is not set
+CONFIG_CLEANCACHE=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_BINFMT_AOUT=m
 CONFIG_BINFMT_MISC=m
-CONFIG_STRAM_PROC=y
-CONFIG_HEARTBEAT=y
-CONFIG_PROC_HARDWARE=y
 CONFIG_NET=y
 CONFIG_PACKET=y
+CONFIG_PACKET_DIAG=m
 CONFIG_UNIX=y
+CONFIG_UNIX_DIAG=m
+CONFIG_XFRM_MIGRATE=y
 CONFIG_NET_KEY=y
-CONFIG_NET_KEY_MIGRATE=y
 CONFIG_INET=y
 CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
 CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE_DEMUX=m
 CONFIG_NET_IPGRE=m
 CONFIG_SYN_COOKIES=y
+CONFIG_NET_IPVTI=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
 CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
 CONFIG_INET_XFRM_MODE_BEET=m
+# CONFIG_INET_LRO is not set
 CONFIG_INET_DIAG=m
+CONFIG_INET_UDP_DIAG=m
 CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
-CONFIG_IPV6_ROUTE_INFO=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
-CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
-CONFIG_IPV6_TUNNEL=m
+CONFIG_IPV6_GRE=m
 CONFIG_NETFILTER=y
-CONFIG_NETFILTER_NETLINK_QUEUE=m
 CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CONNTRACK_ZONES=y
+# CONFIG_NF_CONNTRACK_PROCFS is not set
 # CONFIG_NF_CT_PROTO_DCCP is not set
 CONFIG_NF_CT_PROTO_UDPLITE=m
 CONFIG_NF_CONNTRACK_AMANDA=m
@@ -55,25 +77,37 @@ CONFIG_NF_CONNTRACK_FTP=m
 CONFIG_NF_CONNTRACK_H323=m
 CONFIG_NF_CONNTRACK_IRC=m
 CONFIG_NF_CONNTRACK_NETBIOS_NS=m
+CONFIG_NF_CONNTRACK_SNMP=m
 CONFIG_NF_CONNTRACK_PPTP=m
 CONFIG_NF_CONNTRACK_SANE=m
 CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NETFILTER_XT_SET=m
+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
 CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
 CONFIG_NETFILTER_XT_TARGET_DSCP=m
+CONFIG_NETFILTER_XT_TARGET_HMARK=m
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m
+CONFIG_NETFILTER_XT_TARGET_LOG=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_TEE=m
 CONFIG_NETFILTER_XT_TARGET_TRACE=m
 CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
+CONFIG_NETFILTER_XT_MATCH_BPF=m
 CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
 CONFIG_NETFILTER_XT_MATCH_COMMENT=m
 CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m
 CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
 CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
 CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m
 CONFIG_NETFILTER_XT_MATCH_DSCP=m
 CONFIG_NETFILTER_XT_MATCH_ESP=m
 CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
@@ -84,6 +118,8 @@ CONFIG_NETFILTER_XT_MATCH_LIMIT=m
 CONFIG_NETFILTER_XT_MATCH_MAC=m
 CONFIG_NETFILTER_XT_MATCH_MARK=m
 CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_NFACCT=m
+CONFIG_NETFILTER_XT_MATCH_OSF=m
 CONFIG_NETFILTER_XT_MATCH_OWNER=m
 CONFIG_NETFILTER_XT_MATCH_POLICY=m
 CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
@@ -97,22 +133,31 @@ CONFIG_NETFILTER_XT_MATCH_STRING=m
 CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
 CONFIG_NETFILTER_XT_MATCH_TIME=m
 CONFIG_NETFILTER_XT_MATCH_U32=m
+CONFIG_IP_SET=m
+CONFIG_IP_SET_BITMAP_IP=m
+CONFIG_IP_SET_BITMAP_IPMAC=m
+CONFIG_IP_SET_BITMAP_PORT=m
+CONFIG_IP_SET_HASH_IP=m
+CONFIG_IP_SET_HASH_IPPORT=m
+CONFIG_IP_SET_HASH_IPPORTIP=m
+CONFIG_IP_SET_HASH_IPPORTNET=m
+CONFIG_IP_SET_HASH_NET=m
+CONFIG_IP_SET_HASH_NETPORT=m
+CONFIG_IP_SET_HASH_NETIFACE=m
+CONFIG_IP_SET_LIST_SET=m
 CONFIG_NF_CONNTRACK_IPV4=m
-CONFIG_IP_NF_QUEUE=m
 CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_ADDRTYPE=m
 CONFIG_IP_NF_MATCH_AH=m
 CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_RPFILTER=m
 CONFIG_IP_NF_MATCH_TTL=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
-CONFIG_IP_NF_TARGET_LOG=m
 CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_NF_NAT=m
+CONFIG_NF_NAT_IPV4=m
 CONFIG_IP_NF_TARGET_MASQUERADE=m
 CONFIG_IP_NF_TARGET_NETMAP=m
 CONFIG_IP_NF_TARGET_REDIRECT=m
-CONFIG_NF_NAT_SNMP_BASIC=m
 CONFIG_IP_NF_MANGLE=m
 CONFIG_IP_NF_TARGET_CLUSTERIP=m
 CONFIG_IP_NF_TARGET_ECN=m
@@ -122,7 +167,6 @@ CONFIG_IP_NF_ARPTABLES=m
 CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
 CONFIG_NF_CONNTRACK_IPV6=m
-CONFIG_IP6_NF_QUEUE=m
 CONFIG_IP6_NF_IPTABLES=m
 CONFIG_IP6_NF_MATCH_AH=m
 CONFIG_IP6_NF_MATCH_EUI64=m
@@ -131,18 +175,30 @@ CONFIG_IP6_NF_MATCH_OPTS=m
 CONFIG_IP6_NF_MATCH_HL=m
 CONFIG_IP6_NF_MATCH_IPV6HEADER=m
 CONFIG_IP6_NF_MATCH_MH=m
+CONFIG_IP6_NF_MATCH_RPFILTER=m
 CONFIG_IP6_NF_MATCH_RT=m
 CONFIG_IP6_NF_TARGET_HL=m
-CONFIG_IP6_NF_TARGET_LOG=m
 CONFIG_IP6_NF_FILTER=m
 CONFIG_IP6_NF_TARGET_REJECT=m
 CONFIG_IP6_NF_MANGLE=m
 CONFIG_IP6_NF_RAW=m
+CONFIG_NF_NAT_IPV6=m
+CONFIG_IP6_NF_TARGET_MASQUERADE=m
+CONFIG_IP6_NF_TARGET_NPT=m
 CONFIG_IP_DCCP=m
 # CONFIG_IP_DCCP_CCID3 is not set
+CONFIG_SCTP_COOKIE_HMAC_SHA1=y
+CONFIG_RDS=m
+CONFIG_RDS_TCP=m
+CONFIG_L2TP=m
 CONFIG_ATALK=m
+CONFIG_BATMAN_ADV=m
+CONFIG_BATMAN_ADV_DAT=y
+# CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
 # CONFIG_FIRMWARE_IN_KERNEL is not set
+# CONFIG_FW_LOADER_USER_HELPER is not set
 CONFIG_CONNECTOR=m
 CONFIG_PARPORT=m
 CONFIG_PARPORT_ATARI=m
@@ -150,11 +206,13 @@ CONFIG_PARPORT_1284=y
 CONFIG_ATARI_FLOPPY=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_DRBD=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_ATA_OVER_ETH=m
 CONFIG_IDE=y
+CONFIG_IDE_GD_ATAPI=y
 CONFIG_BLK_DEV_IDECD=y
 CONFIG_BLK_DEV_FALCON_IDE=y
 CONFIG_RAID_ATTRS=m
@@ -167,63 +225,81 @@ CONFIG_BLK_DEV_SR=y
 CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
 CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_SAS_LIBSAS=m
-# CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set
-CONFIG_SCSI_SRP_ATTRS=m
-CONFIG_SCSI_SRP_TGT_ATTRS=y
+CONFIG_SCSI_SAS_ATTRS=m
 CONFIG_ISCSI_TCP=m
+CONFIG_ISCSI_BOOT_SYSFS=m
 CONFIG_ATARI_SCSI=y
 CONFIG_MD=y
-CONFIG_BLK_DEV_MD=m
 CONFIG_MD_LINEAR=m
 CONFIG_MD_RAID0=m
-CONFIG_MD_RAID1=m
-CONFIG_MD_RAID456=m
 CONFIG_BLK_DEV_DM=m
 CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_THIN_PROVISIONING=m
+CONFIG_DM_CACHE=m
 CONFIG_DM_MIRROR=m
+CONFIG_DM_RAID=m
 CONFIG_DM_ZERO=m
 CONFIG_DM_MULTIPATH=m
 CONFIG_DM_UEVENT=y
+CONFIG_TARGET_CORE=m
+CONFIG_TCM_IBLOCK=m
+CONFIG_TCM_FILEIO=m
+CONFIG_TCM_PSCSI=m
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=m
-CONFIG_MACVLAN=m
 CONFIG_EQUALIZER=m
-CONFIG_VETH=m
-CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
+CONFIG_NET_TEAM=m
+CONFIG_NET_TEAM_MODE_BROADCAST=m
+CONFIG_NET_TEAM_MODE_ROUNDROBIN=m
+CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m
+CONFIG_NET_TEAM_MODE_LOADBALANCE=m
+CONFIG_VXLAN=m
+CONFIG_NETCONSOLE=m
+CONFIG_NETCONSOLE_DYNAMIC=y
+CONFIG_VETH=m
 CONFIG_ATARILANCE=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
 CONFIG_PPP=m
-CONFIG_PPP_FILTER=y
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=m
 CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_FILTER=y
 CONFIG_PPP_MPPE=m
 CONFIG_PPPOE=m
+CONFIG_PPTP=m
+CONFIG_PPPOL2TP=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
 CONFIG_SLIP=m
 CONFIG_SLIP_COMPRESSED=y
 CONFIG_SLIP_SMART=y
 CONFIG_SLIP_MODE_SLIP6=y
-CONFIG_NETCONSOLE=m
-CONFIG_NETCONSOLE_DYNAMIC=y
-CONFIG_INPUT_FF_MEMLESS=m
+# CONFIG_WLAN is not set
+CONFIG_INPUT_EVDEV=m
 CONFIG_KEYBOARD_ATARI=y
 # CONFIG_KEYBOARD_ATKBD is not set
-CONFIG_MOUSE_PS2=m
+# CONFIG_MOUSE_PS2 is not set
 CONFIG_MOUSE_ATARI=m
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_M68K_BEEP=m
-# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO is not set
 CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_LEGACY_PTYS is not set
 # CONFIG_DEVKMEM is not set
 CONFIG_PRINTER=m
 # CONFIG_HW_RANDOM is not set
-CONFIG_GEN_RTC=m
-CONFIG_GEN_RTC_X=y
+CONFIG_NTP_PPS=y
+CONFIG_PPS_CLIENT_LDISC=m
+CONFIG_PPS_CLIENT_PARPORT=m
+CONFIG_PTP_1588_CLOCK=m
 # CONFIG_HWMON is not set
 CONFIG_FB=y
 CONFIG_FB_ATARI=y
@@ -233,47 +309,64 @@ CONFIG_SOUND=m
 CONFIG_DMASOUND_ATARI=m
 CONFIG_HID=m
 CONFIG_HIDRAW=y
-# CONFIG_USB_SUPPORT is not set
+CONFIG_UHID=m
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_GENERIC=m
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_HEARTBEAT=y
+CONFIG_PROC_HARDWARE=y
+CONFIG_NATFEAT=y
+CONFIG_NFBLOCK=y
+CONFIG_NFCON=y
+CONFIG_NFETH=y
 CONFIG_ATARI_DSP56K=m
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 # CONFIG_EXT3_FS_XATTR is not set
+CONFIG_EXT4_FS=y
 CONFIG_REISERFS_FS=m
 CONFIG_JFS_FS=m
 CONFIG_XFS_FS=m
 CONFIG_OCFS2_FS=m
-# CONFIG_OCFS2_FS_STATS is not set
 # CONFIG_OCFS2_DEBUG_MASKLOG is not set
+CONFIG_FANOTIFY=y
 CONFIG_QUOTA_NETLINK_INTERFACE=y
 # CONFIG_PRINT_QUOTA_WARNING is not set
-CONFIG_AUTOFS_FS=m
 CONFIG_AUTOFS4_FS=m
 CONFIG_FUSE_FS=m
+CONFIG_CUSE=m
 CONFIG_ISO9660_FS=y
 CONFIG_JOLIET=y
 CONFIG_ZISOFS=y
 CONFIG_UDF_FS=m
-CONFIG_MSDOS_FS=y
+CONFIG_MSDOS_FS=m
 CONFIG_VFAT_FS=m
 CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
 CONFIG_AFFS_FS=m
+CONFIG_ECRYPT_FS=m
+CONFIG_ECRYPT_FS_MESSAGING=y
 CONFIG_HFS_FS=m
 CONFIG_HFSPLUS_FS=m
 CONFIG_CRAMFS=m
 CONFIG_SQUASHFS=m
-CONFIG_MINIX_FS=y
+CONFIG_SQUASHFS_LZO=y
+CONFIG_MINIX_FS=m
+CONFIG_OMFS_FS=m
 CONFIG_HPFS_FS=m
+CONFIG_QNX4FS_FS=m
+CONFIG_QNX6FS_FS=m
 CONFIG_SYSV_FS=m
 CONFIG_UFS_FS=m
 CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
 CONFIG_NFS_V4=y
+CONFIG_NFS_SWAP=y
+CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
 CONFIG_NFSD_V3=y
-CONFIG_SMB_FS=m
-CONFIG_SMB_NLS_DEFAULT=y
+CONFIG_CIFS=m
+# CONFIG_CIFS_DEBUG is not set
 CONFIG_CODA_FS=m
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_CODEPAGE_737=m
@@ -312,10 +405,23 @@ CONFIG_NLS_ISO8859_14=m
 CONFIG_NLS_ISO8859_15=m
 CONFIG_NLS_KOI8_R=m
 CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_MAC_ROMAN=m
+CONFIG_NLS_MAC_CELTIC=m
+CONFIG_NLS_MAC_CENTEURO=m
+CONFIG_NLS_MAC_CROATIAN=m
+CONFIG_NLS_MAC_CYRILLIC=m
+CONFIG_NLS_MAC_GAELIC=m
+CONFIG_NLS_MAC_GREEK=m
+CONFIG_NLS_MAC_ICELAND=m
+CONFIG_NLS_MAC_INUIT=m
+CONFIG_NLS_MAC_ROMANIAN=m
+CONFIG_NLS_MAC_TURKISH=m
 CONFIG_DLM=m
 CONFIG_MAGIC_SYSRQ=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_ASYNC_RAID6_TEST=m
+CONFIG_ENCRYPTED_KEYS=m
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_USER=m
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_CRYPTD=m
 CONFIG_CRYPTO_TEST=m
@@ -325,19 +431,16 @@ CONFIG_CRYPTO_CTS=m
 CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_XTS=m
-CONFIG_CRYPTO_HMAC=y
 CONFIG_CRYPTO_XCBC=m
-CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_VMAC=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_RMD128=m
 CONFIG_CRYPTO_RMD160=m
 CONFIG_CRYPTO_RMD256=m
 CONFIG_CRYPTO_RMD320=m
-CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_ANUBIS=m
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_CAMELLIA=m
@@ -353,6 +456,14 @@ CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_ZLIB=m
 CONFIG_CRYPTO_LZO=m
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_USER_API_HASH=m
+CONFIG_CRYPTO_USER_API_SKCIPHER=m
 # CONFIG_CRYPTO_HW is not set
-CONFIG_CRC16=y
 CONFIG_CRC_T10DIF=y
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
+CONFIG_XZ_DEC_TEST=m
index 12f2117..c015ddb 100644 (file)
@@ -1,53 +1,74 @@
-CONFIG_EXPERIMENTAL=y
 CONFIG_LOCALVERSION="-bvme6000"
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_FHANDLE=y
 CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_RELAY=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_LOG_BUF_SHIFT=16
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
-CONFIG_VME=y
-CONFIG_BVME6000=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_AMIGA_PARTITION=y
+CONFIG_ATARI_PARTITION=y
+CONFIG_MAC_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+CONFIG_SUN_PARTITION=y
+# CONFIG_EFI_PARTITION is not set
+CONFIG_IOSCHED_DEADLINE=m
 CONFIG_M68040=y
 CONFIG_M68060=y
+CONFIG_VME=y
+CONFIG_BVME6000=y
+# CONFIG_COMPACTION is not set
+CONFIG_CLEANCACHE=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_BINFMT_AOUT=m
 CONFIG_BINFMT_MISC=m
-CONFIG_PROC_HARDWARE=y
 CONFIG_NET=y
 CONFIG_PACKET=y
+CONFIG_PACKET_DIAG=m
 CONFIG_UNIX=y
+CONFIG_UNIX_DIAG=m
+CONFIG_XFRM_MIGRATE=y
 CONFIG_NET_KEY=y
-CONFIG_NET_KEY_MIGRATE=y
 CONFIG_INET=y
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=y
 CONFIG_IP_PNP_BOOTP=y
 CONFIG_IP_PNP_RARP=y
 CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE_DEMUX=m
 CONFIG_NET_IPGRE=m
 CONFIG_SYN_COOKIES=y
+CONFIG_NET_IPVTI=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
 CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
 CONFIG_INET_XFRM_MODE_BEET=m
+# CONFIG_INET_LRO is not set
 CONFIG_INET_DIAG=m
+CONFIG_INET_UDP_DIAG=m
 CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
-CONFIG_IPV6_ROUTE_INFO=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
-CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
-CONFIG_IPV6_TUNNEL=m
+CONFIG_IPV6_GRE=m
 CONFIG_NETFILTER=y
-CONFIG_NETFILTER_NETLINK_QUEUE=m
 CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CONNTRACK_ZONES=y
+# CONFIG_NF_CONNTRACK_PROCFS is not set
 # CONFIG_NF_CT_PROTO_DCCP is not set
 CONFIG_NF_CT_PROTO_UDPLITE=m
 CONFIG_NF_CONNTRACK_AMANDA=m
@@ -55,25 +76,37 @@ CONFIG_NF_CONNTRACK_FTP=m
 CONFIG_NF_CONNTRACK_H323=m
 CONFIG_NF_CONNTRACK_IRC=m
 CONFIG_NF_CONNTRACK_NETBIOS_NS=m
+CONFIG_NF_CONNTRACK_SNMP=m
 CONFIG_NF_CONNTRACK_PPTP=m
 CONFIG_NF_CONNTRACK_SANE=m
 CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NETFILTER_XT_SET=m
+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
 CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
 CONFIG_NETFILTER_XT_TARGET_DSCP=m
+CONFIG_NETFILTER_XT_TARGET_HMARK=m
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m
+CONFIG_NETFILTER_XT_TARGET_LOG=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_TEE=m
 CONFIG_NETFILTER_XT_TARGET_TRACE=m
 CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
+CONFIG_NETFILTER_XT_MATCH_BPF=m
 CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
 CONFIG_NETFILTER_XT_MATCH_COMMENT=m
 CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m
 CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
 CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
 CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m
 CONFIG_NETFILTER_XT_MATCH_DSCP=m
 CONFIG_NETFILTER_XT_MATCH_ESP=m
 CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
@@ -84,6 +117,8 @@ CONFIG_NETFILTER_XT_MATCH_LIMIT=m
 CONFIG_NETFILTER_XT_MATCH_MAC=m
 CONFIG_NETFILTER_XT_MATCH_MARK=m
 CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_NFACCT=m
+CONFIG_NETFILTER_XT_MATCH_OSF=m
 CONFIG_NETFILTER_XT_MATCH_OWNER=m
 CONFIG_NETFILTER_XT_MATCH_POLICY=m
 CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
@@ -97,22 +132,31 @@ CONFIG_NETFILTER_XT_MATCH_STRING=m
 CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
 CONFIG_NETFILTER_XT_MATCH_TIME=m
 CONFIG_NETFILTER_XT_MATCH_U32=m
+CONFIG_IP_SET=m
+CONFIG_IP_SET_BITMAP_IP=m
+CONFIG_IP_SET_BITMAP_IPMAC=m
+CONFIG_IP_SET_BITMAP_PORT=m
+CONFIG_IP_SET_HASH_IP=m
+CONFIG_IP_SET_HASH_IPPORT=m
+CONFIG_IP_SET_HASH_IPPORTIP=m
+CONFIG_IP_SET_HASH_IPPORTNET=m
+CONFIG_IP_SET_HASH_NET=m
+CONFIG_IP_SET_HASH_NETPORT=m
+CONFIG_IP_SET_HASH_NETIFACE=m
+CONFIG_IP_SET_LIST_SET=m
 CONFIG_NF_CONNTRACK_IPV4=m
-CONFIG_IP_NF_QUEUE=m
 CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_ADDRTYPE=m
 CONFIG_IP_NF_MATCH_AH=m
 CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_RPFILTER=m
 CONFIG_IP_NF_MATCH_TTL=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
-CONFIG_IP_NF_TARGET_LOG=m
 CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_NF_NAT=m
+CONFIG_NF_NAT_IPV4=m
 CONFIG_IP_NF_TARGET_MASQUERADE=m
 CONFIG_IP_NF_TARGET_NETMAP=m
 CONFIG_IP_NF_TARGET_REDIRECT=m
-CONFIG_NF_NAT_SNMP_BASIC=m
 CONFIG_IP_NF_MANGLE=m
 CONFIG_IP_NF_TARGET_CLUSTERIP=m
 CONFIG_IP_NF_TARGET_ECN=m
@@ -122,7 +166,6 @@ CONFIG_IP_NF_ARPTABLES=m
 CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
 CONFIG_NF_CONNTRACK_IPV6=m
-CONFIG_IP6_NF_QUEUE=m
 CONFIG_IP6_NF_IPTABLES=m
 CONFIG_IP6_NF_MATCH_AH=m
 CONFIG_IP6_NF_MATCH_EUI64=m
@@ -131,21 +174,34 @@ CONFIG_IP6_NF_MATCH_OPTS=m
 CONFIG_IP6_NF_MATCH_HL=m
 CONFIG_IP6_NF_MATCH_IPV6HEADER=m
 CONFIG_IP6_NF_MATCH_MH=m
+CONFIG_IP6_NF_MATCH_RPFILTER=m
 CONFIG_IP6_NF_MATCH_RT=m
 CONFIG_IP6_NF_TARGET_HL=m
-CONFIG_IP6_NF_TARGET_LOG=m
 CONFIG_IP6_NF_FILTER=m
 CONFIG_IP6_NF_TARGET_REJECT=m
 CONFIG_IP6_NF_MANGLE=m
 CONFIG_IP6_NF_RAW=m
+CONFIG_NF_NAT_IPV6=m
+CONFIG_IP6_NF_TARGET_MASQUERADE=m
+CONFIG_IP6_NF_TARGET_NPT=m
 CONFIG_IP_DCCP=m
 # CONFIG_IP_DCCP_CCID3 is not set
+CONFIG_SCTP_COOKIE_HMAC_SHA1=y
+CONFIG_RDS=m
+CONFIG_RDS_TCP=m
+CONFIG_L2TP=m
 CONFIG_ATALK=m
+CONFIG_BATMAN_ADV=m
+CONFIG_BATMAN_ADV_DAT=y
+# CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
 # CONFIG_FIRMWARE_IN_KERNEL is not set
+# CONFIG_FW_LOADER_USER_HELPER is not set
 CONFIG_CONNECTOR=m
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_DRBD=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_CDROM_PKTCDVD=m
@@ -160,103 +216,131 @@ CONFIG_BLK_DEV_SR=y
 CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
 CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_SAS_LIBSAS=m
-# CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set
-CONFIG_SCSI_SRP_ATTRS=m
-CONFIG_SCSI_SRP_TGT_ATTRS=y
+CONFIG_SCSI_SAS_ATTRS=m
 CONFIG_ISCSI_TCP=m
+CONFIG_ISCSI_BOOT_SYSFS=m
 CONFIG_BVME6000_SCSI=y
 CONFIG_MD=y
-CONFIG_BLK_DEV_MD=m
 CONFIG_MD_LINEAR=m
 CONFIG_MD_RAID0=m
-CONFIG_MD_RAID1=m
-CONFIG_MD_RAID456=m
 CONFIG_BLK_DEV_DM=m
 CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_THIN_PROVISIONING=m
+CONFIG_DM_CACHE=m
 CONFIG_DM_MIRROR=m
+CONFIG_DM_RAID=m
 CONFIG_DM_ZERO=m
 CONFIG_DM_MULTIPATH=m
 CONFIG_DM_UEVENT=y
+CONFIG_TARGET_CORE=m
+CONFIG_TCM_IBLOCK=m
+CONFIG_TCM_FILEIO=m
+CONFIG_TCM_PSCSI=m
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=m
-CONFIG_MACVLAN=m
 CONFIG_EQUALIZER=m
+CONFIG_NET_TEAM=m
+CONFIG_NET_TEAM_MODE_BROADCAST=m
+CONFIG_NET_TEAM_MODE_ROUNDROBIN=m
+CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m
+CONFIG_NET_TEAM_MODE_LOADBALANCE=m
+CONFIG_VXLAN=m
+CONFIG_NETCONSOLE=m
+CONFIG_NETCONSOLE_DYNAMIC=y
 CONFIG_VETH=m
-CONFIG_NET_ETHERNET=y
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
 CONFIG_BVME6000_NET=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
 CONFIG_PPP=m
-CONFIG_PPP_FILTER=y
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=m
 CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_FILTER=y
 CONFIG_PPP_MPPE=m
 CONFIG_PPPOE=m
+CONFIG_PPTP=m
+CONFIG_PPPOL2TP=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
 CONFIG_SLIP=m
 CONFIG_SLIP_COMPRESSED=y
 CONFIG_SLIP_SMART=y
 CONFIG_SLIP_MODE_SLIP6=y
-CONFIG_NETCONSOLE=m
-CONFIG_NETCONSOLE_DYNAMIC=y
-CONFIG_INPUT_FF_MEMLESS=m
+# CONFIG_WLAN is not set
+CONFIG_INPUT_EVDEV=m
 # CONFIG_KEYBOARD_ATKBD is not set
-CONFIG_MOUSE_PS2=m
-CONFIG_MOUSE_SERIAL=m
-CONFIG_SERIO=m
-# CONFIG_SERIO_SERPORT is not set
+# CONFIG_MOUSE_PS2 is not set
+# CONFIG_SERIO is not set
 CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_LEGACY_PTYS is not set
 # CONFIG_DEVKMEM is not set
 # CONFIG_HW_RANDOM is not set
-CONFIG_GEN_RTC=m
-CONFIG_GEN_RTC_X=y
+CONFIG_NTP_PPS=y
+CONFIG_PPS_CLIENT_LDISC=m
+CONFIG_PTP_1588_CLOCK=m
 # CONFIG_HWMON is not set
 CONFIG_HID=m
 CONFIG_HIDRAW=y
+CONFIG_UHID=m
+# CONFIG_HID_GENERIC is not set
 # CONFIG_USB_SUPPORT is not set
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_GENERIC=m
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_PROC_HARDWARE=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 # CONFIG_EXT3_FS_XATTR is not set
+CONFIG_EXT4_FS=y
 CONFIG_REISERFS_FS=m
 CONFIG_JFS_FS=m
 CONFIG_XFS_FS=m
 CONFIG_OCFS2_FS=m
-# CONFIG_OCFS2_FS_STATS is not set
 # CONFIG_OCFS2_DEBUG_MASKLOG is not set
+CONFIG_FANOTIFY=y
 CONFIG_QUOTA_NETLINK_INTERFACE=y
 # CONFIG_PRINT_QUOTA_WARNING is not set
-CONFIG_AUTOFS_FS=m
 CONFIG_AUTOFS4_FS=m
 CONFIG_FUSE_FS=m
+CONFIG_CUSE=m
 CONFIG_ISO9660_FS=y
 CONFIG_JOLIET=y
 CONFIG_ZISOFS=y
 CONFIG_UDF_FS=m
-CONFIG_MSDOS_FS=y
+CONFIG_MSDOS_FS=m
 CONFIG_VFAT_FS=m
 CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
 CONFIG_AFFS_FS=m
+CONFIG_ECRYPT_FS=m
+CONFIG_ECRYPT_FS_MESSAGING=y
 CONFIG_HFS_FS=m
 CONFIG_HFSPLUS_FS=m
 CONFIG_CRAMFS=m
 CONFIG_SQUASHFS=m
-CONFIG_MINIX_FS=y
+CONFIG_SQUASHFS_LZO=y
+CONFIG_MINIX_FS=m
+CONFIG_OMFS_FS=m
 CONFIG_HPFS_FS=m
+CONFIG_QNX4FS_FS=m
+CONFIG_QNX6FS_FS=m
 CONFIG_SYSV_FS=m
 CONFIG_UFS_FS=m
 CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
 CONFIG_NFS_V4=y
+CONFIG_NFS_SWAP=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
 CONFIG_NFSD_V3=y
-CONFIG_SMB_FS=m
-CONFIG_SMB_NLS_DEFAULT=y
+CONFIG_CIFS=m
+# CONFIG_CIFS_DEBUG is not set
 CONFIG_CODA_FS=m
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_CODEPAGE_737=m
@@ -295,10 +379,23 @@ CONFIG_NLS_ISO8859_14=m
 CONFIG_NLS_ISO8859_15=m
 CONFIG_NLS_KOI8_R=m
 CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_MAC_ROMAN=m
+CONFIG_NLS_MAC_CELTIC=m
+CONFIG_NLS_MAC_CENTEURO=m
+CONFIG_NLS_MAC_CROATIAN=m
+CONFIG_NLS_MAC_CYRILLIC=m
+CONFIG_NLS_MAC_GAELIC=m
+CONFIG_NLS_MAC_GREEK=m
+CONFIG_NLS_MAC_ICELAND=m
+CONFIG_NLS_MAC_INUIT=m
+CONFIG_NLS_MAC_ROMANIAN=m
+CONFIG_NLS_MAC_TURKISH=m
 CONFIG_DLM=m
 CONFIG_MAGIC_SYSRQ=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_ASYNC_RAID6_TEST=m
+CONFIG_ENCRYPTED_KEYS=m
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_USER=m
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_CRYPTD=m
 CONFIG_CRYPTO_TEST=m
@@ -308,19 +405,16 @@ CONFIG_CRYPTO_CTS=m
 CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_XTS=m
-CONFIG_CRYPTO_HMAC=y
 CONFIG_CRYPTO_XCBC=m
-CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_VMAC=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_RMD128=m
 CONFIG_CRYPTO_RMD160=m
 CONFIG_CRYPTO_RMD256=m
 CONFIG_CRYPTO_RMD320=m
-CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_ANUBIS=m
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_CAMELLIA=m
@@ -336,7 +430,14 @@ CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_ZLIB=m
 CONFIG_CRYPTO_LZO=m
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_USER_API_HASH=m
+CONFIG_CRYPTO_USER_API_SKCIPHER=m
 # CONFIG_CRYPTO_HW is not set
-CONFIG_CRC16=m
 CONFIG_CRC_T10DIF=y
-CONFIG_CRC32=m
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
+CONFIG_XZ_DEC_TEST=m
index 215389a..ec7382d 100644 (file)
@@ -1,54 +1,76 @@
-CONFIG_EXPERIMENTAL=y
 CONFIG_LOCALVERSION="-hp300"
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_FHANDLE=y
 CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_RELAY=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_LOG_BUF_SHIFT=16
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
-CONFIG_HP300=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_AMIGA_PARTITION=y
+CONFIG_ATARI_PARTITION=y
+CONFIG_MAC_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+CONFIG_SUN_PARTITION=y
+# CONFIG_EFI_PARTITION is not set
+CONFIG_SYSV68_PARTITION=y
+CONFIG_IOSCHED_DEADLINE=m
 CONFIG_M68020=y
 CONFIG_M68030=y
 CONFIG_M68040=y
 CONFIG_M68060=y
+CONFIG_HP300=y
+# CONFIG_COMPACTION is not set
+CONFIG_CLEANCACHE=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_BINFMT_AOUT=m
 CONFIG_BINFMT_MISC=m
-CONFIG_PROC_HARDWARE=y
 CONFIG_NET=y
 CONFIG_PACKET=y
+CONFIG_PACKET_DIAG=m
 CONFIG_UNIX=y
+CONFIG_UNIX_DIAG=m
+CONFIG_XFRM_MIGRATE=y
 CONFIG_NET_KEY=y
-CONFIG_NET_KEY_MIGRATE=y
 CONFIG_INET=y
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=y
 CONFIG_IP_PNP_BOOTP=y
 CONFIG_IP_PNP_RARP=y
 CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE_DEMUX=m
 CONFIG_NET_IPGRE=m
 CONFIG_SYN_COOKIES=y
+CONFIG_NET_IPVTI=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
 CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
 CONFIG_INET_XFRM_MODE_BEET=m
+# CONFIG_INET_LRO is not set
 CONFIG_INET_DIAG=m
+CONFIG_INET_UDP_DIAG=m
 CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
-CONFIG_IPV6_ROUTE_INFO=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
-CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
-CONFIG_IPV6_TUNNEL=m
+CONFIG_IPV6_GRE=m
 CONFIG_NETFILTER=y
-CONFIG_NETFILTER_NETLINK_QUEUE=m
 CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CONNTRACK_ZONES=y
+# CONFIG_NF_CONNTRACK_PROCFS is not set
 # CONFIG_NF_CT_PROTO_DCCP is not set
 CONFIG_NF_CT_PROTO_UDPLITE=m
 CONFIG_NF_CONNTRACK_AMANDA=m
@@ -56,25 +78,37 @@ CONFIG_NF_CONNTRACK_FTP=m
 CONFIG_NF_CONNTRACK_H323=m
 CONFIG_NF_CONNTRACK_IRC=m
 CONFIG_NF_CONNTRACK_NETBIOS_NS=m
+CONFIG_NF_CONNTRACK_SNMP=m
 CONFIG_NF_CONNTRACK_PPTP=m
 CONFIG_NF_CONNTRACK_SANE=m
 CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NETFILTER_XT_SET=m
+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
 CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
 CONFIG_NETFILTER_XT_TARGET_DSCP=m
+CONFIG_NETFILTER_XT_TARGET_HMARK=m
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m
+CONFIG_NETFILTER_XT_TARGET_LOG=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_TEE=m
 CONFIG_NETFILTER_XT_TARGET_TRACE=m
 CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
+CONFIG_NETFILTER_XT_MATCH_BPF=m
 CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
 CONFIG_NETFILTER_XT_MATCH_COMMENT=m
 CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m
 CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
 CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
 CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m
 CONFIG_NETFILTER_XT_MATCH_DSCP=m
 CONFIG_NETFILTER_XT_MATCH_ESP=m
 CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
@@ -85,6 +119,8 @@ CONFIG_NETFILTER_XT_MATCH_LIMIT=m
 CONFIG_NETFILTER_XT_MATCH_MAC=m
 CONFIG_NETFILTER_XT_MATCH_MARK=m
 CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_NFACCT=m
+CONFIG_NETFILTER_XT_MATCH_OSF=m
 CONFIG_NETFILTER_XT_MATCH_OWNER=m
 CONFIG_NETFILTER_XT_MATCH_POLICY=m
 CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
@@ -98,22 +134,31 @@ CONFIG_NETFILTER_XT_MATCH_STRING=m
 CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
 CONFIG_NETFILTER_XT_MATCH_TIME=m
 CONFIG_NETFILTER_XT_MATCH_U32=m
+CONFIG_IP_SET=m
+CONFIG_IP_SET_BITMAP_IP=m
+CONFIG_IP_SET_BITMAP_IPMAC=m
+CONFIG_IP_SET_BITMAP_PORT=m
+CONFIG_IP_SET_HASH_IP=m
+CONFIG_IP_SET_HASH_IPPORT=m
+CONFIG_IP_SET_HASH_IPPORTIP=m
+CONFIG_IP_SET_HASH_IPPORTNET=m
+CONFIG_IP_SET_HASH_NET=m
+CONFIG_IP_SET_HASH_NETPORT=m
+CONFIG_IP_SET_HASH_NETIFACE=m
+CONFIG_IP_SET_LIST_SET=m
 CONFIG_NF_CONNTRACK_IPV4=m
-CONFIG_IP_NF_QUEUE=m
 CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_ADDRTYPE=m
 CONFIG_IP_NF_MATCH_AH=m
 CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_RPFILTER=m
 CONFIG_IP_NF_MATCH_TTL=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
-CONFIG_IP_NF_TARGET_LOG=m
 CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_NF_NAT=m
+CONFIG_NF_NAT_IPV4=m
 CONFIG_IP_NF_TARGET_MASQUERADE=m
 CONFIG_IP_NF_TARGET_NETMAP=m
 CONFIG_IP_NF_TARGET_REDIRECT=m
-CONFIG_NF_NAT_SNMP_BASIC=m
 CONFIG_IP_NF_MANGLE=m
 CONFIG_IP_NF_TARGET_CLUSTERIP=m
 CONFIG_IP_NF_TARGET_ECN=m
@@ -123,7 +168,6 @@ CONFIG_IP_NF_ARPTABLES=m
 CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
 CONFIG_NF_CONNTRACK_IPV6=m
-CONFIG_IP6_NF_QUEUE=m
 CONFIG_IP6_NF_IPTABLES=m
 CONFIG_IP6_NF_MATCH_AH=m
 CONFIG_IP6_NF_MATCH_EUI64=m
@@ -132,21 +176,34 @@ CONFIG_IP6_NF_MATCH_OPTS=m
 CONFIG_IP6_NF_MATCH_HL=m
 CONFIG_IP6_NF_MATCH_IPV6HEADER=m
 CONFIG_IP6_NF_MATCH_MH=m
+CONFIG_IP6_NF_MATCH_RPFILTER=m
 CONFIG_IP6_NF_MATCH_RT=m
 CONFIG_IP6_NF_TARGET_HL=m
-CONFIG_IP6_NF_TARGET_LOG=m
 CONFIG_IP6_NF_FILTER=m
 CONFIG_IP6_NF_TARGET_REJECT=m
 CONFIG_IP6_NF_MANGLE=m
 CONFIG_IP6_NF_RAW=m
+CONFIG_NF_NAT_IPV6=m
+CONFIG_IP6_NF_TARGET_MASQUERADE=m
+CONFIG_IP6_NF_TARGET_NPT=m
 CONFIG_IP_DCCP=m
 # CONFIG_IP_DCCP_CCID3 is not set
+CONFIG_SCTP_COOKIE_HMAC_SHA1=y
+CONFIG_RDS=m
+CONFIG_RDS_TCP=m
+CONFIG_L2TP=m
 CONFIG_ATALK=m
+CONFIG_BATMAN_ADV=m
+CONFIG_BATMAN_ADV_DAT=y
+# CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
 # CONFIG_FIRMWARE_IN_KERNEL is not set
+# CONFIG_FW_LOADER_USER_HELPER is not set
 CONFIG_CONNECTOR=m
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_DRBD=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_CDROM_PKTCDVD=m
@@ -161,59 +218,77 @@ CONFIG_BLK_DEV_SR=y
 CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
 CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_SAS_LIBSAS=m
-# CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set
-CONFIG_SCSI_SRP_ATTRS=m
-CONFIG_SCSI_SRP_TGT_ATTRS=y
+CONFIG_SCSI_SAS_ATTRS=m
 CONFIG_ISCSI_TCP=m
+CONFIG_ISCSI_BOOT_SYSFS=m
 CONFIG_MD=y
-CONFIG_BLK_DEV_MD=m
 CONFIG_MD_LINEAR=m
 CONFIG_MD_RAID0=m
-CONFIG_MD_RAID1=m
-CONFIG_MD_RAID456=m
 CONFIG_BLK_DEV_DM=m
 CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_THIN_PROVISIONING=m
+CONFIG_DM_CACHE=m
 CONFIG_DM_MIRROR=m
+CONFIG_DM_RAID=m
 CONFIG_DM_ZERO=m
 CONFIG_DM_MULTIPATH=m
 CONFIG_DM_UEVENT=y
+CONFIG_TARGET_CORE=m
+CONFIG_TCM_IBLOCK=m
+CONFIG_TCM_FILEIO=m
+CONFIG_TCM_PSCSI=m
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=m
-CONFIG_MACVLAN=m
 CONFIG_EQUALIZER=m
+CONFIG_NET_TEAM=m
+CONFIG_NET_TEAM_MODE_BROADCAST=m
+CONFIG_NET_TEAM_MODE_ROUNDROBIN=m
+CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m
+CONFIG_NET_TEAM_MODE_LOADBALANCE=m
+CONFIG_VXLAN=m
+CONFIG_NETCONSOLE=m
+CONFIG_NETCONSOLE_DYNAMIC=y
 CONFIG_VETH=m
-CONFIG_NET_ETHERNET=y
 CONFIG_HPLANCE=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
 CONFIG_PPP=m
-CONFIG_PPP_FILTER=y
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=m
 CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_FILTER=y
 CONFIG_PPP_MPPE=m
 CONFIG_PPPOE=m
+CONFIG_PPTP=m
+CONFIG_PPPOL2TP=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
 CONFIG_SLIP=m
 CONFIG_SLIP_COMPRESSED=y
 CONFIG_SLIP_SMART=y
 CONFIG_SLIP_MODE_SLIP6=y
-CONFIG_NETCONSOLE=m
-CONFIG_NETCONSOLE_DYNAMIC=y
-CONFIG_INPUT_FF_MEMLESS=m
+# CONFIG_WLAN is not set
+CONFIG_INPUT_EVDEV=m
 # CONFIG_KEYBOARD_ATKBD is not set
-CONFIG_MOUSE_PS2=m
+# CONFIG_MOUSE_PS2 is not set
 CONFIG_MOUSE_SERIAL=m
 CONFIG_INPUT_MISC=y
 CONFIG_HP_SDC_RTC=m
-# CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIO_SERPORT=m
 CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_LEGACY_PTYS is not set
 # CONFIG_DEVKMEM is not set
 # CONFIG_HW_RANDOM is not set
-CONFIG_GEN_RTC=m
-CONFIG_GEN_RTC_X=y
+CONFIG_NTP_PPS=y
+CONFIG_PPS_CLIENT_LDISC=m
+CONFIG_PTP_1588_CLOCK=m
 # CONFIG_HWMON is not set
 CONFIG_FB=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
@@ -222,47 +297,60 @@ CONFIG_LOGO=y
 # CONFIG_LOGO_LINUX_VGA16 is not set
 CONFIG_HID=m
 CONFIG_HIDRAW=y
+CONFIG_UHID=m
+# CONFIG_HID_GENERIC is not set
 # CONFIG_USB_SUPPORT is not set
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_GENERIC=m
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_PROC_HARDWARE=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 # CONFIG_EXT3_FS_XATTR is not set
+CONFIG_EXT4_FS=y
 CONFIG_REISERFS_FS=m
 CONFIG_JFS_FS=m
 CONFIG_XFS_FS=m
 CONFIG_OCFS2_FS=m
-# CONFIG_OCFS2_FS_STATS is not set
 # CONFIG_OCFS2_DEBUG_MASKLOG is not set
+CONFIG_FANOTIFY=y
 CONFIG_QUOTA_NETLINK_INTERFACE=y
 # CONFIG_PRINT_QUOTA_WARNING is not set
-CONFIG_AUTOFS_FS=m
 CONFIG_AUTOFS4_FS=m
 CONFIG_FUSE_FS=m
+CONFIG_CUSE=m
 CONFIG_ISO9660_FS=y
 CONFIG_JOLIET=y
 CONFIG_ZISOFS=y
 CONFIG_UDF_FS=m
-CONFIG_MSDOS_FS=y
+CONFIG_MSDOS_FS=m
 CONFIG_VFAT_FS=m
 CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
 CONFIG_AFFS_FS=m
+CONFIG_ECRYPT_FS=m
+CONFIG_ECRYPT_FS_MESSAGING=y
 CONFIG_HFS_FS=m
 CONFIG_HFSPLUS_FS=m
 CONFIG_CRAMFS=m
 CONFIG_SQUASHFS=m
-CONFIG_MINIX_FS=y
+CONFIG_SQUASHFS_LZO=y
+CONFIG_MINIX_FS=m
+CONFIG_OMFS_FS=m
 CONFIG_HPFS_FS=m
+CONFIG_QNX4FS_FS=m
+CONFIG_QNX6FS_FS=m
 CONFIG_SYSV_FS=m
 CONFIG_UFS_FS=m
 CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
 CONFIG_NFS_V4=y
+CONFIG_NFS_SWAP=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
 CONFIG_NFSD_V3=y
-CONFIG_SMB_FS=m
-CONFIG_SMB_NLS_DEFAULT=y
+CONFIG_CIFS=m
+# CONFIG_CIFS_DEBUG is not set
 CONFIG_CODA_FS=m
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_CODEPAGE_737=m
@@ -301,10 +389,23 @@ CONFIG_NLS_ISO8859_14=m
 CONFIG_NLS_ISO8859_15=m
 CONFIG_NLS_KOI8_R=m
 CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_MAC_ROMAN=m
+CONFIG_NLS_MAC_CELTIC=m
+CONFIG_NLS_MAC_CENTEURO=m
+CONFIG_NLS_MAC_CROATIAN=m
+CONFIG_NLS_MAC_CYRILLIC=m
+CONFIG_NLS_MAC_GAELIC=m
+CONFIG_NLS_MAC_GREEK=m
+CONFIG_NLS_MAC_ICELAND=m
+CONFIG_NLS_MAC_INUIT=m
+CONFIG_NLS_MAC_ROMANIAN=m
+CONFIG_NLS_MAC_TURKISH=m
 CONFIG_DLM=m
 CONFIG_MAGIC_SYSRQ=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_ASYNC_RAID6_TEST=m
+CONFIG_ENCRYPTED_KEYS=m
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_USER=m
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_CRYPTD=m
 CONFIG_CRYPTO_TEST=m
@@ -314,19 +415,16 @@ CONFIG_CRYPTO_CTS=m
 CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_XTS=m
-CONFIG_CRYPTO_HMAC=y
 CONFIG_CRYPTO_XCBC=m
-CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_VMAC=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_RMD128=m
 CONFIG_CRYPTO_RMD160=m
 CONFIG_CRYPTO_RMD256=m
 CONFIG_CRYPTO_RMD320=m
-CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_ANUBIS=m
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_CAMELLIA=m
@@ -342,6 +440,14 @@ CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_ZLIB=m
 CONFIG_CRYPTO_LZO=m
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_USER_API_HASH=m
+CONFIG_CRYPTO_USER_API_SKCIPHER=m
 # CONFIG_CRYPTO_HW is not set
-CONFIG_CRC16=m
 CONFIG_CRC_T10DIF=y
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
+CONFIG_XZ_DEC_TEST=m
index cb9dfb3..7d46fbe 100644 (file)
@@ -1,49 +1,75 @@
-CONFIG_EXPERIMENTAL=y
 CONFIG_LOCALVERSION="-mac"
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_FHANDLE=y
 CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_RELAY=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_LOG_BUF_SHIFT=16
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
-CONFIG_MAC=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_AMIGA_PARTITION=y
+CONFIG_ATARI_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+CONFIG_SUN_PARTITION=y
+# CONFIG_EFI_PARTITION is not set
+CONFIG_SYSV68_PARTITION=y
+CONFIG_IOSCHED_DEADLINE=m
 CONFIG_M68020=y
 CONFIG_M68030=y
 CONFIG_M68040=y
+CONFIG_M68KFPU_EMU=y
+CONFIG_MAC=y
+# CONFIG_COMPACTION is not set
+CONFIG_CLEANCACHE=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_BINFMT_AOUT=m
 CONFIG_BINFMT_MISC=m
-CONFIG_PROC_HARDWARE=y
 CONFIG_NET=y
 CONFIG_PACKET=y
+CONFIG_PACKET_DIAG=m
 CONFIG_UNIX=y
+CONFIG_UNIX_DIAG=m
+CONFIG_XFRM_MIGRATE=y
 CONFIG_NET_KEY=y
-CONFIG_NET_KEY_MIGRATE=y
 CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
 CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE_DEMUX=m
 CONFIG_NET_IPGRE=m
 CONFIG_SYN_COOKIES=y
+CONFIG_NET_IPVTI=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
 CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
 CONFIG_INET_XFRM_MODE_BEET=m
+# CONFIG_INET_LRO is not set
 CONFIG_INET_DIAG=m
+CONFIG_INET_UDP_DIAG=m
 CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
-CONFIG_IPV6_ROUTE_INFO=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
-CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
-CONFIG_IPV6_TUNNEL=m
+CONFIG_IPV6_GRE=m
 CONFIG_NETFILTER=y
-CONFIG_NETFILTER_NETLINK_QUEUE=m
 CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CONNTRACK_ZONES=y
+# CONFIG_NF_CONNTRACK_PROCFS is not set
 # CONFIG_NF_CT_PROTO_DCCP is not set
 CONFIG_NF_CT_PROTO_UDPLITE=m
 CONFIG_NF_CONNTRACK_AMANDA=m
@@ -51,25 +77,37 @@ CONFIG_NF_CONNTRACK_FTP=m
 CONFIG_NF_CONNTRACK_H323=m
 CONFIG_NF_CONNTRACK_IRC=m
 CONFIG_NF_CONNTRACK_NETBIOS_NS=m
+CONFIG_NF_CONNTRACK_SNMP=m
 CONFIG_NF_CONNTRACK_PPTP=m
 CONFIG_NF_CONNTRACK_SANE=m
 CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NETFILTER_XT_SET=m
+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
 CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
 CONFIG_NETFILTER_XT_TARGET_DSCP=m
+CONFIG_NETFILTER_XT_TARGET_HMARK=m
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m
+CONFIG_NETFILTER_XT_TARGET_LOG=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_TEE=m
 CONFIG_NETFILTER_XT_TARGET_TRACE=m
 CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
+CONFIG_NETFILTER_XT_MATCH_BPF=m
 CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
 CONFIG_NETFILTER_XT_MATCH_COMMENT=m
 CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m
 CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
 CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
 CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m
 CONFIG_NETFILTER_XT_MATCH_DSCP=m
 CONFIG_NETFILTER_XT_MATCH_ESP=m
 CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
@@ -80,6 +118,8 @@ CONFIG_NETFILTER_XT_MATCH_LIMIT=m
 CONFIG_NETFILTER_XT_MATCH_MAC=m
 CONFIG_NETFILTER_XT_MATCH_MARK=m
 CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_NFACCT=m
+CONFIG_NETFILTER_XT_MATCH_OSF=m
 CONFIG_NETFILTER_XT_MATCH_OWNER=m
 CONFIG_NETFILTER_XT_MATCH_POLICY=m
 CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
@@ -93,22 +133,31 @@ CONFIG_NETFILTER_XT_MATCH_STRING=m
 CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
 CONFIG_NETFILTER_XT_MATCH_TIME=m
 CONFIG_NETFILTER_XT_MATCH_U32=m
+CONFIG_IP_SET=m
+CONFIG_IP_SET_BITMAP_IP=m
+CONFIG_IP_SET_BITMAP_IPMAC=m
+CONFIG_IP_SET_BITMAP_PORT=m
+CONFIG_IP_SET_HASH_IP=m
+CONFIG_IP_SET_HASH_IPPORT=m
+CONFIG_IP_SET_HASH_IPPORTIP=m
+CONFIG_IP_SET_HASH_IPPORTNET=m
+CONFIG_IP_SET_HASH_NET=m
+CONFIG_IP_SET_HASH_NETPORT=m
+CONFIG_IP_SET_HASH_NETIFACE=m
+CONFIG_IP_SET_LIST_SET=m
 CONFIG_NF_CONNTRACK_IPV4=m
-CONFIG_IP_NF_QUEUE=m
 CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_ADDRTYPE=m
 CONFIG_IP_NF_MATCH_AH=m
 CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_RPFILTER=m
 CONFIG_IP_NF_MATCH_TTL=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
-CONFIG_IP_NF_TARGET_LOG=m
 CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_NF_NAT=m
+CONFIG_NF_NAT_IPV4=m
 CONFIG_IP_NF_TARGET_MASQUERADE=m
 CONFIG_IP_NF_TARGET_NETMAP=m
 CONFIG_IP_NF_TARGET_REDIRECT=m
-CONFIG_NF_NAT_SNMP_BASIC=m
 CONFIG_IP_NF_MANGLE=m
 CONFIG_IP_NF_TARGET_CLUSTERIP=m
 CONFIG_IP_NF_TARGET_ECN=m
@@ -118,7 +167,6 @@ CONFIG_IP_NF_ARPTABLES=m
 CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
 CONFIG_NF_CONNTRACK_IPV6=m
-CONFIG_IP6_NF_QUEUE=m
 CONFIG_IP6_NF_IPTABLES=m
 CONFIG_IP6_NF_MATCH_AH=m
 CONFIG_IP6_NF_MATCH_EUI64=m
@@ -127,31 +175,45 @@ CONFIG_IP6_NF_MATCH_OPTS=m
 CONFIG_IP6_NF_MATCH_HL=m
 CONFIG_IP6_NF_MATCH_IPV6HEADER=m
 CONFIG_IP6_NF_MATCH_MH=m
+CONFIG_IP6_NF_MATCH_RPFILTER=m
 CONFIG_IP6_NF_MATCH_RT=m
 CONFIG_IP6_NF_TARGET_HL=m
-CONFIG_IP6_NF_TARGET_LOG=m
 CONFIG_IP6_NF_FILTER=m
 CONFIG_IP6_NF_TARGET_REJECT=m
 CONFIG_IP6_NF_MANGLE=m
 CONFIG_IP6_NF_RAW=m
+CONFIG_NF_NAT_IPV6=m
+CONFIG_IP6_NF_TARGET_MASQUERADE=m
+CONFIG_IP6_NF_TARGET_NPT=m
 CONFIG_IP_DCCP=m
 # CONFIG_IP_DCCP_CCID3 is not set
+CONFIG_SCTP_COOKIE_HMAC_SHA1=y
+CONFIG_RDS=m
+CONFIG_RDS_TCP=m
+CONFIG_L2TP=m
 CONFIG_ATALK=m
 CONFIG_DEV_APPLETALK=m
 CONFIG_IPDDP=m
 CONFIG_IPDDP_ENCAP=y
 CONFIG_IPDDP_DECAP=y
+CONFIG_BATMAN_ADV=m
+CONFIG_BATMAN_ADV_DAT=y
+# CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
 # CONFIG_FIRMWARE_IN_KERNEL is not set
+# CONFIG_FW_LOADER_USER_HELPER is not set
 CONFIG_CONNECTOR=m
-CONFIG_BLK_DEV_SWIM=y
+CONFIG_BLK_DEV_SWIM=m
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_DRBD=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_ATA_OVER_ETH=m
 CONFIG_IDE=y
+CONFIG_IDE_GD_ATAPI=y
 CONFIG_BLK_DEV_IDECD=y
 CONFIG_BLK_DEV_MAC_IDE=y
 CONFIG_RAID_ATTRS=m
@@ -164,29 +226,30 @@ CONFIG_BLK_DEV_SR=y
 CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
 CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_SAS_LIBSAS=m
-# CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set
-CONFIG_SCSI_SRP_ATTRS=m
-CONFIG_SCSI_SRP_TGT_ATTRS=y
+CONFIG_SCSI_SAS_ATTRS=m
 CONFIG_ISCSI_TCP=m
+CONFIG_ISCSI_BOOT_SYSFS=m
 CONFIG_MAC_SCSI=y
 CONFIG_SCSI_MAC_ESP=y
 CONFIG_MD=y
-CONFIG_BLK_DEV_MD=m
 CONFIG_MD_LINEAR=m
 CONFIG_MD_RAID0=m
-CONFIG_MD_RAID1=m
-CONFIG_MD_RAID456=m
 CONFIG_BLK_DEV_DM=m
 CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_THIN_PROVISIONING=m
+CONFIG_DM_CACHE=m
 CONFIG_DM_MIRROR=m
+CONFIG_DM_RAID=m
 CONFIG_DM_ZERO=m
 CONFIG_DM_MULTIPATH=m
 CONFIG_DM_UEVENT=y
+CONFIG_TARGET_CORE=m
+CONFIG_TCM_IBLOCK=m
+CONFIG_TCM_FILEIO=m
+CONFIG_TCM_PSCSI=m
 CONFIG_ADB=y
 CONFIG_ADB_MACII=y
-CONFIG_ADB_MACIISI=y
 CONFIG_ADB_IOP=y
 CONFIG_ADB_PMU68K=y
 CONFIG_ADB_CUDA=y
@@ -194,46 +257,61 @@ CONFIG_INPUT_ADBHID=y
 CONFIG_MAC_EMUMOUSEBTN=y
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=m
-CONFIG_MACVLAN=m
 CONFIG_EQUALIZER=m
+CONFIG_NET_TEAM=m
+CONFIG_NET_TEAM_MODE_BROADCAST=m
+CONFIG_NET_TEAM_MODE_ROUNDROBIN=m
+CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m
+CONFIG_NET_TEAM_MODE_LOADBALANCE=m
+CONFIG_VXLAN=m
+CONFIG_NETCONSOLE=m
+CONFIG_NETCONSOLE_DYNAMIC=y
 CONFIG_VETH=m
-CONFIG_NET_ETHERNET=y
-CONFIG_MAC8390=y
-CONFIG_MAC89x0=m
-CONFIG_MACSONIC=m
 CONFIG_MACMACE=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+CONFIG_MAC89x0=y
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+CONFIG_MACSONIC=y
+CONFIG_MAC8390=y
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
 CONFIG_PPP=m
-CONFIG_PPP_FILTER=y
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=m
 CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_FILTER=y
 CONFIG_PPP_MPPE=m
 CONFIG_PPPOE=m
+CONFIG_PPTP=m
+CONFIG_PPPOL2TP=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
 CONFIG_SLIP=m
 CONFIG_SLIP_COMPRESSED=y
 CONFIG_SLIP_SMART=y
 CONFIG_SLIP_MODE_SLIP6=y
-CONFIG_NETCONSOLE=m
-CONFIG_NETCONSOLE_DYNAMIC=y
-CONFIG_INPUT_FF_MEMLESS=m
+# CONFIG_WLAN is not set
+CONFIG_INPUT_EVDEV=m
 # CONFIG_KEYBOARD_ATKBD is not set
-CONFIG_MOUSE_PS2=m
+# CONFIG_MOUSE_PS2 is not set
 CONFIG_MOUSE_SERIAL=m
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_M68K_BEEP=m
 CONFIG_SERIO=m
-# CONFIG_SERIO_SERPORT is not set
 CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_LEGACY_PTYS is not set
 # CONFIG_DEVKMEM is not set
 CONFIG_SERIAL_PMACZILOG=y
 CONFIG_SERIAL_PMACZILOG_TTYS=y
 CONFIG_SERIAL_PMACZILOG_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
-CONFIG_GEN_RTC=m
-CONFIG_GEN_RTC_X=y
+CONFIG_NTP_PPS=y
+CONFIG_PPS_CLIENT_LDISC=m
+CONFIG_PTP_1588_CLOCK=m
 # CONFIG_HWMON is not set
 CONFIG_FB=y
 CONFIG_FB_VALKYRIE=y
@@ -242,46 +320,60 @@ CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_LOGO=y
 CONFIG_HID=m
 CONFIG_HIDRAW=y
+CONFIG_UHID=m
+# CONFIG_HID_GENERIC is not set
 # CONFIG_USB_SUPPORT is not set
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_GENERIC=m
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_PROC_HARDWARE=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 # CONFIG_EXT3_FS_XATTR is not set
+CONFIG_EXT4_FS=y
 CONFIG_REISERFS_FS=m
 CONFIG_JFS_FS=m
 CONFIG_XFS_FS=m
 CONFIG_OCFS2_FS=m
-# CONFIG_OCFS2_FS_STATS is not set
 # CONFIG_OCFS2_DEBUG_MASKLOG is not set
+CONFIG_FANOTIFY=y
 CONFIG_QUOTA_NETLINK_INTERFACE=y
 # CONFIG_PRINT_QUOTA_WARNING is not set
-CONFIG_AUTOFS_FS=m
 CONFIG_AUTOFS4_FS=m
 CONFIG_FUSE_FS=m
+CONFIG_CUSE=m
 CONFIG_ISO9660_FS=y
 CONFIG_JOLIET=y
 CONFIG_ZISOFS=y
 CONFIG_UDF_FS=m
-CONFIG_MSDOS_FS=y
+CONFIG_MSDOS_FS=m
 CONFIG_VFAT_FS=m
 CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
 CONFIG_AFFS_FS=m
-CONFIG_HFS_FS=y
-CONFIG_HFSPLUS_FS=y
+CONFIG_ECRYPT_FS=m
+CONFIG_ECRYPT_FS_MESSAGING=y
+CONFIG_HFS_FS=m
+CONFIG_HFSPLUS_FS=m
 CONFIG_CRAMFS=m
 CONFIG_SQUASHFS=m
-CONFIG_MINIX_FS=y
+CONFIG_SQUASHFS_LZO=y
+CONFIG_MINIX_FS=m
+CONFIG_OMFS_FS=m
 CONFIG_HPFS_FS=m
+CONFIG_QNX4FS_FS=m
+CONFIG_QNX6FS_FS=m
 CONFIG_SYSV_FS=m
 CONFIG_UFS_FS=m
-CONFIG_NFS_FS=m
-CONFIG_NFS_V3=y
+CONFIG_NFS_FS=y
 CONFIG_NFS_V4=y
+CONFIG_NFS_SWAP=y
+CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
 CONFIG_NFSD_V3=y
-CONFIG_SMB_FS=m
-CONFIG_SMB_NLS_DEFAULT=y
+CONFIG_CIFS=m
+# CONFIG_CIFS_DEBUG is not set
 CONFIG_CODA_FS=m
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_CODEPAGE_737=m
@@ -320,10 +412,23 @@ CONFIG_NLS_ISO8859_14=m
 CONFIG_NLS_ISO8859_15=m
 CONFIG_NLS_KOI8_R=m
 CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_MAC_ROMAN=m
+CONFIG_NLS_MAC_CELTIC=m
+CONFIG_NLS_MAC_CENTEURO=m
+CONFIG_NLS_MAC_CROATIAN=m
+CONFIG_NLS_MAC_CYRILLIC=m
+CONFIG_NLS_MAC_GAELIC=m
+CONFIG_NLS_MAC_GREEK=m
+CONFIG_NLS_MAC_ICELAND=m
+CONFIG_NLS_MAC_INUIT=m
+CONFIG_NLS_MAC_ROMANIAN=m
+CONFIG_NLS_MAC_TURKISH=m
 CONFIG_DLM=m
 CONFIG_MAGIC_SYSRQ=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_ASYNC_RAID6_TEST=m
+CONFIG_ENCRYPTED_KEYS=m
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_USER=m
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_CRYPTD=m
 CONFIG_CRYPTO_TEST=m
@@ -333,19 +438,16 @@ CONFIG_CRYPTO_CTS=m
 CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_XTS=m
-CONFIG_CRYPTO_HMAC=y
 CONFIG_CRYPTO_XCBC=m
-CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_VMAC=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_RMD128=m
 CONFIG_CRYPTO_RMD160=m
 CONFIG_CRYPTO_RMD256=m
 CONFIG_CRYPTO_RMD320=m
-CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_ANUBIS=m
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_CAMELLIA=m
@@ -361,6 +463,14 @@ CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_ZLIB=m
 CONFIG_CRYPTO_LZO=m
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_USER_API_HASH=m
+CONFIG_CRYPTO_USER_API_SKCIPHER=m
 # CONFIG_CRYPTO_HW is not set
-CONFIG_CRC16=m
 CONFIG_CRC_T10DIF=y
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
+CONFIG_XZ_DEC_TEST=m
index 8d5def4..0f795d8 100644 (file)
@@ -1,15 +1,29 @@
-CONFIG_EXPERIMENTAL=y
 CONFIG_LOCALVERSION="-multi"
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_FHANDLE=y
 CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_RELAY=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_LOG_BUF_SHIFT=16
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+# CONFIG_EFI_PARTITION is not set
+CONFIG_IOSCHED_DEADLINE=m
+CONFIG_M68020=y
+CONFIG_M68040=y
+CONFIG_M68060=y
+CONFIG_M68KFPU_EMU=y
 CONFIG_AMIGA=y
 CONFIG_ATARI=y
 CONFIG_MAC=y
@@ -21,48 +35,50 @@ CONFIG_BVME6000=y
 CONFIG_HP300=y
 CONFIG_SUN3X=y
 CONFIG_Q40=y
-CONFIG_M68020=y
-CONFIG_M68040=y
-CONFIG_M68060=y
-CONFIG_BINFMT_AOUT=m
-CONFIG_BINFMT_MISC=m
 CONFIG_ZORRO=y
 CONFIG_AMIGA_PCMCIA=y
-CONFIG_STRAM_PROC=y
-CONFIG_HEARTBEAT=y
-CONFIG_PROC_HARDWARE=y
 CONFIG_ZORRO_NAMES=y
+# CONFIG_COMPACTION is not set
+CONFIG_CLEANCACHE=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_BINFMT_AOUT=m
+CONFIG_BINFMT_MISC=m
 CONFIG_NET=y
 CONFIG_PACKET=y
+CONFIG_PACKET_DIAG=m
 CONFIG_UNIX=y
+CONFIG_UNIX_DIAG=m
+CONFIG_XFRM_MIGRATE=y
 CONFIG_NET_KEY=y
-CONFIG_NET_KEY_MIGRATE=y
 CONFIG_INET=y
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=y
 CONFIG_IP_PNP_BOOTP=y
 CONFIG_IP_PNP_RARP=y
 CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE_DEMUX=m
 CONFIG_NET_IPGRE=m
 CONFIG_SYN_COOKIES=y
+CONFIG_NET_IPVTI=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
 CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
 CONFIG_INET_XFRM_MODE_BEET=m
+# CONFIG_INET_LRO is not set
 CONFIG_INET_DIAG=m
+CONFIG_INET_UDP_DIAG=m
 CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
-CONFIG_IPV6_ROUTE_INFO=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
-CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
-CONFIG_IPV6_TUNNEL=m
+CONFIG_IPV6_GRE=m
 CONFIG_NETFILTER=y
-CONFIG_NETFILTER_NETLINK_QUEUE=m
 CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CONNTRACK_ZONES=y
+# CONFIG_NF_CONNTRACK_PROCFS is not set
 # CONFIG_NF_CT_PROTO_DCCP is not set
 CONFIG_NF_CT_PROTO_UDPLITE=m
 CONFIG_NF_CONNTRACK_AMANDA=m
@@ -70,25 +86,37 @@ CONFIG_NF_CONNTRACK_FTP=m
 CONFIG_NF_CONNTRACK_H323=m
 CONFIG_NF_CONNTRACK_IRC=m
 CONFIG_NF_CONNTRACK_NETBIOS_NS=m
+CONFIG_NF_CONNTRACK_SNMP=m
 CONFIG_NF_CONNTRACK_PPTP=m
 CONFIG_NF_CONNTRACK_SANE=m
 CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NETFILTER_XT_SET=m
+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
 CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
 CONFIG_NETFILTER_XT_TARGET_DSCP=m
+CONFIG_NETFILTER_XT_TARGET_HMARK=m
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m
+CONFIG_NETFILTER_XT_TARGET_LOG=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_TEE=m
 CONFIG_NETFILTER_XT_TARGET_TRACE=m
 CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
+CONFIG_NETFILTER_XT_MATCH_BPF=m
 CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
 CONFIG_NETFILTER_XT_MATCH_COMMENT=m
 CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m
 CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
 CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
 CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m
 CONFIG_NETFILTER_XT_MATCH_DSCP=m
 CONFIG_NETFILTER_XT_MATCH_ESP=m
 CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
@@ -99,6 +127,8 @@ CONFIG_NETFILTER_XT_MATCH_LIMIT=m
 CONFIG_NETFILTER_XT_MATCH_MAC=m
 CONFIG_NETFILTER_XT_MATCH_MARK=m
 CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_NFACCT=m
+CONFIG_NETFILTER_XT_MATCH_OSF=m
 CONFIG_NETFILTER_XT_MATCH_OWNER=m
 CONFIG_NETFILTER_XT_MATCH_POLICY=m
 CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
@@ -112,22 +142,31 @@ CONFIG_NETFILTER_XT_MATCH_STRING=m
 CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
 CONFIG_NETFILTER_XT_MATCH_TIME=m
 CONFIG_NETFILTER_XT_MATCH_U32=m
+CONFIG_IP_SET=m
+CONFIG_IP_SET_BITMAP_IP=m
+CONFIG_IP_SET_BITMAP_IPMAC=m
+CONFIG_IP_SET_BITMAP_PORT=m
+CONFIG_IP_SET_HASH_IP=m
+CONFIG_IP_SET_HASH_IPPORT=m
+CONFIG_IP_SET_HASH_IPPORTIP=m
+CONFIG_IP_SET_HASH_IPPORTNET=m
+CONFIG_IP_SET_HASH_NET=m
+CONFIG_IP_SET_HASH_NETPORT=m
+CONFIG_IP_SET_HASH_NETIFACE=m
+CONFIG_IP_SET_LIST_SET=m
 CONFIG_NF_CONNTRACK_IPV4=m
-CONFIG_IP_NF_QUEUE=m
 CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_ADDRTYPE=m
 CONFIG_IP_NF_MATCH_AH=m
 CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_RPFILTER=m
 CONFIG_IP_NF_MATCH_TTL=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
-CONFIG_IP_NF_TARGET_LOG=m
 CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_NF_NAT=m
+CONFIG_NF_NAT_IPV4=m
 CONFIG_IP_NF_TARGET_MASQUERADE=m
 CONFIG_IP_NF_TARGET_NETMAP=m
 CONFIG_IP_NF_TARGET_REDIRECT=m
-CONFIG_NF_NAT_SNMP_BASIC=m
 CONFIG_IP_NF_MANGLE=m
 CONFIG_IP_NF_TARGET_CLUSTERIP=m
 CONFIG_IP_NF_TARGET_ECN=m
@@ -137,7 +176,6 @@ CONFIG_IP_NF_ARPTABLES=m
 CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
 CONFIG_NF_CONNTRACK_IPV6=m
-CONFIG_IP6_NF_QUEUE=m
 CONFIG_IP6_NF_IPTABLES=m
 CONFIG_IP6_NF_MATCH_AH=m
 CONFIG_IP6_NF_MATCH_EUI64=m
@@ -146,22 +184,34 @@ CONFIG_IP6_NF_MATCH_OPTS=m
 CONFIG_IP6_NF_MATCH_HL=m
 CONFIG_IP6_NF_MATCH_IPV6HEADER=m
 CONFIG_IP6_NF_MATCH_MH=m
+CONFIG_IP6_NF_MATCH_RPFILTER=m
 CONFIG_IP6_NF_MATCH_RT=m
 CONFIG_IP6_NF_TARGET_HL=m
-CONFIG_IP6_NF_TARGET_LOG=m
 CONFIG_IP6_NF_FILTER=m
 CONFIG_IP6_NF_TARGET_REJECT=m
 CONFIG_IP6_NF_MANGLE=m
 CONFIG_IP6_NF_RAW=m
+CONFIG_NF_NAT_IPV6=m
+CONFIG_IP6_NF_TARGET_MASQUERADE=m
+CONFIG_IP6_NF_TARGET_NPT=m
 CONFIG_IP_DCCP=m
 # CONFIG_IP_DCCP_CCID3 is not set
+CONFIG_SCTP_COOKIE_HMAC_SHA1=y
+CONFIG_RDS=m
+CONFIG_RDS_TCP=m
+CONFIG_L2TP=m
 CONFIG_ATALK=m
 CONFIG_DEV_APPLETALK=m
 CONFIG_IPDDP=m
 CONFIG_IPDDP_ENCAP=y
 CONFIG_IPDDP_DECAP=y
+CONFIG_BATMAN_ADV=m
+CONFIG_BATMAN_ADV_DAT=y
+# CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
 # CONFIG_FIRMWARE_IN_KERNEL is not set
+# CONFIG_FW_LOADER_USER_HELPER is not set
 CONFIG_CONNECTOR=m
 CONFIG_PARPORT=m
 CONFIG_PARPORT_AMIGA=m
@@ -170,15 +220,17 @@ CONFIG_PARPORT_ATARI=m
 CONFIG_PARPORT_1284=y
 CONFIG_AMIGA_FLOPPY=y
 CONFIG_ATARI_FLOPPY=y
-CONFIG_BLK_DEV_SWIM=y
+CONFIG_BLK_DEV_SWIM=m
 CONFIG_AMIGA_Z2RAM=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_DRBD=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_ATA_OVER_ETH=m
 CONFIG_IDE=y
+CONFIG_IDE_GD_ATAPI=y
 CONFIG_BLK_DEV_IDECD=y
 CONFIG_BLK_DEV_GAYLE=y
 CONFIG_BLK_DEV_BUDDHA=y
@@ -195,11 +247,9 @@ CONFIG_BLK_DEV_SR=y
 CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
 CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_SAS_LIBSAS=m
-# CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set
-CONFIG_SCSI_SRP_ATTRS=m
-CONFIG_SCSI_SRP_TGT_ATTRS=y
+CONFIG_SCSI_SAS_ATTRS=m
 CONFIG_ISCSI_TCP=m
+CONFIG_ISCSI_BOOT_SYSFS=m
 CONFIG_A3000_SCSI=y
 CONFIG_A2091_SCSI=y
 CONFIG_GVP11_SCSI=y
@@ -213,21 +263,24 @@ CONFIG_MVME16x_SCSI=y
 CONFIG_BVME6000_SCSI=y
 CONFIG_SUN3X_ESP=y
 CONFIG_MD=y
-CONFIG_BLK_DEV_MD=m
 CONFIG_MD_LINEAR=m
 CONFIG_MD_RAID0=m
-CONFIG_MD_RAID1=m
-CONFIG_MD_RAID456=m
 CONFIG_BLK_DEV_DM=m
 CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_THIN_PROVISIONING=m
+CONFIG_DM_CACHE=m
 CONFIG_DM_MIRROR=m
+CONFIG_DM_RAID=m
 CONFIG_DM_ZERO=m
 CONFIG_DM_MULTIPATH=m
 CONFIG_DM_UEVENT=y
+CONFIG_TARGET_CORE=m
+CONFIG_TCM_IBLOCK=m
+CONFIG_TCM_FILEIO=m
+CONFIG_TCM_PSCSI=m
 CONFIG_ADB=y
 CONFIG_ADB_MACII=y
-CONFIG_ADB_MACIISI=y
 CONFIG_ADB_IOP=y
 CONFIG_ADB_PMU68K=y
 CONFIG_ADB_CUDA=y
@@ -235,49 +288,64 @@ CONFIG_INPUT_ADBHID=y
 CONFIG_MAC_EMUMOUSEBTN=y
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=m
-CONFIG_MACVLAN=m
 CONFIG_EQUALIZER=m
-CONFIG_VETH=m
-CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
-CONFIG_ARIADNE=y
+CONFIG_NET_TEAM=m
+CONFIG_NET_TEAM_MODE_BROADCAST=m
+CONFIG_NET_TEAM_MODE_ROUNDROBIN=m
+CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m
+CONFIG_NET_TEAM_MODE_LOADBALANCE=m
+CONFIG_VXLAN=m
+CONFIG_NETCONSOLE=m
+CONFIG_NETCONSOLE_DYNAMIC=y
+CONFIG_VETH=m
+# CONFIG_NET_VENDOR_3COM is not set
 CONFIG_A2065=y
-CONFIG_HYDRA=y
-CONFIG_ZORRO8390=y
-CONFIG_APNE=y
-CONFIG_MAC8390=y
-CONFIG_MAC89x0=y
-CONFIG_MACSONIC=y
-CONFIG_MACMACE=y
-CONFIG_MVME147_NET=y
-CONFIG_MVME16x_NET=y
-CONFIG_BVME6000_NET=y
+CONFIG_ARIADNE=y
 CONFIG_ATARILANCE=y
-CONFIG_SUN3LANCE=y
 CONFIG_HPLANCE=y
+CONFIG_MVME147_NET=y
+CONFIG_SUN3LANCE=y
+CONFIG_MACMACE=y
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+CONFIG_MAC89x0=y
+# CONFIG_NET_VENDOR_FUJITSU is not set
+# CONFIG_NET_VENDOR_HP is not set
+CONFIG_BVME6000_NET=y
+CONFIG_MVME16x_NET=y
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+CONFIG_MACSONIC=y
+CONFIG_HYDRA=y
+CONFIG_MAC8390=y
 CONFIG_NE2000=m
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
+CONFIG_APNE=y
+CONFIG_ZORRO8390=y
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
 CONFIG_PPP=m
-CONFIG_PPP_FILTER=y
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=m
 CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_FILTER=y
 CONFIG_PPP_MPPE=m
 CONFIG_PPPOE=m
+CONFIG_PPTP=m
+CONFIG_PPPOL2TP=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
 CONFIG_SLIP=m
 CONFIG_SLIP_COMPRESSED=y
 CONFIG_SLIP_SMART=y
 CONFIG_SLIP_MODE_SLIP6=y
-CONFIG_NETCONSOLE=m
-CONFIG_NETCONSOLE_DYNAMIC=y
-CONFIG_INPUT_FF_MEMLESS=m
+# CONFIG_WLAN is not set
+CONFIG_INPUT_EVDEV=m
 CONFIG_KEYBOARD_AMIGA=y
 CONFIG_KEYBOARD_ATARI=y
 # CONFIG_KEYBOARD_ATKBD is not set
 CONFIG_KEYBOARD_SUNKBD=y
-CONFIG_MOUSE_PS2=m
+# CONFIG_MOUSE_PS2 is not set
 CONFIG_MOUSE_SERIAL=m
 CONFIG_MOUSE_AMIGA=m
 CONFIG_MOUSE_ATARI=m
@@ -285,18 +353,20 @@ CONFIG_INPUT_JOYSTICK=y
 CONFIG_JOYSTICK_AMIGA=m
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_M68K_BEEP=m
-CONFIG_HP_SDC_RTC=y
-# CONFIG_SERIO_SERPORT is not set
+CONFIG_HP_SDC_RTC=m
 CONFIG_SERIO_Q40KBD=y
 CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_LEGACY_PTYS is not set
 # CONFIG_DEVKMEM is not set
 CONFIG_SERIAL_PMACZILOG=y
 CONFIG_SERIAL_PMACZILOG_TTYS=y
 CONFIG_SERIAL_PMACZILOG_CONSOLE=y
 CONFIG_PRINTER=m
 # CONFIG_HW_RANDOM is not set
-CONFIG_GEN_RTC=y
-CONFIG_GEN_RTC_X=y
+CONFIG_NTP_PPS=y
+CONFIG_PPS_CLIENT_LDISC=m
+CONFIG_PPS_CLIENT_PARPORT=m
+CONFIG_PTP_1588_CLOCK=m
 # CONFIG_HWMON is not set
 CONFIG_FB=y
 CONFIG_FB_CIRRUS=y
@@ -316,7 +386,20 @@ CONFIG_DMASOUND_PAULA=m
 CONFIG_DMASOUND_Q40=m
 CONFIG_HID=m
 CONFIG_HIDRAW=y
+CONFIG_UHID=m
+# CONFIG_HID_GENERIC is not set
 # CONFIG_USB_SUPPORT is not set
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_MSM6242=m
+CONFIG_RTC_DRV_RP5C01=m
+CONFIG_RTC_DRV_GENERIC=m
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_HEARTBEAT=y
+CONFIG_PROC_HARDWARE=y
+CONFIG_NATFEAT=y
+CONFIG_NFBLOCK=y
+CONFIG_NFCON=y
+CONFIG_NFETH=y
 CONFIG_ATARI_DSP56K=m
 CONFIG_AMIGA_BUILTIN_SERIAL=y
 CONFIG_SERIAL_CONSOLE=y
@@ -324,42 +407,49 @@ CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 # CONFIG_EXT3_FS_XATTR is not set
+CONFIG_EXT4_FS=y
 CONFIG_REISERFS_FS=m
 CONFIG_JFS_FS=m
 CONFIG_XFS_FS=m
 CONFIG_OCFS2_FS=m
-# CONFIG_OCFS2_FS_STATS is not set
 # CONFIG_OCFS2_DEBUG_MASKLOG is not set
+CONFIG_FANOTIFY=y
 CONFIG_QUOTA_NETLINK_INTERFACE=y
 # CONFIG_PRINT_QUOTA_WARNING is not set
-CONFIG_AUTOFS_FS=m
 CONFIG_AUTOFS4_FS=m
 CONFIG_FUSE_FS=m
+CONFIG_CUSE=m
 CONFIG_ISO9660_FS=y
 CONFIG_JOLIET=y
 CONFIG_ZISOFS=y
 CONFIG_UDF_FS=m
-CONFIG_MSDOS_FS=y
+CONFIG_MSDOS_FS=m
 CONFIG_VFAT_FS=m
 CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
 CONFIG_AFFS_FS=m
-CONFIG_HFS_FS=y
-CONFIG_HFSPLUS_FS=y
+CONFIG_ECRYPT_FS=m
+CONFIG_ECRYPT_FS_MESSAGING=y
+CONFIG_HFS_FS=m
+CONFIG_HFSPLUS_FS=m
 CONFIG_CRAMFS=m
 CONFIG_SQUASHFS=m
-CONFIG_MINIX_FS=y
+CONFIG_SQUASHFS_LZO=y
+CONFIG_MINIX_FS=m
+CONFIG_OMFS_FS=m
 CONFIG_HPFS_FS=m
+CONFIG_QNX4FS_FS=m
+CONFIG_QNX6FS_FS=m
 CONFIG_SYSV_FS=m
 CONFIG_UFS_FS=m
 CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
 CONFIG_NFS_V4=y
+CONFIG_NFS_SWAP=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
 CONFIG_NFSD_V3=y
-CONFIG_SMB_FS=m
-CONFIG_SMB_NLS_DEFAULT=y
+CONFIG_CIFS=m
+# CONFIG_CIFS_DEBUG is not set
 CONFIG_CODA_FS=m
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_CODEPAGE_737=m
@@ -398,10 +488,23 @@ CONFIG_NLS_ISO8859_14=m
 CONFIG_NLS_ISO8859_15=m
 CONFIG_NLS_KOI8_R=m
 CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_MAC_ROMAN=m
+CONFIG_NLS_MAC_CELTIC=m
+CONFIG_NLS_MAC_CENTEURO=m
+CONFIG_NLS_MAC_CROATIAN=m
+CONFIG_NLS_MAC_CYRILLIC=m
+CONFIG_NLS_MAC_GAELIC=m
+CONFIG_NLS_MAC_GREEK=m
+CONFIG_NLS_MAC_ICELAND=m
+CONFIG_NLS_MAC_INUIT=m
+CONFIG_NLS_MAC_ROMANIAN=m
+CONFIG_NLS_MAC_TURKISH=m
 CONFIG_DLM=m
 CONFIG_MAGIC_SYSRQ=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_ASYNC_RAID6_TEST=m
+CONFIG_ENCRYPTED_KEYS=m
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_USER=m
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_CRYPTD=m
 CONFIG_CRYPTO_TEST=m
@@ -411,19 +514,16 @@ CONFIG_CRYPTO_CTS=m
 CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_XTS=m
-CONFIG_CRYPTO_HMAC=y
 CONFIG_CRYPTO_XCBC=m
-CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_VMAC=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_RMD128=m
 CONFIG_CRYPTO_RMD160=m
 CONFIG_CRYPTO_RMD256=m
 CONFIG_CRYPTO_RMD320=m
-CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_ANUBIS=m
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_CAMELLIA=m
@@ -439,6 +539,14 @@ CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_ZLIB=m
 CONFIG_CRYPTO_LZO=m
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_USER_API_HASH=m
+CONFIG_CRYPTO_USER_API_SKCIPHER=m
 # CONFIG_CRYPTO_HW is not set
-CONFIG_CRC16=y
 CONFIG_CRC_T10DIF=y
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
+CONFIG_XZ_DEC_TEST=m
index e2af46f..5586c65 100644 (file)
@@ -1,52 +1,73 @@
-CONFIG_EXPERIMENTAL=y
 CONFIG_LOCALVERSION="-mvme147"
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_FHANDLE=y
 CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_RELAY=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_LOG_BUF_SHIFT=16
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_AMIGA_PARTITION=y
+CONFIG_ATARI_PARTITION=y
+CONFIG_MAC_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+CONFIG_SUN_PARTITION=y
+# CONFIG_EFI_PARTITION is not set
+CONFIG_IOSCHED_DEADLINE=m
+CONFIG_M68030=y
 CONFIG_VME=y
 CONFIG_MVME147=y
-CONFIG_M68030=y
+# CONFIG_COMPACTION is not set
+CONFIG_CLEANCACHE=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_BINFMT_AOUT=m
 CONFIG_BINFMT_MISC=m
-CONFIG_PROC_HARDWARE=y
 CONFIG_NET=y
 CONFIG_PACKET=y
+CONFIG_PACKET_DIAG=m
 CONFIG_UNIX=y
+CONFIG_UNIX_DIAG=m
+CONFIG_XFRM_MIGRATE=y
 CONFIG_NET_KEY=y
-CONFIG_NET_KEY_MIGRATE=y
 CONFIG_INET=y
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=y
 CONFIG_IP_PNP_BOOTP=y
 CONFIG_IP_PNP_RARP=y
 CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE_DEMUX=m
 CONFIG_NET_IPGRE=m
 CONFIG_SYN_COOKIES=y
+CONFIG_NET_IPVTI=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
 CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
 CONFIG_INET_XFRM_MODE_BEET=m
+# CONFIG_INET_LRO is not set
 CONFIG_INET_DIAG=m
+CONFIG_INET_UDP_DIAG=m
 CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
-CONFIG_IPV6_ROUTE_INFO=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
-CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
-CONFIG_IPV6_TUNNEL=m
+CONFIG_IPV6_GRE=m
 CONFIG_NETFILTER=y
-CONFIG_NETFILTER_NETLINK_QUEUE=m
 CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CONNTRACK_ZONES=y
+# CONFIG_NF_CONNTRACK_PROCFS is not set
 # CONFIG_NF_CT_PROTO_DCCP is not set
 CONFIG_NF_CT_PROTO_UDPLITE=m
 CONFIG_NF_CONNTRACK_AMANDA=m
@@ -54,25 +75,37 @@ CONFIG_NF_CONNTRACK_FTP=m
 CONFIG_NF_CONNTRACK_H323=m
 CONFIG_NF_CONNTRACK_IRC=m
 CONFIG_NF_CONNTRACK_NETBIOS_NS=m
+CONFIG_NF_CONNTRACK_SNMP=m
 CONFIG_NF_CONNTRACK_PPTP=m
 CONFIG_NF_CONNTRACK_SANE=m
 CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NETFILTER_XT_SET=m
+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
 CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
 CONFIG_NETFILTER_XT_TARGET_DSCP=m
+CONFIG_NETFILTER_XT_TARGET_HMARK=m
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m
+CONFIG_NETFILTER_XT_TARGET_LOG=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_TEE=m
 CONFIG_NETFILTER_XT_TARGET_TRACE=m
 CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
+CONFIG_NETFILTER_XT_MATCH_BPF=m
 CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
 CONFIG_NETFILTER_XT_MATCH_COMMENT=m
 CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m
 CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
 CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
 CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m
 CONFIG_NETFILTER_XT_MATCH_DSCP=m
 CONFIG_NETFILTER_XT_MATCH_ESP=m
 CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
@@ -83,6 +116,8 @@ CONFIG_NETFILTER_XT_MATCH_LIMIT=m
 CONFIG_NETFILTER_XT_MATCH_MAC=m
 CONFIG_NETFILTER_XT_MATCH_MARK=m
 CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_NFACCT=m
+CONFIG_NETFILTER_XT_MATCH_OSF=m
 CONFIG_NETFILTER_XT_MATCH_OWNER=m
 CONFIG_NETFILTER_XT_MATCH_POLICY=m
 CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
@@ -96,22 +131,31 @@ CONFIG_NETFILTER_XT_MATCH_STRING=m
 CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
 CONFIG_NETFILTER_XT_MATCH_TIME=m
 CONFIG_NETFILTER_XT_MATCH_U32=m
+CONFIG_IP_SET=m
+CONFIG_IP_SET_BITMAP_IP=m
+CONFIG_IP_SET_BITMAP_IPMAC=m
+CONFIG_IP_SET_BITMAP_PORT=m
+CONFIG_IP_SET_HASH_IP=m
+CONFIG_IP_SET_HASH_IPPORT=m
+CONFIG_IP_SET_HASH_IPPORTIP=m
+CONFIG_IP_SET_HASH_IPPORTNET=m
+CONFIG_IP_SET_HASH_NET=m
+CONFIG_IP_SET_HASH_NETPORT=m
+CONFIG_IP_SET_HASH_NETIFACE=m
+CONFIG_IP_SET_LIST_SET=m
 CONFIG_NF_CONNTRACK_IPV4=m
-CONFIG_IP_NF_QUEUE=m
 CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_ADDRTYPE=m
 CONFIG_IP_NF_MATCH_AH=m
 CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_RPFILTER=m
 CONFIG_IP_NF_MATCH_TTL=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
-CONFIG_IP_NF_TARGET_LOG=m
 CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_NF_NAT=m
+CONFIG_NF_NAT_IPV4=m
 CONFIG_IP_NF_TARGET_MASQUERADE=m
 CONFIG_IP_NF_TARGET_NETMAP=m
 CONFIG_IP_NF_TARGET_REDIRECT=m
-CONFIG_NF_NAT_SNMP_BASIC=m
 CONFIG_IP_NF_MANGLE=m
 CONFIG_IP_NF_TARGET_CLUSTERIP=m
 CONFIG_IP_NF_TARGET_ECN=m
@@ -121,7 +165,6 @@ CONFIG_IP_NF_ARPTABLES=m
 CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
 CONFIG_NF_CONNTRACK_IPV6=m
-CONFIG_IP6_NF_QUEUE=m
 CONFIG_IP6_NF_IPTABLES=m
 CONFIG_IP6_NF_MATCH_AH=m
 CONFIG_IP6_NF_MATCH_EUI64=m
@@ -130,21 +173,34 @@ CONFIG_IP6_NF_MATCH_OPTS=m
 CONFIG_IP6_NF_MATCH_HL=m
 CONFIG_IP6_NF_MATCH_IPV6HEADER=m
 CONFIG_IP6_NF_MATCH_MH=m
+CONFIG_IP6_NF_MATCH_RPFILTER=m
 CONFIG_IP6_NF_MATCH_RT=m
 CONFIG_IP6_NF_TARGET_HL=m
-CONFIG_IP6_NF_TARGET_LOG=m
 CONFIG_IP6_NF_FILTER=m
 CONFIG_IP6_NF_TARGET_REJECT=m
 CONFIG_IP6_NF_MANGLE=m
 CONFIG_IP6_NF_RAW=m
+CONFIG_NF_NAT_IPV6=m
+CONFIG_IP6_NF_TARGET_MASQUERADE=m
+CONFIG_IP6_NF_TARGET_NPT=m
 CONFIG_IP_DCCP=m
 # CONFIG_IP_DCCP_CCID3 is not set
+CONFIG_SCTP_COOKIE_HMAC_SHA1=y
+CONFIG_RDS=m
+CONFIG_RDS_TCP=m
+CONFIG_L2TP=m
 CONFIG_ATALK=m
+CONFIG_BATMAN_ADV=m
+CONFIG_BATMAN_ADV_DAT=y
+# CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
 # CONFIG_FIRMWARE_IN_KERNEL is not set
+# CONFIG_FW_LOADER_USER_HELPER is not set
 CONFIG_CONNECTOR=m
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_DRBD=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_CDROM_PKTCDVD=m
@@ -159,103 +215,132 @@ CONFIG_BLK_DEV_SR=y
 CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
 CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_SAS_LIBSAS=m
-# CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set
-CONFIG_SCSI_SRP_ATTRS=m
-CONFIG_SCSI_SRP_TGT_ATTRS=y
+CONFIG_SCSI_SAS_ATTRS=m
 CONFIG_ISCSI_TCP=m
+CONFIG_ISCSI_BOOT_SYSFS=m
 CONFIG_MVME147_SCSI=y
 CONFIG_MD=y
-CONFIG_BLK_DEV_MD=m
 CONFIG_MD_LINEAR=m
 CONFIG_MD_RAID0=m
-CONFIG_MD_RAID1=m
-CONFIG_MD_RAID456=m
 CONFIG_BLK_DEV_DM=m
 CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_THIN_PROVISIONING=m
+CONFIG_DM_CACHE=m
 CONFIG_DM_MIRROR=m
+CONFIG_DM_RAID=m
 CONFIG_DM_ZERO=m
 CONFIG_DM_MULTIPATH=m
 CONFIG_DM_UEVENT=y
+CONFIG_TARGET_CORE=m
+CONFIG_TCM_IBLOCK=m
+CONFIG_TCM_FILEIO=m
+CONFIG_TCM_PSCSI=m
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=m
-CONFIG_MACVLAN=m
 CONFIG_EQUALIZER=m
+CONFIG_NET_TEAM=m
+CONFIG_NET_TEAM_MODE_BROADCAST=m
+CONFIG_NET_TEAM_MODE_ROUNDROBIN=m
+CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m
+CONFIG_NET_TEAM_MODE_LOADBALANCE=m
+CONFIG_VXLAN=m
+CONFIG_NETCONSOLE=m
+CONFIG_NETCONSOLE_DYNAMIC=y
 CONFIG_VETH=m
-CONFIG_NET_ETHERNET=y
 CONFIG_MVME147_NET=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
 CONFIG_PPP=m
-CONFIG_PPP_FILTER=y
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=m
 CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_FILTER=y
 CONFIG_PPP_MPPE=m
 CONFIG_PPPOE=m
+CONFIG_PPTP=m
+CONFIG_PPPOL2TP=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
 CONFIG_SLIP=m
 CONFIG_SLIP_COMPRESSED=y
 CONFIG_SLIP_SMART=y
 CONFIG_SLIP_MODE_SLIP6=y
-CONFIG_NETCONSOLE=m
-CONFIG_NETCONSOLE_DYNAMIC=y
-CONFIG_INPUT_FF_MEMLESS=m
+# CONFIG_WLAN is not set
+CONFIG_INPUT_EVDEV=m
 # CONFIG_KEYBOARD_ATKBD is not set
-CONFIG_MOUSE_PS2=m
-CONFIG_MOUSE_SERIAL=m
-CONFIG_SERIO=m
-# CONFIG_SERIO_SERPORT is not set
+# CONFIG_MOUSE_PS2 is not set
+# CONFIG_SERIO is not set
 CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_LEGACY_PTYS is not set
 # CONFIG_DEVKMEM is not set
 # CONFIG_HW_RANDOM is not set
-CONFIG_GEN_RTC=m
-CONFIG_GEN_RTC_X=y
+CONFIG_NTP_PPS=y
+CONFIG_PPS_CLIENT_LDISC=m
+CONFIG_PTP_1588_CLOCK=m
 # CONFIG_HWMON is not set
 CONFIG_HID=m
 CONFIG_HIDRAW=y
+CONFIG_UHID=m
+# CONFIG_HID_GENERIC is not set
 # CONFIG_USB_SUPPORT is not set
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_GENERIC=m
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_PROC_HARDWARE=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 # CONFIG_EXT3_FS_XATTR is not set
+CONFIG_EXT4_FS=y
 CONFIG_REISERFS_FS=m
 CONFIG_JFS_FS=m
 CONFIG_XFS_FS=m
 CONFIG_OCFS2_FS=m
-# CONFIG_OCFS2_FS_STATS is not set
 # CONFIG_OCFS2_DEBUG_MASKLOG is not set
+CONFIG_FANOTIFY=y
 CONFIG_QUOTA_NETLINK_INTERFACE=y
 # CONFIG_PRINT_QUOTA_WARNING is not set
-CONFIG_AUTOFS_FS=m
 CONFIG_AUTOFS4_FS=m
 CONFIG_FUSE_FS=m
+CONFIG_CUSE=m
 CONFIG_ISO9660_FS=y
 CONFIG_JOLIET=y
 CONFIG_ZISOFS=y
 CONFIG_UDF_FS=m
-CONFIG_MSDOS_FS=y
+CONFIG_MSDOS_FS=m
 CONFIG_VFAT_FS=m
 CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
 CONFIG_AFFS_FS=m
+CONFIG_ECRYPT_FS=m
+CONFIG_ECRYPT_FS_MESSAGING=y
 CONFIG_HFS_FS=m
 CONFIG_HFSPLUS_FS=m
 CONFIG_CRAMFS=m
 CONFIG_SQUASHFS=m
-CONFIG_MINIX_FS=y
+CONFIG_SQUASHFS_LZO=y
+CONFIG_MINIX_FS=m
+CONFIG_OMFS_FS=m
 CONFIG_HPFS_FS=m
+CONFIG_QNX4FS_FS=m
+CONFIG_QNX6FS_FS=m
 CONFIG_SYSV_FS=m
 CONFIG_UFS_FS=m
 CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
 CONFIG_NFS_V4=y
+CONFIG_NFS_SWAP=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
 CONFIG_NFSD_V3=y
-CONFIG_SMB_FS=m
-CONFIG_SMB_NLS_DEFAULT=y
+CONFIG_CIFS=m
+# CONFIG_CIFS_DEBUG is not set
 CONFIG_CODA_FS=m
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_CODEPAGE_737=m
@@ -294,10 +379,23 @@ CONFIG_NLS_ISO8859_14=m
 CONFIG_NLS_ISO8859_15=m
 CONFIG_NLS_KOI8_R=m
 CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_MAC_ROMAN=m
+CONFIG_NLS_MAC_CELTIC=m
+CONFIG_NLS_MAC_CENTEURO=m
+CONFIG_NLS_MAC_CROATIAN=m
+CONFIG_NLS_MAC_CYRILLIC=m
+CONFIG_NLS_MAC_GAELIC=m
+CONFIG_NLS_MAC_GREEK=m
+CONFIG_NLS_MAC_ICELAND=m
+CONFIG_NLS_MAC_INUIT=m
+CONFIG_NLS_MAC_ROMANIAN=m
+CONFIG_NLS_MAC_TURKISH=m
 CONFIG_DLM=m
 CONFIG_MAGIC_SYSRQ=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_ASYNC_RAID6_TEST=m
+CONFIG_ENCRYPTED_KEYS=m
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_USER=m
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_CRYPTD=m
 CONFIG_CRYPTO_TEST=m
@@ -307,19 +405,16 @@ CONFIG_CRYPTO_CTS=m
 CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_XTS=m
-CONFIG_CRYPTO_HMAC=y
 CONFIG_CRYPTO_XCBC=m
-CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_VMAC=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_RMD128=m
 CONFIG_CRYPTO_RMD160=m
 CONFIG_CRYPTO_RMD256=m
 CONFIG_CRYPTO_RMD320=m
-CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_ANUBIS=m
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_CAMELLIA=m
@@ -335,6 +430,14 @@ CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_ZLIB=m
 CONFIG_CRYPTO_LZO=m
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_USER_API_HASH=m
+CONFIG_CRYPTO_USER_API_SKCIPHER=m
 # CONFIG_CRYPTO_HW is not set
-CONFIG_CRC16=m
 CONFIG_CRC_T10DIF=y
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
+CONFIG_XZ_DEC_TEST=m
index 7c9402b..e5e8262 100644 (file)
@@ -1,53 +1,74 @@
-CONFIG_EXPERIMENTAL=y
 CONFIG_LOCALVERSION="-mvme16x"
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_FHANDLE=y
 CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_RELAY=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_LOG_BUF_SHIFT=16
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
-CONFIG_VME=y
-CONFIG_MVME16x=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_AMIGA_PARTITION=y
+CONFIG_ATARI_PARTITION=y
+CONFIG_MAC_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+CONFIG_SUN_PARTITION=y
+# CONFIG_EFI_PARTITION is not set
+CONFIG_IOSCHED_DEADLINE=m
 CONFIG_M68040=y
 CONFIG_M68060=y
+CONFIG_VME=y
+CONFIG_MVME16x=y
+# CONFIG_COMPACTION is not set
+CONFIG_CLEANCACHE=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_BINFMT_AOUT=m
 CONFIG_BINFMT_MISC=m
-CONFIG_PROC_HARDWARE=y
 CONFIG_NET=y
 CONFIG_PACKET=y
+CONFIG_PACKET_DIAG=m
 CONFIG_UNIX=y
+CONFIG_UNIX_DIAG=m
+CONFIG_XFRM_MIGRATE=y
 CONFIG_NET_KEY=y
-CONFIG_NET_KEY_MIGRATE=y
 CONFIG_INET=y
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=y
 CONFIG_IP_PNP_BOOTP=y
 CONFIG_IP_PNP_RARP=y
 CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE_DEMUX=m
 CONFIG_NET_IPGRE=m
 CONFIG_SYN_COOKIES=y
+CONFIG_NET_IPVTI=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
 CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
 CONFIG_INET_XFRM_MODE_BEET=m
+# CONFIG_INET_LRO is not set
 CONFIG_INET_DIAG=m
+CONFIG_INET_UDP_DIAG=m
 CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
-CONFIG_IPV6_ROUTE_INFO=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
-CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
-CONFIG_IPV6_TUNNEL=m
+CONFIG_IPV6_GRE=m
 CONFIG_NETFILTER=y
-CONFIG_NETFILTER_NETLINK_QUEUE=m
 CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CONNTRACK_ZONES=y
+# CONFIG_NF_CONNTRACK_PROCFS is not set
 # CONFIG_NF_CT_PROTO_DCCP is not set
 CONFIG_NF_CT_PROTO_UDPLITE=m
 CONFIG_NF_CONNTRACK_AMANDA=m
@@ -55,25 +76,37 @@ CONFIG_NF_CONNTRACK_FTP=m
 CONFIG_NF_CONNTRACK_H323=m
 CONFIG_NF_CONNTRACK_IRC=m
 CONFIG_NF_CONNTRACK_NETBIOS_NS=m
+CONFIG_NF_CONNTRACK_SNMP=m
 CONFIG_NF_CONNTRACK_PPTP=m
 CONFIG_NF_CONNTRACK_SANE=m
 CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NETFILTER_XT_SET=m
+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
 CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
 CONFIG_NETFILTER_XT_TARGET_DSCP=m
+CONFIG_NETFILTER_XT_TARGET_HMARK=m
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m
+CONFIG_NETFILTER_XT_TARGET_LOG=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_TEE=m
 CONFIG_NETFILTER_XT_TARGET_TRACE=m
 CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
+CONFIG_NETFILTER_XT_MATCH_BPF=m
 CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
 CONFIG_NETFILTER_XT_MATCH_COMMENT=m
 CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m
 CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
 CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
 CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m
 CONFIG_NETFILTER_XT_MATCH_DSCP=m
 CONFIG_NETFILTER_XT_MATCH_ESP=m
 CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
@@ -84,6 +117,8 @@ CONFIG_NETFILTER_XT_MATCH_LIMIT=m
 CONFIG_NETFILTER_XT_MATCH_MAC=m
 CONFIG_NETFILTER_XT_MATCH_MARK=m
 CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_NFACCT=m
+CONFIG_NETFILTER_XT_MATCH_OSF=m
 CONFIG_NETFILTER_XT_MATCH_OWNER=m
 CONFIG_NETFILTER_XT_MATCH_POLICY=m
 CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
@@ -97,22 +132,31 @@ CONFIG_NETFILTER_XT_MATCH_STRING=m
 CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
 CONFIG_NETFILTER_XT_MATCH_TIME=m
 CONFIG_NETFILTER_XT_MATCH_U32=m
+CONFIG_IP_SET=m
+CONFIG_IP_SET_BITMAP_IP=m
+CONFIG_IP_SET_BITMAP_IPMAC=m
+CONFIG_IP_SET_BITMAP_PORT=m
+CONFIG_IP_SET_HASH_IP=m
+CONFIG_IP_SET_HASH_IPPORT=m
+CONFIG_IP_SET_HASH_IPPORTIP=m
+CONFIG_IP_SET_HASH_IPPORTNET=m
+CONFIG_IP_SET_HASH_NET=m
+CONFIG_IP_SET_HASH_NETPORT=m
+CONFIG_IP_SET_HASH_NETIFACE=m
+CONFIG_IP_SET_LIST_SET=m
 CONFIG_NF_CONNTRACK_IPV4=m
-CONFIG_IP_NF_QUEUE=m
 CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_ADDRTYPE=m
 CONFIG_IP_NF_MATCH_AH=m
 CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_RPFILTER=m
 CONFIG_IP_NF_MATCH_TTL=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
-CONFIG_IP_NF_TARGET_LOG=m
 CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_NF_NAT=m
+CONFIG_NF_NAT_IPV4=m
 CONFIG_IP_NF_TARGET_MASQUERADE=m
 CONFIG_IP_NF_TARGET_NETMAP=m
 CONFIG_IP_NF_TARGET_REDIRECT=m
-CONFIG_NF_NAT_SNMP_BASIC=m
 CONFIG_IP_NF_MANGLE=m
 CONFIG_IP_NF_TARGET_CLUSTERIP=m
 CONFIG_IP_NF_TARGET_ECN=m
@@ -122,7 +166,6 @@ CONFIG_IP_NF_ARPTABLES=m
 CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
 CONFIG_NF_CONNTRACK_IPV6=m
-CONFIG_IP6_NF_QUEUE=m
 CONFIG_IP6_NF_IPTABLES=m
 CONFIG_IP6_NF_MATCH_AH=m
 CONFIG_IP6_NF_MATCH_EUI64=m
@@ -131,21 +174,34 @@ CONFIG_IP6_NF_MATCH_OPTS=m
 CONFIG_IP6_NF_MATCH_HL=m
 CONFIG_IP6_NF_MATCH_IPV6HEADER=m
 CONFIG_IP6_NF_MATCH_MH=m
+CONFIG_IP6_NF_MATCH_RPFILTER=m
 CONFIG_IP6_NF_MATCH_RT=m
 CONFIG_IP6_NF_TARGET_HL=m
-CONFIG_IP6_NF_TARGET_LOG=m
 CONFIG_IP6_NF_FILTER=m
 CONFIG_IP6_NF_TARGET_REJECT=m
 CONFIG_IP6_NF_MANGLE=m
 CONFIG_IP6_NF_RAW=m
+CONFIG_NF_NAT_IPV6=m
+CONFIG_IP6_NF_TARGET_MASQUERADE=m
+CONFIG_IP6_NF_TARGET_NPT=m
 CONFIG_IP_DCCP=m
 # CONFIG_IP_DCCP_CCID3 is not set
+CONFIG_SCTP_COOKIE_HMAC_SHA1=y
+CONFIG_RDS=m
+CONFIG_RDS_TCP=m
+CONFIG_L2TP=m
 CONFIG_ATALK=m
+CONFIG_BATMAN_ADV=m
+CONFIG_BATMAN_ADV_DAT=y
+# CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
 # CONFIG_FIRMWARE_IN_KERNEL is not set
+# CONFIG_FW_LOADER_USER_HELPER is not set
 CONFIG_CONNECTOR=m
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_DRBD=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_CDROM_PKTCDVD=m
@@ -160,103 +216,131 @@ CONFIG_BLK_DEV_SR=y
 CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
 CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_SAS_LIBSAS=m
-# CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set
-CONFIG_SCSI_SRP_ATTRS=m
-CONFIG_SCSI_SRP_TGT_ATTRS=y
+CONFIG_SCSI_SAS_ATTRS=m
 CONFIG_ISCSI_TCP=m
+CONFIG_ISCSI_BOOT_SYSFS=m
 CONFIG_MVME16x_SCSI=y
 CONFIG_MD=y
-CONFIG_BLK_DEV_MD=m
 CONFIG_MD_LINEAR=m
 CONFIG_MD_RAID0=m
-CONFIG_MD_RAID1=m
-CONFIG_MD_RAID456=m
 CONFIG_BLK_DEV_DM=m
 CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_THIN_PROVISIONING=m
+CONFIG_DM_CACHE=m
 CONFIG_DM_MIRROR=m
+CONFIG_DM_RAID=m
 CONFIG_DM_ZERO=m
 CONFIG_DM_MULTIPATH=m
 CONFIG_DM_UEVENT=y
+CONFIG_TARGET_CORE=m
+CONFIG_TCM_IBLOCK=m
+CONFIG_TCM_FILEIO=m
+CONFIG_TCM_PSCSI=m
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=m
-CONFIG_MACVLAN=m
 CONFIG_EQUALIZER=m
+CONFIG_NET_TEAM=m
+CONFIG_NET_TEAM_MODE_BROADCAST=m
+CONFIG_NET_TEAM_MODE_ROUNDROBIN=m
+CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m
+CONFIG_NET_TEAM_MODE_LOADBALANCE=m
+CONFIG_VXLAN=m
+CONFIG_NETCONSOLE=m
+CONFIG_NETCONSOLE_DYNAMIC=y
 CONFIG_VETH=m
-CONFIG_NET_ETHERNET=y
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
 CONFIG_MVME16x_NET=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
 CONFIG_PPP=m
-CONFIG_PPP_FILTER=y
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=m
 CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_FILTER=y
 CONFIG_PPP_MPPE=m
 CONFIG_PPPOE=m
+CONFIG_PPTP=m
+CONFIG_PPPOL2TP=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
 CONFIG_SLIP=m
 CONFIG_SLIP_COMPRESSED=y
 CONFIG_SLIP_SMART=y
 CONFIG_SLIP_MODE_SLIP6=y
-CONFIG_NETCONSOLE=m
-CONFIG_NETCONSOLE_DYNAMIC=y
-CONFIG_INPUT_FF_MEMLESS=m
+# CONFIG_WLAN is not set
+CONFIG_INPUT_EVDEV=m
 # CONFIG_KEYBOARD_ATKBD is not set
-CONFIG_MOUSE_PS2=m
-CONFIG_MOUSE_SERIAL=m
-CONFIG_SERIO=m
-# CONFIG_SERIO_SERPORT is not set
+# CONFIG_MOUSE_PS2 is not set
+# CONFIG_SERIO is not set
 CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_LEGACY_PTYS is not set
 # CONFIG_DEVKMEM is not set
 # CONFIG_HW_RANDOM is not set
-CONFIG_GEN_RTC=m
-CONFIG_GEN_RTC_X=y
+CONFIG_NTP_PPS=y
+CONFIG_PPS_CLIENT_LDISC=m
+CONFIG_PTP_1588_CLOCK=m
 # CONFIG_HWMON is not set
 CONFIG_HID=m
 CONFIG_HIDRAW=y
+CONFIG_UHID=m
+# CONFIG_HID_GENERIC is not set
 # CONFIG_USB_SUPPORT is not set
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_GENERIC=m
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_PROC_HARDWARE=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 # CONFIG_EXT3_FS_XATTR is not set
+CONFIG_EXT4_FS=y
 CONFIG_REISERFS_FS=m
 CONFIG_JFS_FS=m
 CONFIG_XFS_FS=m
 CONFIG_OCFS2_FS=m
-# CONFIG_OCFS2_FS_STATS is not set
 # CONFIG_OCFS2_DEBUG_MASKLOG is not set
+CONFIG_FANOTIFY=y
 CONFIG_QUOTA_NETLINK_INTERFACE=y
 # CONFIG_PRINT_QUOTA_WARNING is not set
-CONFIG_AUTOFS_FS=m
 CONFIG_AUTOFS4_FS=m
 CONFIG_FUSE_FS=m
+CONFIG_CUSE=m
 CONFIG_ISO9660_FS=y
 CONFIG_JOLIET=y
 CONFIG_ZISOFS=y
 CONFIG_UDF_FS=m
-CONFIG_MSDOS_FS=y
+CONFIG_MSDOS_FS=m
 CONFIG_VFAT_FS=m
 CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
 CONFIG_AFFS_FS=m
+CONFIG_ECRYPT_FS=m
+CONFIG_ECRYPT_FS_MESSAGING=y
 CONFIG_HFS_FS=m
 CONFIG_HFSPLUS_FS=m
 CONFIG_CRAMFS=m
 CONFIG_SQUASHFS=m
-CONFIG_MINIX_FS=y
+CONFIG_SQUASHFS_LZO=y
+CONFIG_MINIX_FS=m
+CONFIG_OMFS_FS=m
 CONFIG_HPFS_FS=m
+CONFIG_QNX4FS_FS=m
+CONFIG_QNX6FS_FS=m
 CONFIG_SYSV_FS=m
 CONFIG_UFS_FS=m
 CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
 CONFIG_NFS_V4=y
+CONFIG_NFS_SWAP=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
 CONFIG_NFSD_V3=y
-CONFIG_SMB_FS=m
-CONFIG_SMB_NLS_DEFAULT=y
+CONFIG_CIFS=m
+# CONFIG_CIFS_DEBUG is not set
 CONFIG_CODA_FS=m
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_CODEPAGE_737=m
@@ -295,10 +379,23 @@ CONFIG_NLS_ISO8859_14=m
 CONFIG_NLS_ISO8859_15=m
 CONFIG_NLS_KOI8_R=m
 CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_MAC_ROMAN=m
+CONFIG_NLS_MAC_CELTIC=m
+CONFIG_NLS_MAC_CENTEURO=m
+CONFIG_NLS_MAC_CROATIAN=m
+CONFIG_NLS_MAC_CYRILLIC=m
+CONFIG_NLS_MAC_GAELIC=m
+CONFIG_NLS_MAC_GREEK=m
+CONFIG_NLS_MAC_ICELAND=m
+CONFIG_NLS_MAC_INUIT=m
+CONFIG_NLS_MAC_ROMANIAN=m
+CONFIG_NLS_MAC_TURKISH=m
 CONFIG_DLM=m
 CONFIG_MAGIC_SYSRQ=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_ASYNC_RAID6_TEST=m
+CONFIG_ENCRYPTED_KEYS=m
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_USER=m
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_CRYPTD=m
 CONFIG_CRYPTO_TEST=m
@@ -308,19 +405,16 @@ CONFIG_CRYPTO_CTS=m
 CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_XTS=m
-CONFIG_CRYPTO_HMAC=y
 CONFIG_CRYPTO_XCBC=m
-CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_VMAC=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_RMD128=m
 CONFIG_CRYPTO_RMD160=m
 CONFIG_CRYPTO_RMD256=m
 CONFIG_CRYPTO_RMD320=m
-CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_ANUBIS=m
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_CAMELLIA=m
@@ -336,6 +430,14 @@ CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_ZLIB=m
 CONFIG_CRYPTO_LZO=m
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_USER_API_HASH=m
+CONFIG_CRYPTO_USER_API_SKCIPHER=m
 # CONFIG_CRYPTO_HW is not set
-CONFIG_CRC16=m
 CONFIG_CRC_T10DIF=y
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
+CONFIG_XZ_DEC_TEST=m
index 19d23db..8982370 100644 (file)
@@ -1,49 +1,74 @@
-CONFIG_EXPERIMENTAL=y
 CONFIG_LOCALVERSION="-q40"
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_FHANDLE=y
 CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_RELAY=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_LOG_BUF_SHIFT=16
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
-CONFIG_Q40=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_AMIGA_PARTITION=y
+CONFIG_ATARI_PARTITION=y
+CONFIG_MAC_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+CONFIG_SUN_PARTITION=y
+# CONFIG_EFI_PARTITION is not set
+CONFIG_SYSV68_PARTITION=y
+CONFIG_IOSCHED_DEADLINE=m
 CONFIG_M68040=y
 CONFIG_M68060=y
+CONFIG_Q40=y
+# CONFIG_COMPACTION is not set
+CONFIG_CLEANCACHE=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_BINFMT_AOUT=m
 CONFIG_BINFMT_MISC=m
-CONFIG_HEARTBEAT=y
-CONFIG_PROC_HARDWARE=y
 CONFIG_NET=y
 CONFIG_PACKET=y
+CONFIG_PACKET_DIAG=m
 CONFIG_UNIX=y
+CONFIG_UNIX_DIAG=m
+CONFIG_XFRM_MIGRATE=y
 CONFIG_NET_KEY=y
-CONFIG_NET_KEY_MIGRATE=y
 CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
 CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE_DEMUX=m
 CONFIG_NET_IPGRE=m
 CONFIG_SYN_COOKIES=y
+CONFIG_NET_IPVTI=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
 CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
 CONFIG_INET_XFRM_MODE_BEET=m
+# CONFIG_INET_LRO is not set
 CONFIG_INET_DIAG=m
+CONFIG_INET_UDP_DIAG=m
 CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
-CONFIG_IPV6_ROUTE_INFO=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
-CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
-CONFIG_IPV6_TUNNEL=m
+CONFIG_IPV6_GRE=m
 CONFIG_NETFILTER=y
-CONFIG_NETFILTER_NETLINK_QUEUE=m
 CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CONNTRACK_ZONES=y
+# CONFIG_NF_CONNTRACK_PROCFS is not set
 # CONFIG_NF_CT_PROTO_DCCP is not set
 CONFIG_NF_CT_PROTO_UDPLITE=m
 CONFIG_NF_CONNTRACK_AMANDA=m
@@ -51,25 +76,37 @@ CONFIG_NF_CONNTRACK_FTP=m
 CONFIG_NF_CONNTRACK_H323=m
 CONFIG_NF_CONNTRACK_IRC=m
 CONFIG_NF_CONNTRACK_NETBIOS_NS=m
+CONFIG_NF_CONNTRACK_SNMP=m
 CONFIG_NF_CONNTRACK_PPTP=m
 CONFIG_NF_CONNTRACK_SANE=m
 CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NETFILTER_XT_SET=m
+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
 CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
 CONFIG_NETFILTER_XT_TARGET_DSCP=m
+CONFIG_NETFILTER_XT_TARGET_HMARK=m
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m
+CONFIG_NETFILTER_XT_TARGET_LOG=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_TEE=m
 CONFIG_NETFILTER_XT_TARGET_TRACE=m
 CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
+CONFIG_NETFILTER_XT_MATCH_BPF=m
 CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
 CONFIG_NETFILTER_XT_MATCH_COMMENT=m
 CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m
 CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
 CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
 CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m
 CONFIG_NETFILTER_XT_MATCH_DSCP=m
 CONFIG_NETFILTER_XT_MATCH_ESP=m
 CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
@@ -80,6 +117,8 @@ CONFIG_NETFILTER_XT_MATCH_LIMIT=m
 CONFIG_NETFILTER_XT_MATCH_MAC=m
 CONFIG_NETFILTER_XT_MATCH_MARK=m
 CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_NFACCT=m
+CONFIG_NETFILTER_XT_MATCH_OSF=m
 CONFIG_NETFILTER_XT_MATCH_OWNER=m
 CONFIG_NETFILTER_XT_MATCH_POLICY=m
 CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
@@ -93,22 +132,31 @@ CONFIG_NETFILTER_XT_MATCH_STRING=m
 CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
 CONFIG_NETFILTER_XT_MATCH_TIME=m
 CONFIG_NETFILTER_XT_MATCH_U32=m
+CONFIG_IP_SET=m
+CONFIG_IP_SET_BITMAP_IP=m
+CONFIG_IP_SET_BITMAP_IPMAC=m
+CONFIG_IP_SET_BITMAP_PORT=m
+CONFIG_IP_SET_HASH_IP=m
+CONFIG_IP_SET_HASH_IPPORT=m
+CONFIG_IP_SET_HASH_IPPORTIP=m
+CONFIG_IP_SET_HASH_IPPORTNET=m
+CONFIG_IP_SET_HASH_NET=m
+CONFIG_IP_SET_HASH_NETPORT=m
+CONFIG_IP_SET_HASH_NETIFACE=m
+CONFIG_IP_SET_LIST_SET=m
 CONFIG_NF_CONNTRACK_IPV4=m
-CONFIG_IP_NF_QUEUE=m
 CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_ADDRTYPE=m
 CONFIG_IP_NF_MATCH_AH=m
 CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_RPFILTER=m
 CONFIG_IP_NF_MATCH_TTL=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
-CONFIG_IP_NF_TARGET_LOG=m
 CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_NF_NAT=m
+CONFIG_NF_NAT_IPV4=m
 CONFIG_IP_NF_TARGET_MASQUERADE=m
 CONFIG_IP_NF_TARGET_NETMAP=m
 CONFIG_IP_NF_TARGET_REDIRECT=m
-CONFIG_NF_NAT_SNMP_BASIC=m
 CONFIG_IP_NF_MANGLE=m
 CONFIG_IP_NF_TARGET_CLUSTERIP=m
 CONFIG_IP_NF_TARGET_ECN=m
@@ -118,7 +166,6 @@ CONFIG_IP_NF_ARPTABLES=m
 CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
 CONFIG_NF_CONNTRACK_IPV6=m
-CONFIG_IP6_NF_QUEUE=m
 CONFIG_IP6_NF_IPTABLES=m
 CONFIG_IP6_NF_MATCH_AH=m
 CONFIG_IP6_NF_MATCH_EUI64=m
@@ -127,26 +174,40 @@ CONFIG_IP6_NF_MATCH_OPTS=m
 CONFIG_IP6_NF_MATCH_HL=m
 CONFIG_IP6_NF_MATCH_IPV6HEADER=m
 CONFIG_IP6_NF_MATCH_MH=m
+CONFIG_IP6_NF_MATCH_RPFILTER=m
 CONFIG_IP6_NF_MATCH_RT=m
 CONFIG_IP6_NF_TARGET_HL=m
-CONFIG_IP6_NF_TARGET_LOG=m
 CONFIG_IP6_NF_FILTER=m
 CONFIG_IP6_NF_TARGET_REJECT=m
 CONFIG_IP6_NF_MANGLE=m
 CONFIG_IP6_NF_RAW=m
+CONFIG_NF_NAT_IPV6=m
+CONFIG_IP6_NF_TARGET_MASQUERADE=m
+CONFIG_IP6_NF_TARGET_NPT=m
 CONFIG_IP_DCCP=m
 # CONFIG_IP_DCCP_CCID3 is not set
+CONFIG_SCTP_COOKIE_HMAC_SHA1=y
+CONFIG_RDS=m
+CONFIG_RDS_TCP=m
+CONFIG_L2TP=m
 CONFIG_ATALK=m
+CONFIG_BATMAN_ADV=m
+CONFIG_BATMAN_ADV_DAT=y
+# CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
 # CONFIG_FIRMWARE_IN_KERNEL is not set
+# CONFIG_FW_LOADER_USER_HELPER is not set
 CONFIG_CONNECTOR=m
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_DRBD=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_ATA_OVER_ETH=m
 CONFIG_IDE=y
+CONFIG_IDE_GD_ATAPI=y
 CONFIG_BLK_DEV_IDECD=y
 CONFIG_BLK_DEV_Q40IDE=y
 CONFIG_RAID_ATTRS=m
@@ -159,61 +220,82 @@ CONFIG_BLK_DEV_SR=y
 CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
 CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_SAS_LIBSAS=m
-# CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set
-CONFIG_SCSI_SRP_ATTRS=m
-CONFIG_SCSI_SRP_TGT_ATTRS=y
+CONFIG_SCSI_SAS_ATTRS=m
 CONFIG_ISCSI_TCP=m
+CONFIG_ISCSI_BOOT_SYSFS=m
 CONFIG_MD=y
-CONFIG_BLK_DEV_MD=m
 CONFIG_MD_LINEAR=m
 CONFIG_MD_RAID0=m
-CONFIG_MD_RAID1=m
-CONFIG_MD_RAID456=m
 CONFIG_BLK_DEV_DM=m
 CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_THIN_PROVISIONING=m
+CONFIG_DM_CACHE=m
 CONFIG_DM_MIRROR=m
+CONFIG_DM_RAID=m
 CONFIG_DM_ZERO=m
 CONFIG_DM_MULTIPATH=m
 CONFIG_DM_UEVENT=y
+CONFIG_TARGET_CORE=m
+CONFIG_TCM_IBLOCK=m
+CONFIG_TCM_FILEIO=m
+CONFIG_TCM_PSCSI=m
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=m
-CONFIG_MACVLAN=m
 CONFIG_EQUALIZER=m
+CONFIG_NET_TEAM=m
+CONFIG_NET_TEAM_MODE_BROADCAST=m
+CONFIG_NET_TEAM_MODE_ROUNDROBIN=m
+CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m
+CONFIG_NET_TEAM_MODE_LOADBALANCE=m
+CONFIG_VXLAN=m
+CONFIG_NETCONSOLE=m
+CONFIG_NETCONSOLE_DYNAMIC=y
 CONFIG_VETH=m
-CONFIG_NET_ETHERNET=y
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_NET_VENDOR_AMD is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_NET_VENDOR_FUJITSU is not set
+# CONFIG_NET_VENDOR_HP is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
 CONFIG_NE2000=m
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
 CONFIG_PPP=m
-CONFIG_PPP_FILTER=y
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=m
 CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_FILTER=y
 CONFIG_PPP_MPPE=m
 CONFIG_PPPOE=m
+CONFIG_PPTP=m
+CONFIG_PPPOL2TP=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
 CONFIG_SLIP=m
 CONFIG_SLIP_COMPRESSED=y
 CONFIG_SLIP_SMART=y
 CONFIG_SLIP_MODE_SLIP6=y
-CONFIG_NETCONSOLE=m
-CONFIG_NETCONSOLE_DYNAMIC=y
-CONFIG_INPUT_FF_MEMLESS=m
+# CONFIG_WLAN is not set
+CONFIG_INPUT_EVDEV=m
 # CONFIG_KEYBOARD_ATKBD is not set
-CONFIG_MOUSE_PS2=m
+# CONFIG_MOUSE_PS2 is not set
 CONFIG_MOUSE_SERIAL=m
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_M68K_BEEP=m
-CONFIG_SERIO=m
-# CONFIG_SERIO_SERPORT is not set
-CONFIG_SERIO_Q40KBD=m
+CONFIG_SERIO_Q40KBD=y
 CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_LEGACY_PTYS is not set
 # CONFIG_DEVKMEM is not set
 # CONFIG_HW_RANDOM is not set
-CONFIG_GEN_RTC=m
-CONFIG_GEN_RTC_X=y
+CONFIG_NTP_PPS=y
+CONFIG_PPS_CLIENT_LDISC=m
+CONFIG_PTP_1588_CLOCK=m
 # CONFIG_HWMON is not set
 CONFIG_FB=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
@@ -222,46 +304,61 @@ CONFIG_SOUND=m
 CONFIG_DMASOUND_Q40=m
 CONFIG_HID=m
 CONFIG_HIDRAW=y
+CONFIG_UHID=m
+# CONFIG_HID_GENERIC is not set
 # CONFIG_USB_SUPPORT is not set
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_GENERIC=m
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_HEARTBEAT=y
+CONFIG_PROC_HARDWARE=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 # CONFIG_EXT3_FS_XATTR is not set
+CONFIG_EXT4_FS=y
 CONFIG_REISERFS_FS=m
 CONFIG_JFS_FS=m
 CONFIG_XFS_FS=m
 CONFIG_OCFS2_FS=m
-# CONFIG_OCFS2_FS_STATS is not set
 # CONFIG_OCFS2_DEBUG_MASKLOG is not set
+CONFIG_FANOTIFY=y
 CONFIG_QUOTA_NETLINK_INTERFACE=y
 # CONFIG_PRINT_QUOTA_WARNING is not set
-CONFIG_AUTOFS_FS=m
 CONFIG_AUTOFS4_FS=m
 CONFIG_FUSE_FS=m
+CONFIG_CUSE=m
 CONFIG_ISO9660_FS=y
 CONFIG_JOLIET=y
 CONFIG_ZISOFS=y
 CONFIG_UDF_FS=m
-CONFIG_MSDOS_FS=y
+CONFIG_MSDOS_FS=m
 CONFIG_VFAT_FS=m
 CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
 CONFIG_AFFS_FS=m
+CONFIG_ECRYPT_FS=m
+CONFIG_ECRYPT_FS_MESSAGING=y
 CONFIG_HFS_FS=m
 CONFIG_HFSPLUS_FS=m
 CONFIG_CRAMFS=m
 CONFIG_SQUASHFS=m
-CONFIG_MINIX_FS=y
+CONFIG_SQUASHFS_LZO=y
+CONFIG_MINIX_FS=m
+CONFIG_OMFS_FS=m
 CONFIG_HPFS_FS=m
+CONFIG_QNX4FS_FS=m
+CONFIG_QNX6FS_FS=m
 CONFIG_SYSV_FS=m
 CONFIG_UFS_FS=m
 CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
 CONFIG_NFS_V4=y
+CONFIG_NFS_SWAP=y
+CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
 CONFIG_NFSD_V3=y
-CONFIG_SMB_FS=m
-CONFIG_SMB_NLS_DEFAULT=y
+CONFIG_CIFS=m
+# CONFIG_CIFS_DEBUG is not set
 CONFIG_CODA_FS=m
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_CODEPAGE_737=m
@@ -300,10 +397,23 @@ CONFIG_NLS_ISO8859_14=m
 CONFIG_NLS_ISO8859_15=m
 CONFIG_NLS_KOI8_R=m
 CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_MAC_ROMAN=m
+CONFIG_NLS_MAC_CELTIC=m
+CONFIG_NLS_MAC_CENTEURO=m
+CONFIG_NLS_MAC_CROATIAN=m
+CONFIG_NLS_MAC_CYRILLIC=m
+CONFIG_NLS_MAC_GAELIC=m
+CONFIG_NLS_MAC_GREEK=m
+CONFIG_NLS_MAC_ICELAND=m
+CONFIG_NLS_MAC_INUIT=m
+CONFIG_NLS_MAC_ROMANIAN=m
+CONFIG_NLS_MAC_TURKISH=m
 CONFIG_DLM=m
 CONFIG_MAGIC_SYSRQ=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_ASYNC_RAID6_TEST=m
+CONFIG_ENCRYPTED_KEYS=m
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_USER=m
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_CRYPTD=m
 CONFIG_CRYPTO_TEST=m
@@ -313,19 +423,16 @@ CONFIG_CRYPTO_CTS=m
 CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_XTS=m
-CONFIG_CRYPTO_HMAC=y
 CONFIG_CRYPTO_XCBC=m
-CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_VMAC=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_RMD128=m
 CONFIG_CRYPTO_RMD160=m
 CONFIG_CRYPTO_RMD256=m
 CONFIG_CRYPTO_RMD320=m
-CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_ANUBIS=m
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_CAMELLIA=m
@@ -341,6 +448,14 @@ CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_ZLIB=m
 CONFIG_CRYPTO_LZO=m
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_USER_API_HASH=m
+CONFIG_CRYPTO_USER_API_SKCIPHER=m
 # CONFIG_CRYPTO_HW is not set
-CONFIG_CRC16=m
 CONFIG_CRC_T10DIF=y
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
+CONFIG_XZ_DEC_TEST=m
index ca6c0b4..54674d6 100644 (file)
@@ -1,50 +1,71 @@
-CONFIG_EXPERIMENTAL=y
 CONFIG_LOCALVERSION="-sun3"
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_FHANDLE=y
 CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_RELAY=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_LOG_BUF_SHIFT=16
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_AMIGA_PARTITION=y
+CONFIG_ATARI_PARTITION=y
+CONFIG_MAC_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+# CONFIG_EFI_PARTITION is not set
+CONFIG_SYSV68_PARTITION=y
+CONFIG_IOSCHED_DEADLINE=m
 CONFIG_SUN3=y
+# CONFIG_COMPACTION is not set
+CONFIG_CLEANCACHE=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_BINFMT_AOUT=m
 CONFIG_BINFMT_MISC=m
-CONFIG_PROC_HARDWARE=y
 CONFIG_NET=y
 CONFIG_PACKET=y
+CONFIG_PACKET_DIAG=m
 CONFIG_UNIX=y
+CONFIG_UNIX_DIAG=m
+CONFIG_XFRM_MIGRATE=y
 CONFIG_NET_KEY=y
-CONFIG_NET_KEY_MIGRATE=y
 CONFIG_INET=y
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=y
 CONFIG_IP_PNP_BOOTP=y
 CONFIG_IP_PNP_RARP=y
 CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE_DEMUX=m
 CONFIG_NET_IPGRE=m
 CONFIG_SYN_COOKIES=y
+CONFIG_NET_IPVTI=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
 CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
 CONFIG_INET_XFRM_MODE_BEET=m
+# CONFIG_INET_LRO is not set
 CONFIG_INET_DIAG=m
+CONFIG_INET_UDP_DIAG=m
 CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
-CONFIG_IPV6_ROUTE_INFO=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
-CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
-CONFIG_IPV6_TUNNEL=m
+CONFIG_IPV6_GRE=m
 CONFIG_NETFILTER=y
-CONFIG_NETFILTER_NETLINK_QUEUE=m
 CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CONNTRACK_ZONES=y
+# CONFIG_NF_CONNTRACK_PROCFS is not set
 # CONFIG_NF_CT_PROTO_DCCP is not set
 CONFIG_NF_CT_PROTO_UDPLITE=m
 CONFIG_NF_CONNTRACK_AMANDA=m
@@ -52,25 +73,37 @@ CONFIG_NF_CONNTRACK_FTP=m
 CONFIG_NF_CONNTRACK_H323=m
 CONFIG_NF_CONNTRACK_IRC=m
 CONFIG_NF_CONNTRACK_NETBIOS_NS=m
+CONFIG_NF_CONNTRACK_SNMP=m
 CONFIG_NF_CONNTRACK_PPTP=m
 CONFIG_NF_CONNTRACK_SANE=m
 CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NETFILTER_XT_SET=m
+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
 CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
 CONFIG_NETFILTER_XT_TARGET_DSCP=m
+CONFIG_NETFILTER_XT_TARGET_HMARK=m
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m
+CONFIG_NETFILTER_XT_TARGET_LOG=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_TEE=m
 CONFIG_NETFILTER_XT_TARGET_TRACE=m
 CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
+CONFIG_NETFILTER_XT_MATCH_BPF=m
 CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
 CONFIG_NETFILTER_XT_MATCH_COMMENT=m
 CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m
 CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
 CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
 CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m
 CONFIG_NETFILTER_XT_MATCH_DSCP=m
 CONFIG_NETFILTER_XT_MATCH_ESP=m
 CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
@@ -81,6 +114,8 @@ CONFIG_NETFILTER_XT_MATCH_LIMIT=m
 CONFIG_NETFILTER_XT_MATCH_MAC=m
 CONFIG_NETFILTER_XT_MATCH_MARK=m
 CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_NFACCT=m
+CONFIG_NETFILTER_XT_MATCH_OSF=m
 CONFIG_NETFILTER_XT_MATCH_OWNER=m
 CONFIG_NETFILTER_XT_MATCH_POLICY=m
 CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
@@ -94,22 +129,31 @@ CONFIG_NETFILTER_XT_MATCH_STRING=m
 CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
 CONFIG_NETFILTER_XT_MATCH_TIME=m
 CONFIG_NETFILTER_XT_MATCH_U32=m
+CONFIG_IP_SET=m
+CONFIG_IP_SET_BITMAP_IP=m
+CONFIG_IP_SET_BITMAP_IPMAC=m
+CONFIG_IP_SET_BITMAP_PORT=m
+CONFIG_IP_SET_HASH_IP=m
+CONFIG_IP_SET_HASH_IPPORT=m
+CONFIG_IP_SET_HASH_IPPORTIP=m
+CONFIG_IP_SET_HASH_IPPORTNET=m
+CONFIG_IP_SET_HASH_NET=m
+CONFIG_IP_SET_HASH_NETPORT=m
+CONFIG_IP_SET_HASH_NETIFACE=m
+CONFIG_IP_SET_LIST_SET=m
 CONFIG_NF_CONNTRACK_IPV4=m
-CONFIG_IP_NF_QUEUE=m
 CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_ADDRTYPE=m
 CONFIG_IP_NF_MATCH_AH=m
 CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_RPFILTER=m
 CONFIG_IP_NF_MATCH_TTL=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
-CONFIG_IP_NF_TARGET_LOG=m
 CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_NF_NAT=m
+CONFIG_NF_NAT_IPV4=m
 CONFIG_IP_NF_TARGET_MASQUERADE=m
 CONFIG_IP_NF_TARGET_NETMAP=m
 CONFIG_IP_NF_TARGET_REDIRECT=m
-CONFIG_NF_NAT_SNMP_BASIC=m
 CONFIG_IP_NF_MANGLE=m
 CONFIG_IP_NF_TARGET_CLUSTERIP=m
 CONFIG_IP_NF_TARGET_ECN=m
@@ -119,7 +163,6 @@ CONFIG_IP_NF_ARPTABLES=m
 CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
 CONFIG_NF_CONNTRACK_IPV6=m
-CONFIG_IP6_NF_QUEUE=m
 CONFIG_IP6_NF_IPTABLES=m
 CONFIG_IP6_NF_MATCH_AH=m
 CONFIG_IP6_NF_MATCH_EUI64=m
@@ -128,21 +171,34 @@ CONFIG_IP6_NF_MATCH_OPTS=m
 CONFIG_IP6_NF_MATCH_HL=m
 CONFIG_IP6_NF_MATCH_IPV6HEADER=m
 CONFIG_IP6_NF_MATCH_MH=m
+CONFIG_IP6_NF_MATCH_RPFILTER=m
 CONFIG_IP6_NF_MATCH_RT=m
 CONFIG_IP6_NF_TARGET_HL=m
-CONFIG_IP6_NF_TARGET_LOG=m
 CONFIG_IP6_NF_FILTER=m
 CONFIG_IP6_NF_TARGET_REJECT=m
 CONFIG_IP6_NF_MANGLE=m
 CONFIG_IP6_NF_RAW=m
+CONFIG_NF_NAT_IPV6=m
+CONFIG_IP6_NF_TARGET_MASQUERADE=m
+CONFIG_IP6_NF_TARGET_NPT=m
 CONFIG_IP_DCCP=m
 # CONFIG_IP_DCCP_CCID3 is not set
+CONFIG_SCTP_COOKIE_HMAC_SHA1=y
+CONFIG_RDS=m
+CONFIG_RDS_TCP=m
+CONFIG_L2TP=m
 CONFIG_ATALK=m
+CONFIG_BATMAN_ADV=m
+CONFIG_BATMAN_ADV_DAT=y
+# CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
 # CONFIG_FIRMWARE_IN_KERNEL is not set
+# CONFIG_FW_LOADER_USER_HELPER is not set
 CONFIG_CONNECTOR=m
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_DRBD=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_CDROM_PKTCDVD=m
@@ -157,107 +213,136 @@ CONFIG_BLK_DEV_SR=y
 CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
 CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_SAS_LIBSAS=m
-# CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set
-CONFIG_SCSI_SRP_ATTRS=m
-CONFIG_SCSI_SRP_TGT_ATTRS=y
+CONFIG_SCSI_SAS_ATTRS=m
 CONFIG_ISCSI_TCP=m
+CONFIG_ISCSI_BOOT_SYSFS=m
 CONFIG_SUN3_SCSI=y
 CONFIG_MD=y
-CONFIG_BLK_DEV_MD=m
 CONFIG_MD_LINEAR=m
 CONFIG_MD_RAID0=m
-CONFIG_MD_RAID1=m
-CONFIG_MD_RAID456=m
 CONFIG_BLK_DEV_DM=m
 CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_THIN_PROVISIONING=m
+CONFIG_DM_CACHE=m
 CONFIG_DM_MIRROR=m
+CONFIG_DM_RAID=m
 CONFIG_DM_ZERO=m
 CONFIG_DM_MULTIPATH=m
 CONFIG_DM_UEVENT=y
+CONFIG_TARGET_CORE=m
+CONFIG_TCM_IBLOCK=m
+CONFIG_TCM_FILEIO=m
+CONFIG_TCM_PSCSI=m
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=m
-CONFIG_MACVLAN=m
 CONFIG_EQUALIZER=m
+CONFIG_NET_TEAM=m
+CONFIG_NET_TEAM_MODE_BROADCAST=m
+CONFIG_NET_TEAM_MODE_ROUNDROBIN=m
+CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m
+CONFIG_NET_TEAM_MODE_LOADBALANCE=m
+CONFIG_VXLAN=m
+CONFIG_NETCONSOLE=m
+CONFIG_NETCONSOLE_DYNAMIC=y
 CONFIG_VETH=m
-CONFIG_NET_ETHERNET=y
 CONFIG_SUN3LANCE=y
+# CONFIG_NET_CADENCE is not set
 CONFIG_SUN3_82586=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SUN is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
 CONFIG_PPP=m
-CONFIG_PPP_FILTER=y
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=m
 CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_FILTER=y
 CONFIG_PPP_MPPE=m
 CONFIG_PPPOE=m
+CONFIG_PPTP=m
+CONFIG_PPPOL2TP=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
 CONFIG_SLIP=m
 CONFIG_SLIP_COMPRESSED=y
 CONFIG_SLIP_SMART=y
 CONFIG_SLIP_MODE_SLIP6=y
-CONFIG_NETCONSOLE=m
-CONFIG_NETCONSOLE_DYNAMIC=y
-CONFIG_INPUT_FF_MEMLESS=m
+# CONFIG_WLAN is not set
+CONFIG_INPUT_EVDEV=m
 # CONFIG_KEYBOARD_ATKBD is not set
 CONFIG_KEYBOARD_SUNKBD=y
-CONFIG_MOUSE_PS2=m
+# CONFIG_MOUSE_PS2 is not set
 CONFIG_MOUSE_SERIAL=m
-# CONFIG_SERIO_SERPORT is not set
 CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_LEGACY_PTYS is not set
 # CONFIG_DEVKMEM is not set
 # CONFIG_HW_RANDOM is not set
-CONFIG_GEN_RTC=m
-CONFIG_GEN_RTC_X=y
+CONFIG_NTP_PPS=y
+CONFIG_PPS_CLIENT_LDISC=m
+CONFIG_PTP_1588_CLOCK=m
 # CONFIG_HWMON is not set
 CONFIG_FB=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_LOGO=y
 CONFIG_HID=m
 CONFIG_HIDRAW=y
+CONFIG_UHID=m
+# CONFIG_HID_GENERIC is not set
 # CONFIG_USB_SUPPORT is not set
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_GENERIC=m
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_PROC_HARDWARE=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 # CONFIG_EXT3_FS_XATTR is not set
+CONFIG_EXT4_FS=y
 CONFIG_REISERFS_FS=m
 CONFIG_JFS_FS=m
 CONFIG_XFS_FS=m
 CONFIG_OCFS2_FS=m
-# CONFIG_OCFS2_FS_STATS is not set
 # CONFIG_OCFS2_DEBUG_MASKLOG is not set
+CONFIG_FANOTIFY=y
 CONFIG_QUOTA_NETLINK_INTERFACE=y
 # CONFIG_PRINT_QUOTA_WARNING is not set
-CONFIG_AUTOFS_FS=m
 CONFIG_AUTOFS4_FS=m
 CONFIG_FUSE_FS=m
+CONFIG_CUSE=m
 CONFIG_ISO9660_FS=y
 CONFIG_JOLIET=y
 CONFIG_ZISOFS=y
 CONFIG_UDF_FS=m
-CONFIG_MSDOS_FS=y
+CONFIG_MSDOS_FS=m
 CONFIG_VFAT_FS=m
 CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
 CONFIG_AFFS_FS=m
+CONFIG_ECRYPT_FS=m
+CONFIG_ECRYPT_FS_MESSAGING=y
 CONFIG_HFS_FS=m
 CONFIG_HFSPLUS_FS=m
 CONFIG_CRAMFS=m
 CONFIG_SQUASHFS=m
-CONFIG_MINIX_FS=y
+CONFIG_SQUASHFS_LZO=y
+CONFIG_MINIX_FS=m
+CONFIG_OMFS_FS=m
 CONFIG_HPFS_FS=m
+CONFIG_QNX4FS_FS=m
+CONFIG_QNX6FS_FS=m
 CONFIG_SYSV_FS=m
 CONFIG_UFS_FS=m
 CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
 CONFIG_NFS_V4=y
+CONFIG_NFS_SWAP=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
 CONFIG_NFSD_V3=y
-CONFIG_SMB_FS=m
-CONFIG_SMB_NLS_DEFAULT=y
+CONFIG_CIFS=m
+# CONFIG_CIFS_DEBUG is not set
 CONFIG_CODA_FS=m
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_CODEPAGE_737=m
@@ -296,10 +381,23 @@ CONFIG_NLS_ISO8859_14=m
 CONFIG_NLS_ISO8859_15=m
 CONFIG_NLS_KOI8_R=m
 CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_MAC_ROMAN=m
+CONFIG_NLS_MAC_CELTIC=m
+CONFIG_NLS_MAC_CENTEURO=m
+CONFIG_NLS_MAC_CROATIAN=m
+CONFIG_NLS_MAC_CYRILLIC=m
+CONFIG_NLS_MAC_GAELIC=m
+CONFIG_NLS_MAC_GREEK=m
+CONFIG_NLS_MAC_ICELAND=m
+CONFIG_NLS_MAC_INUIT=m
+CONFIG_NLS_MAC_ROMANIAN=m
+CONFIG_NLS_MAC_TURKISH=m
 CONFIG_DLM=m
 CONFIG_MAGIC_SYSRQ=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_ASYNC_RAID6_TEST=m
+CONFIG_ENCRYPTED_KEYS=m
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_USER=m
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_CRYPTD=m
 CONFIG_CRYPTO_TEST=m
@@ -309,19 +407,16 @@ CONFIG_CRYPTO_CTS=m
 CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_XTS=m
-CONFIG_CRYPTO_HMAC=y
 CONFIG_CRYPTO_XCBC=m
-CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_VMAC=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_RMD128=m
 CONFIG_CRYPTO_RMD160=m
 CONFIG_CRYPTO_RMD256=m
 CONFIG_CRYPTO_RMD320=m
-CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_ANUBIS=m
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_CAMELLIA=m
@@ -337,6 +432,14 @@ CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_ZLIB=m
 CONFIG_CRYPTO_LZO=m
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_USER_API_HASH=m
+CONFIG_CRYPTO_USER_API_SKCIPHER=m
 # CONFIG_CRYPTO_HW is not set
-CONFIG_CRC16=m
 CONFIG_CRC_T10DIF=y
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
+CONFIG_XZ_DEC_TEST=m
index c80941c..832d953 100644 (file)
@@ -1,50 +1,71 @@
-CONFIG_EXPERIMENTAL=y
 CONFIG_LOCALVERSION="-sun3x"
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_FHANDLE=y
 CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_RELAY=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_LOG_BUF_SHIFT=16
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_AMIGA_PARTITION=y
+CONFIG_ATARI_PARTITION=y
+CONFIG_MAC_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+# CONFIG_EFI_PARTITION is not set
+CONFIG_SYSV68_PARTITION=y
+CONFIG_IOSCHED_DEADLINE=m
 CONFIG_SUN3X=y
+# CONFIG_COMPACTION is not set
+CONFIG_CLEANCACHE=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_BINFMT_AOUT=m
 CONFIG_BINFMT_MISC=m
-CONFIG_PROC_HARDWARE=y
 CONFIG_NET=y
 CONFIG_PACKET=y
+CONFIG_PACKET_DIAG=m
 CONFIG_UNIX=y
+CONFIG_UNIX_DIAG=m
+CONFIG_XFRM_MIGRATE=y
 CONFIG_NET_KEY=y
-CONFIG_NET_KEY_MIGRATE=y
 CONFIG_INET=y
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=y
 CONFIG_IP_PNP_BOOTP=y
 CONFIG_IP_PNP_RARP=y
 CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE_DEMUX=m
 CONFIG_NET_IPGRE=m
 CONFIG_SYN_COOKIES=y
+CONFIG_NET_IPVTI=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
 CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
 CONFIG_INET_XFRM_MODE_BEET=m
+# CONFIG_INET_LRO is not set
 CONFIG_INET_DIAG=m
+CONFIG_INET_UDP_DIAG=m
 CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
-CONFIG_IPV6_ROUTE_INFO=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
-CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
-CONFIG_IPV6_TUNNEL=m
+CONFIG_IPV6_GRE=m
 CONFIG_NETFILTER=y
-CONFIG_NETFILTER_NETLINK_QUEUE=m
 CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CONNTRACK_ZONES=y
+# CONFIG_NF_CONNTRACK_PROCFS is not set
 # CONFIG_NF_CT_PROTO_DCCP is not set
 CONFIG_NF_CT_PROTO_UDPLITE=m
 CONFIG_NF_CONNTRACK_AMANDA=m
@@ -52,25 +73,37 @@ CONFIG_NF_CONNTRACK_FTP=m
 CONFIG_NF_CONNTRACK_H323=m
 CONFIG_NF_CONNTRACK_IRC=m
 CONFIG_NF_CONNTRACK_NETBIOS_NS=m
+CONFIG_NF_CONNTRACK_SNMP=m
 CONFIG_NF_CONNTRACK_PPTP=m
 CONFIG_NF_CONNTRACK_SANE=m
 CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NETFILTER_XT_SET=m
+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
 CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
 CONFIG_NETFILTER_XT_TARGET_DSCP=m
+CONFIG_NETFILTER_XT_TARGET_HMARK=m
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m
+CONFIG_NETFILTER_XT_TARGET_LOG=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_TEE=m
 CONFIG_NETFILTER_XT_TARGET_TRACE=m
 CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
+CONFIG_NETFILTER_XT_MATCH_BPF=m
 CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
 CONFIG_NETFILTER_XT_MATCH_COMMENT=m
 CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m
 CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
 CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
 CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m
 CONFIG_NETFILTER_XT_MATCH_DSCP=m
 CONFIG_NETFILTER_XT_MATCH_ESP=m
 CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
@@ -81,6 +114,8 @@ CONFIG_NETFILTER_XT_MATCH_LIMIT=m
 CONFIG_NETFILTER_XT_MATCH_MAC=m
 CONFIG_NETFILTER_XT_MATCH_MARK=m
 CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_NFACCT=m
+CONFIG_NETFILTER_XT_MATCH_OSF=m
 CONFIG_NETFILTER_XT_MATCH_OWNER=m
 CONFIG_NETFILTER_XT_MATCH_POLICY=m
 CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
@@ -94,22 +129,31 @@ CONFIG_NETFILTER_XT_MATCH_STRING=m
 CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
 CONFIG_NETFILTER_XT_MATCH_TIME=m
 CONFIG_NETFILTER_XT_MATCH_U32=m
+CONFIG_IP_SET=m
+CONFIG_IP_SET_BITMAP_IP=m
+CONFIG_IP_SET_BITMAP_IPMAC=m
+CONFIG_IP_SET_BITMAP_PORT=m
+CONFIG_IP_SET_HASH_IP=m
+CONFIG_IP_SET_HASH_IPPORT=m
+CONFIG_IP_SET_HASH_IPPORTIP=m
+CONFIG_IP_SET_HASH_IPPORTNET=m
+CONFIG_IP_SET_HASH_NET=m
+CONFIG_IP_SET_HASH_NETPORT=m
+CONFIG_IP_SET_HASH_NETIFACE=m
+CONFIG_IP_SET_LIST_SET=m
 CONFIG_NF_CONNTRACK_IPV4=m
-CONFIG_IP_NF_QUEUE=m
 CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_ADDRTYPE=m
 CONFIG_IP_NF_MATCH_AH=m
 CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_RPFILTER=m
 CONFIG_IP_NF_MATCH_TTL=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
-CONFIG_IP_NF_TARGET_LOG=m
 CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_NF_NAT=m
+CONFIG_NF_NAT_IPV4=m
 CONFIG_IP_NF_TARGET_MASQUERADE=m
 CONFIG_IP_NF_TARGET_NETMAP=m
 CONFIG_IP_NF_TARGET_REDIRECT=m
-CONFIG_NF_NAT_SNMP_BASIC=m
 CONFIG_IP_NF_MANGLE=m
 CONFIG_IP_NF_TARGET_CLUSTERIP=m
 CONFIG_IP_NF_TARGET_ECN=m
@@ -119,7 +163,6 @@ CONFIG_IP_NF_ARPTABLES=m
 CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
 CONFIG_NF_CONNTRACK_IPV6=m
-CONFIG_IP6_NF_QUEUE=m
 CONFIG_IP6_NF_IPTABLES=m
 CONFIG_IP6_NF_MATCH_AH=m
 CONFIG_IP6_NF_MATCH_EUI64=m
@@ -128,21 +171,34 @@ CONFIG_IP6_NF_MATCH_OPTS=m
 CONFIG_IP6_NF_MATCH_HL=m
 CONFIG_IP6_NF_MATCH_IPV6HEADER=m
 CONFIG_IP6_NF_MATCH_MH=m
+CONFIG_IP6_NF_MATCH_RPFILTER=m
 CONFIG_IP6_NF_MATCH_RT=m
 CONFIG_IP6_NF_TARGET_HL=m
-CONFIG_IP6_NF_TARGET_LOG=m
 CONFIG_IP6_NF_FILTER=m
 CONFIG_IP6_NF_TARGET_REJECT=m
 CONFIG_IP6_NF_MANGLE=m
 CONFIG_IP6_NF_RAW=m
+CONFIG_NF_NAT_IPV6=m
+CONFIG_IP6_NF_TARGET_MASQUERADE=m
+CONFIG_IP6_NF_TARGET_NPT=m
 CONFIG_IP_DCCP=m
 # CONFIG_IP_DCCP_CCID3 is not set
+CONFIG_SCTP_COOKIE_HMAC_SHA1=y
+CONFIG_RDS=m
+CONFIG_RDS_TCP=m
+CONFIG_L2TP=m
 CONFIG_ATALK=m
+CONFIG_BATMAN_ADV=m
+CONFIG_BATMAN_ADV_DAT=y
+# CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
 # CONFIG_FIRMWARE_IN_KERNEL is not set
+# CONFIG_FW_LOADER_USER_HELPER is not set
 CONFIG_CONNECTOR=m
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_DRBD=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_CDROM_PKTCDVD=m
@@ -157,106 +213,136 @@ CONFIG_BLK_DEV_SR=y
 CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
 CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_SAS_LIBSAS=m
-# CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set
-CONFIG_SCSI_SRP_ATTRS=m
-CONFIG_SCSI_SRP_TGT_ATTRS=y
+CONFIG_SCSI_SAS_ATTRS=m
 CONFIG_ISCSI_TCP=m
+CONFIG_ISCSI_BOOT_SYSFS=m
 CONFIG_SUN3X_ESP=y
 CONFIG_MD=y
-CONFIG_BLK_DEV_MD=m
 CONFIG_MD_LINEAR=m
 CONFIG_MD_RAID0=m
-CONFIG_MD_RAID1=m
-CONFIG_MD_RAID456=m
 CONFIG_BLK_DEV_DM=m
 CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_THIN_PROVISIONING=m
+CONFIG_DM_CACHE=m
 CONFIG_DM_MIRROR=m
+CONFIG_DM_RAID=m
 CONFIG_DM_ZERO=m
 CONFIG_DM_MULTIPATH=m
 CONFIG_DM_UEVENT=y
+CONFIG_TARGET_CORE=m
+CONFIG_TCM_IBLOCK=m
+CONFIG_TCM_FILEIO=m
+CONFIG_TCM_PSCSI=m
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=m
-CONFIG_MACVLAN=m
 CONFIG_EQUALIZER=m
+CONFIG_NET_TEAM=m
+CONFIG_NET_TEAM_MODE_BROADCAST=m
+CONFIG_NET_TEAM_MODE_ROUNDROBIN=m
+CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m
+CONFIG_NET_TEAM_MODE_LOADBALANCE=m
+CONFIG_VXLAN=m
+CONFIG_NETCONSOLE=m
+CONFIG_NETCONSOLE_DYNAMIC=y
 CONFIG_VETH=m
-CONFIG_NET_ETHERNET=y
 CONFIG_SUN3LANCE=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
 CONFIG_PPP=m
-CONFIG_PPP_FILTER=y
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=m
 CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_FILTER=y
 CONFIG_PPP_MPPE=m
 CONFIG_PPPOE=m
+CONFIG_PPTP=m
+CONFIG_PPPOL2TP=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
 CONFIG_SLIP=m
 CONFIG_SLIP_COMPRESSED=y
 CONFIG_SLIP_SMART=y
 CONFIG_SLIP_MODE_SLIP6=y
-CONFIG_NETCONSOLE=m
-CONFIG_NETCONSOLE_DYNAMIC=y
-CONFIG_INPUT_FF_MEMLESS=m
+# CONFIG_WLAN is not set
+CONFIG_INPUT_EVDEV=m
 # CONFIG_KEYBOARD_ATKBD is not set
 CONFIG_KEYBOARD_SUNKBD=y
-CONFIG_MOUSE_PS2=m
+# CONFIG_MOUSE_PS2 is not set
 CONFIG_MOUSE_SERIAL=m
-# CONFIG_SERIO_SERPORT is not set
 CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_LEGACY_PTYS is not set
 # CONFIG_DEVKMEM is not set
 # CONFIG_HW_RANDOM is not set
-CONFIG_GEN_RTC=m
-CONFIG_GEN_RTC_X=y
+CONFIG_NTP_PPS=y
+CONFIG_PPS_CLIENT_LDISC=m
+CONFIG_PTP_1588_CLOCK=m
 # CONFIG_HWMON is not set
 CONFIG_FB=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_LOGO=y
 CONFIG_HID=m
 CONFIG_HIDRAW=y
+CONFIG_UHID=m
+# CONFIG_HID_GENERIC is not set
 # CONFIG_USB_SUPPORT is not set
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_GENERIC=m
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_PROC_HARDWARE=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 # CONFIG_EXT3_FS_XATTR is not set
+CONFIG_EXT4_FS=y
 CONFIG_REISERFS_FS=m
 CONFIG_JFS_FS=m
 CONFIG_XFS_FS=m
 CONFIG_OCFS2_FS=m
-# CONFIG_OCFS2_FS_STATS is not set
 # CONFIG_OCFS2_DEBUG_MASKLOG is not set
+CONFIG_FANOTIFY=y
 CONFIG_QUOTA_NETLINK_INTERFACE=y
 # CONFIG_PRINT_QUOTA_WARNING is not set
-CONFIG_AUTOFS_FS=m
 CONFIG_AUTOFS4_FS=m
 CONFIG_FUSE_FS=m
+CONFIG_CUSE=m
 CONFIG_ISO9660_FS=y
 CONFIG_JOLIET=y
 CONFIG_ZISOFS=y
 CONFIG_UDF_FS=m
-CONFIG_MSDOS_FS=y
+CONFIG_MSDOS_FS=m
 CONFIG_VFAT_FS=m
 CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
 CONFIG_AFFS_FS=m
+CONFIG_ECRYPT_FS=m
+CONFIG_ECRYPT_FS_MESSAGING=y
 CONFIG_HFS_FS=m
 CONFIG_HFSPLUS_FS=m
 CONFIG_CRAMFS=m
 CONFIG_SQUASHFS=m
-CONFIG_MINIX_FS=y
+CONFIG_SQUASHFS_LZO=y
+CONFIG_MINIX_FS=m
+CONFIG_OMFS_FS=m
 CONFIG_HPFS_FS=m
+CONFIG_QNX4FS_FS=m
+CONFIG_QNX6FS_FS=m
 CONFIG_SYSV_FS=m
 CONFIG_UFS_FS=m
 CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
 CONFIG_NFS_V4=y
+CONFIG_NFS_SWAP=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
 CONFIG_NFSD_V3=y
-CONFIG_SMB_FS=m
-CONFIG_SMB_NLS_DEFAULT=y
+CONFIG_CIFS=m
+# CONFIG_CIFS_DEBUG is not set
 CONFIG_CODA_FS=m
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_CODEPAGE_737=m
@@ -295,10 +381,23 @@ CONFIG_NLS_ISO8859_14=m
 CONFIG_NLS_ISO8859_15=m
 CONFIG_NLS_KOI8_R=m
 CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_MAC_ROMAN=m
+CONFIG_NLS_MAC_CELTIC=m
+CONFIG_NLS_MAC_CENTEURO=m
+CONFIG_NLS_MAC_CROATIAN=m
+CONFIG_NLS_MAC_CYRILLIC=m
+CONFIG_NLS_MAC_GAELIC=m
+CONFIG_NLS_MAC_GREEK=m
+CONFIG_NLS_MAC_ICELAND=m
+CONFIG_NLS_MAC_INUIT=m
+CONFIG_NLS_MAC_ROMANIAN=m
+CONFIG_NLS_MAC_TURKISH=m
 CONFIG_DLM=m
 CONFIG_MAGIC_SYSRQ=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_ASYNC_RAID6_TEST=m
+CONFIG_ENCRYPTED_KEYS=m
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_USER=m
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_CRYPTD=m
 CONFIG_CRYPTO_TEST=m
@@ -308,19 +407,16 @@ CONFIG_CRYPTO_CTS=m
 CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_XTS=m
-CONFIG_CRYPTO_HMAC=y
 CONFIG_CRYPTO_XCBC=m
-CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_VMAC=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_RMD128=m
 CONFIG_CRYPTO_RMD160=m
 CONFIG_CRYPTO_RMD256=m
 CONFIG_CRYPTO_RMD320=m
-CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_ANUBIS=m
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_CAMELLIA=m
@@ -336,6 +432,14 @@ CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_ZLIB=m
 CONFIG_CRYPTO_LZO=m
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_USER_API_HASH=m
+CONFIG_CRYPTO_USER_API_SKCIPHER=m
 # CONFIG_CRYPTO_HW is not set
-CONFIG_CRC16=m
 CONFIG_CRC_T10DIF=y
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
+CONFIG_XZ_DEC_TEST=m
index c7933e4..09d77a8 100644 (file)
@@ -6,7 +6,6 @@ generic-y += device.h
 generic-y += emergency-restart.h
 generic-y += errno.h
 generic-y += exec.h
-generic-y += futex.h
 generic-y += hw_irq.h
 generic-y += ioctl.h
 generic-y += ipcbuf.h
index a739985..66a36bd 100644 (file)
@@ -480,23 +480,6 @@ typedef struct scc_enet {
 #define SICR_ENET_CLKRT        ((uint)0x0000003d)
 #endif
 
-#ifdef CONFIG_RPXLITE
-/* This ENET stuff is for the MPC850 with ethernet on SCC2.  Some of
- * this may be unique to the RPX-Lite configuration.
- * Note TENA is on Port B.
- */
-#define PA_ENET_RXD    ((ushort)0x0004)
-#define PA_ENET_TXD    ((ushort)0x0008)
-#define PA_ENET_TCLK   ((ushort)0x0200)
-#define PA_ENET_RCLK   ((ushort)0x0800)
-#define PB_ENET_TENA   ((uint)0x00002000)
-#define PC_ENET_CLSN   ((ushort)0x0040)
-#define PC_ENET_RENA   ((ushort)0x0080)
-
-#define SICR_ENET_MASK ((uint)0x0000ff00)
-#define SICR_ENET_CLKRT        ((uint)0x00003d00)
-#endif
-
 #ifdef CONFIG_BSEIP
 /* This ENET stuff is for the MPC823 with ethernet on SCC2.
  * This is unique to the BSE ip-Engine board.
diff --git a/arch/m68k/include/asm/futex.h b/arch/m68k/include/asm/futex.h
new file mode 100644 (file)
index 0000000..bc868af
--- /dev/null
@@ -0,0 +1,94 @@
+#ifndef _ASM_M68K_FUTEX_H
+#define _ASM_M68K_FUTEX_H
+
+#ifdef __KERNEL__
+#if !defined(CONFIG_MMU)
+#include <asm-generic/futex.h>
+#else  /* CONFIG_MMU */
+
+#include <linux/futex.h>
+#include <linux/uaccess.h>
+#include <asm/errno.h>
+
+static inline int
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+                             u32 oldval, u32 newval)
+{
+       u32 val;
+
+       if (unlikely(get_user(val, uaddr) != 0))
+               return -EFAULT;
+
+       if (val == oldval && unlikely(put_user(newval, uaddr) != 0))
+               return -EFAULT;
+
+       *uval = val;
+
+       return 0;
+}
+
+static inline int
+futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
+{
+       int op = (encoded_op >> 28) & 7;
+       int cmp = (encoded_op >> 24) & 15;
+       int oparg = (encoded_op << 8) >> 20;
+       int cmparg = (encoded_op << 20) >> 20;
+       int oldval, ret;
+       u32 tmp;
+
+       if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+               oparg = 1 << oparg;
+
+       pagefault_disable();    /* implies preempt_disable() */
+
+       ret = -EFAULT;
+       if (unlikely(get_user(oldval, uaddr) != 0))
+               goto out_pagefault_enable;
+
+       ret = 0;
+       tmp = oldval;
+
+       switch (op) {
+       case FUTEX_OP_SET:
+               tmp = oparg;
+               break;
+       case FUTEX_OP_ADD:
+               tmp += oparg;
+               break;
+       case FUTEX_OP_OR:
+               tmp |= oparg;
+               break;
+       case FUTEX_OP_ANDN:
+               tmp &= ~oparg;
+               break;
+       case FUTEX_OP_XOR:
+               tmp ^= oparg;
+               break;
+       default:
+               ret = -ENOSYS;
+       }
+
+       if (ret == 0 && unlikely(put_user(tmp, uaddr) != 0))
+               ret = -EFAULT;
+
+out_pagefault_enable:
+       pagefault_enable();     /* subsumes preempt_enable() */
+
+       if (ret == 0) {
+               switch (cmp) {
+               case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+               case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+               case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+               case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+               case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+               case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+               default: ret = -ENOSYS;
+               }
+       }
+       return ret;
+}
+
+#endif /* CONFIG_MMU */
+#endif /* __KERNEL__ */
+#endif /* _ASM_M68K_FUTEX_H */
index 8cc8343..2f6eec1 100644 (file)
@@ -86,6 +86,7 @@ static inline int gpio_cansleep(unsigned gpio)
        return gpio < MCFGPIO_PIN_MAX ? 0 : __gpio_cansleep(gpio);
 }
 
+#ifndef CONFIG_GPIOLIB
 static inline int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)
 {
        int err;
@@ -105,5 +106,5 @@ static inline int gpio_request_one(unsigned gpio, unsigned long flags, const cha
 
        return err;
 }
-
+#endif /* !CONFIG_GPIOLIB */
 #endif
index d197e7f..ac85f16 100644 (file)
@@ -2752,11 +2752,9 @@ func_return      get_new_page
 #ifdef CONFIG_MAC
 
 L(scc_initable_mac):
-       .byte   9,12            /* Reset */
        .byte   4,0x44          /* x16, 1 stopbit, no parity */
        .byte   3,0xc0          /* receiver: 8 bpc */
        .byte   5,0xe2          /* transmitter: 8 bpc, assert dtr/rts */
-       .byte   9,0             /* no interrupts */
        .byte   10,0            /* NRZ */
        .byte   11,0x50         /* use baud rate generator */
        .byte   12,1,13,0       /* 38400 baud */
@@ -2899,6 +2897,7 @@ func_start        serial_init,%d0/%d1/%a0/%a1
        is_not_mac(L(serial_init_not_mac))
 
 #ifdef SERIAL_DEBUG
+
 /* You may define either or both of these. */
 #define MAC_USE_SCC_A /* Modem port */
 #define MAC_USE_SCC_B /* Printer port */
@@ -2908,9 +2907,21 @@ func_start       serial_init,%d0/%d1/%a0/%a1
 #define mac_scc_cha_b_data_offset      0x4
 #define mac_scc_cha_a_data_offset      0x6
 
+#if defined(MAC_USE_SCC_A) || defined(MAC_USE_SCC_B)
+       movel   %pc@(L(mac_sccbase)),%a0
+       /* Reset SCC device */
+       moveb   #9,%a0@(mac_scc_cha_a_ctrl_offset)
+       moveb   #0xc0,%a0@(mac_scc_cha_a_ctrl_offset)
+       /* Wait for 5 PCLK cycles, which is about 68 CPU cycles */
+       /* 5 / 3.6864 MHz = approx. 1.36 us = 68 / 50 MHz */
+       movel   #35,%d0
+5:
+       subq    #1,%d0
+       jne     5b
+#endif
+
 #ifdef MAC_USE_SCC_A
        /* Initialize channel A */
-       movel   %pc@(L(mac_sccbase)),%a0
        lea     %pc@(L(scc_initable_mac)),%a1
 5:     moveb   %a1@+,%d0
        jmi     6f
@@ -2922,9 +2933,6 @@ func_start        serial_init,%d0/%d1/%a0/%a1
 
 #ifdef MAC_USE_SCC_B
        /* Initialize channel B */
-#ifndef MAC_USE_SCC_A  /* Load mac_sccbase only if needed */
-       movel   %pc@(L(mac_sccbase)),%a0
-#endif /* MAC_USE_SCC_A */
        lea     %pc@(L(scc_initable_mac)),%a1
 7:     moveb   %a1@+,%d0
        jmi     8f
@@ -2933,6 +2941,7 @@ func_start        serial_init,%d0/%d1/%a0/%a1
        jra     7b
 8:
 #endif /* MAC_USE_SCC_B */
+
 #endif /* SERIAL_DEBUG */
 
        jra     L(serial_init_done)
@@ -3006,17 +3015,17 @@ func_start      serial_putc,%d0/%d1/%a0/%a1
 
 #ifdef SERIAL_DEBUG
 
-#ifdef MAC_USE_SCC_A
+#if defined(MAC_USE_SCC_A) || defined(MAC_USE_SCC_B)
        movel   %pc@(L(mac_sccbase)),%a1
+#endif
+
+#ifdef MAC_USE_SCC_A
 3:     btst    #2,%a1@(mac_scc_cha_a_ctrl_offset)
        jeq     3b
        moveb   %d0,%a1@(mac_scc_cha_a_data_offset)
 #endif /* MAC_USE_SCC_A */
 
 #ifdef MAC_USE_SCC_B
-#ifndef MAC_USE_SCC_A  /* Load mac_sccbase only if needed */
-       movel   %pc@(L(mac_sccbase)),%a1
-#endif /* MAC_USE_SCC_A */
 4:     btst    #2,%a1@(mac_scc_cha_b_ctrl_offset)
        jeq     4b
        moveb   %d0,%a1@(mac_scc_cha_b_data_offset)
index 0f553bc..ffea82a 100644 (file)
@@ -102,21 +102,23 @@ do { \
 
 #define flush_cache_range(vma, start, len) do { } while (0)
 
-#define copy_to_user_page(vma, page, vaddr, dst, src, len)             \
-do {                                                                   \
-       u32 addr = virt_to_phys(dst);                                   \
-       memcpy((dst), (src), (len));                                    \
-       if (vma->vm_flags & VM_EXEC) {                                  \
-               invalidate_icache_range((unsigned) (addr),              \
-                                       (unsigned) (addr) + PAGE_SIZE); \
-               flush_dcache_range((unsigned) (addr),                   \
-                                       (unsigned) (addr) + PAGE_SIZE); \
-       }                                                               \
-} while (0)
-
-#define copy_from_user_page(vma, page, vaddr, dst, src, len)           \
-do {                                                                   \
-       memcpy((dst), (src), (len));                                    \
-} while (0)
+static inline void copy_to_user_page(struct vm_area_struct *vma,
+                                    struct page *page, unsigned long vaddr,
+                                    void *dst, void *src, int len)
+{
+       u32 addr = virt_to_phys(dst);
+       memcpy(dst, src, len);
+       if (vma->vm_flags & VM_EXEC) {
+               invalidate_icache_range(addr, addr + PAGE_SIZE);
+               flush_dcache_range(addr, addr + PAGE_SIZE);
+       }
+}
+
+static inline void copy_from_user_page(struct vm_area_struct *vma,
+                                      struct page *page, unsigned long vaddr,
+                                      void *dst, void *src, int len)
+{
+       memcpy(dst, src, len);
+}
 
 #endif /* _ASM_MICROBLAZE_CACHEFLUSH_H */
index ff8cde1..01848f0 100644 (file)
@@ -105,7 +105,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
 
        __asm__ __volatile__ ("1:       lwx     %1, %3, r0;             \
                                        cmp     %2, %1, %4;             \
-                                       beqi    %2, 3f;                 \
+                                       bnei    %2, 3f;                 \
                                2:      swx     %5, %3, r0;             \
                                        addic   %2, r0, 0;              \
                                        bnei    %2, 1b;                 \
index 8cb8a85..2565cb9 100644 (file)
@@ -123,11 +123,11 @@ static inline void writel(unsigned int v, volatile void __iomem *addr)
  * inb_p/inw_p/...
  * The macros don't do byte-swapping.
  */
-#define inb(port)              readb((u8 *)((port)))
+#define inb(port)              readb((u8 *)((unsigned long)(port)))
 #define outb(val, port)                writeb((val), (u8 *)((unsigned long)(port)))
-#define inw(port)              readw((u16 *)((port)))
+#define inw(port)              readw((u16 *)((unsigned long)(port)))
 #define outw(val, port)                writew((val), (u16 *)((unsigned long)(port)))
-#define inl(port)              readl((u32 *)((port)))
+#define inl(port)              readl((u32 *)((unsigned long)(port)))
 #define outl(val, port)                writel((val), (u32 *)((unsigned long)(port)))
 
 #define inb_p(port)            inb((port))
index efe59d8..04e4955 100644 (file)
@@ -99,13 +99,13 @@ static inline int access_ok(int type, const void __user *addr,
        if ((get_fs().seg < ((unsigned long)addr)) ||
                        (get_fs().seg < ((unsigned long)addr + size - 1))) {
                pr_debug("ACCESS fail: %s at 0x%08x (size 0x%x), seg 0x%08x\n",
-                       type ? "WRITE" : "READ ", (u32)addr, (u32)size,
+                       type ? "WRITE" : "READ ", (__force u32)addr, (u32)size,
                        (u32)get_fs().seg);
                return 0;
        }
 ok:
        pr_debug("ACCESS OK: %s at 0x%08x (size 0x%x), seg 0x%08x\n",
-                       type ? "WRITE" : "READ ", (u32)addr, (u32)size,
+                       type ? "WRITE" : "READ ", (__force u32)addr, (u32)size,
                        (u32)get_fs().seg);
        return 1;
 }
index 4254514..a6e4441 100644 (file)
@@ -140,7 +140,7 @@ do {                                                                        \
 /* It is used only first parameter for OP - for wic, wdc */
 #define CACHE_RANGE_LOOP_1(start, end, line_length, op)                        \
 do {                                                                   \
-       int volatile temp;                                              \
+       int volatile temp = 0;                                          \
        int align = ~(line_length - 1);                                 \
        end = ((end & align) == end) ? end - line_length : end & align; \
        WARN_ON(end - start < 0);                                       \
index cb0f6af..9edc35f 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/i2c.h>
 #include <linux/i2c-gpio.h>
 #include <asm/bootinfo.h>
+#include <asm/idle.h>
 #include <asm/reboot.h>
 #include <asm/mach-au1x00/au1000.h>
 #include <prom.h>
index 38afb11..93fa586 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
 
+#include <asm/idle.h>
 #include <asm/processor.h>
 #include <asm/time.h>
 #include <asm/mach-au1x00/au1000.h>
index a0233a2..8be4e85 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/clk.h>
 
 #include <asm/bootinfo.h>
+#include <asm/idle.h>
 #include <asm/time.h>          /* for mips_hpt_frequency */
 #include <asm/reboot.h>                /* for _machine_{restart,halt} */
 #include <asm/mips_machine.h>
index b0baa29..01b1b3f 100644 (file)
@@ -428,13 +428,16 @@ static void octeon_restart(char *command)
  */
 static void octeon_kill_core(void *arg)
 {
-       mb();
-       if (octeon_is_simulation()) {
-               /* The simulator needs the watchdog to stop for dead cores */
-               cvmx_write_csr(CVMX_CIU_WDOGX(cvmx_get_core_num()), 0);
+       if (octeon_is_simulation())
                /* A break instruction causes the simulator stop a core */
-               asm volatile ("sync\nbreak");
-       }
+               asm volatile ("break" ::: "memory");
+
+       local_irq_disable();
+       /* Disable watchdog on this core. */
+       cvmx_write_csr(CVMX_CIU_WDOGX(cvmx_get_core_num()), 0);
+       /* Spin in a low power mode. */
+       while (true)
+               asm volatile ("wait" ::: "memory");
 }
 
 
index 516b442..4eedd48 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/io.h>
 #include <linux/leds.h>
 
+#include <asm/idle.h>
 #include <asm/processor.h>
 
 #include <cobalt.h>
index face9d2..bac26b9 100644 (file)
@@ -228,7 +228,6 @@ CONFIG_HIDRAW=y
 CONFIG_USB_HID=y
 CONFIG_USB_SUPPORT=y
 CONFIG_USB=y
-CONFIG_USB_SUSPEND=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_ROOT_HUB_TT=y
 CONFIG_USB_EHCI_TT_NEWSCHED=y
index 14752dd..e2b4ad5 100644 (file)
@@ -344,7 +344,6 @@ CONFIG_UHID=y
 CONFIG_USB_HIDDEV=y
 CONFIG_USB=y
 CONFIG_USB_DYNAMIC_MINORS=y
-CONFIG_USB_SUSPEND=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_HCD_PLATFORM=y
 CONFIG_USB_EHCI_ROOT_HUB_TT=y
index b6acd2f..343bebc 100644 (file)
@@ -300,7 +300,6 @@ CONFIG_USB=y
 CONFIG_USB_DEVICEFS=y
 # CONFIG_USB_DEVICE_CLASS is not set
 CONFIG_USB_DYNAMIC_MINORS=y
-CONFIG_USB_SUSPEND=y
 CONFIG_USB_OTG_WHITELIST=y
 CONFIG_USB_MON=y
 CONFIG_USB_EHCI_HCD=y
index c9456e7..778e32d 100644 (file)
@@ -6,8 +6,6 @@
 #include <linux/seq_file.h>
 #include <linux/clk.h>
 
-extern void (*cpu_wait) (void);
-
 struct clk;
 
 struct clk_ops {
diff --git a/arch/mips/include/asm/idle.h b/arch/mips/include/asm/idle.h
new file mode 100644 (file)
index 0000000..d192158
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef __ASM_IDLE_H
+#define __ASM_IDLE_H
+
+#include <linux/linkage.h>
+
+extern void (*cpu_wait)(void);
+extern void r4k_wait(void);
+extern asmlinkage void __r4k_wait(void);
+extern void r4k_wait_irqoff(void);
+extern void __pastwait(void);
+
+static inline int using_rollback_handler(void)
+{
+       return cpu_wait == r4k_wait;
+}
+
+static inline int address_is_in_r4k_wait_irqoff(unsigned long addr)
+{
+       return addr >= (unsigned long)r4k_wait_irqoff &&
+              addr < (unsigned long)__pastwait;
+}
+
+#endif /* __ASM_IDLE_H  */
index 1be1372..b7e5985 100644 (file)
@@ -118,7 +118,7 @@ static inline void set_io_port_base(unsigned long base)
  */
 static inline unsigned long virt_to_phys(volatile const void *address)
 {
-       return (unsigned long)address - PAGE_OFFSET + PHYS_OFFSET;
+       return __pa(address);
 }
 
 /*
diff --git a/arch/mips/include/asm/kvm.h b/arch/mips/include/asm/kvm.h
deleted file mode 100644 (file)
index 85789ea..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
-* 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) 2012  MIPS Technologies, Inc.  All rights reserved.
-* Authors: Sanjay Lal <sanjayl@kymasys.com>
-*/
-
-#ifndef __LINUX_KVM_MIPS_H
-#define __LINUX_KVM_MIPS_H
-
-#include <linux/types.h>
-
-#define __KVM_MIPS
-
-#define N_MIPS_COPROC_REGS      32
-#define N_MIPS_COPROC_SEL      8
-
-/* for KVM_GET_REGS and KVM_SET_REGS */
-struct kvm_regs {
-       __u32 gprs[32];
-       __u32 hi;
-       __u32 lo;
-       __u32 pc;
-
-       __u32 cp0reg[N_MIPS_COPROC_REGS][N_MIPS_COPROC_SEL];
-};
-
-/* for KVM_GET_SREGS and KVM_SET_SREGS */
-struct kvm_sregs {
-};
-
-/* for KVM_GET_FPU and KVM_SET_FPU */
-struct kvm_fpu {
-};
-
-struct kvm_debug_exit_arch {
-};
-
-/* for KVM_SET_GUEST_DEBUG */
-struct kvm_guest_debug_arch {
-};
-
-struct kvm_mips_interrupt {
-       /* in */
-       __u32 cpu;
-       __u32 irq;
-};
-
-/* definition of registers in kvm_run */
-struct kvm_sync_regs {
-};
-
-#endif /* __LINUX_KVM_MIPS_H */
index e68781e..4d6fa0b 100644 (file)
@@ -336,7 +336,7 @@ enum emulation_result {
 #define VPN2_MASK           0xffffe000
 #define TLB_IS_GLOBAL(x)    (((x).tlb_lo0 & MIPS3_PG_G) && ((x).tlb_lo1 & MIPS3_PG_G))
 #define TLB_VPN2(x)         ((x).tlb_hi & VPN2_MASK)
-#define TLB_ASID(x)         (ASID_MASK((x).tlb_hi))
+#define TLB_ASID(x)         ((x).tlb_hi & ASID_MASK)
 #define TLB_IS_VALID(x, va) (((va) & (1 << PAGE_SHIFT)) ? ((x).tlb_lo1 & MIPS3_PG_V) : ((x).tlb_lo0 & MIPS3_PG_V))
 
 struct kvm_mips_tlb {
@@ -496,10 +496,6 @@ struct kvm_mips_callbacks {
                            uint32_t cause);
        int (*irq_clear) (struct kvm_vcpu *vcpu, unsigned int priority,
                          uint32_t cause);
-       int (*vcpu_ioctl_get_regs) (struct kvm_vcpu *vcpu,
-                                   struct kvm_regs *regs);
-       int (*vcpu_ioctl_set_regs) (struct kvm_vcpu *vcpu,
-                                   struct kvm_regs *regs);
 };
 extern struct kvm_mips_callbacks *kvm_mips_callbacks;
 int kvm_mips_emulation_init(struct kvm_mips_callbacks **install_callbacks);
index 1554721..516e6e9 100644 (file)
@@ -67,68 +67,45 @@ extern unsigned long pgd_current[];
        TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir)
 #endif
 #endif /* CONFIG_MIPS_PGD_C0_CONTEXT*/
+#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
 
-#define ASID_INC(asid)                                         \
-({                                                             \
-       unsigned long __asid = asid;                            \
-       __asm__("1:\taddiu\t%0,1\t\t\t\t# patched\n\t"          \
-       ".section\t__asid_inc,\"a\"\n\t"                        \
-       ".word\t1b\n\t"                                         \
-       ".previous"                                             \
-       :"=r" (__asid)                                          \
-       :"0" (__asid));                                         \
-       __asid;                                                 \
-})
-#define ASID_MASK(asid)                                                \
-({                                                             \
-       unsigned long __asid = asid;                            \
-       __asm__("1:\tandi\t%0,%1,0xfc0\t\t\t# patched\n\t"      \
-       ".section\t__asid_mask,\"a\"\n\t"                       \
-       ".word\t1b\n\t"                                         \
-       ".previous"                                             \
-       :"=r" (__asid)                                          \
-       :"r" (__asid));                                         \
-       __asid;                                                 \
-})
-#define ASID_VERSION_MASK                                      \
-({                                                             \
-       unsigned long __asid;                                   \
-       __asm__("1:\taddiu\t%0,$0,0xff00\t\t\t\t# patched\n\t"  \
-       ".section\t__asid_version_mask,\"a\"\n\t"               \
-       ".word\t1b\n\t"                                         \
-       ".previous"                                             \
-       :"=r" (__asid));                                        \
-       __asid;                                                 \
-})
-#define ASID_FIRST_VERSION                                     \
-({                                                             \
-       unsigned long __asid = asid;                            \
-       __asm__("1:\tli\t%0,0x100\t\t\t\t# patched\n\t"         \
-       ".section\t__asid_first_version,\"a\"\n\t"              \
-       ".word\t1b\n\t"                                         \
-       ".previous"                                             \
-       :"=r" (__asid));                                        \
-       __asid;                                                 \
-})
-
-#define ASID_FIRST_VERSION_R3000       0x1000
-#define ASID_FIRST_VERSION_R4000       0x100
-#define ASID_FIRST_VERSION_R8000       0x1000
-#define ASID_FIRST_VERSION_RM9000      0x1000
+#define ASID_INC       0x40
+#define ASID_MASK      0xfc0
+
+#elif defined(CONFIG_CPU_R8000)
+
+#define ASID_INC       0x10
+#define ASID_MASK      0xff0
+
+#elif defined(CONFIG_MIPS_MT_SMTC)
+
+#define ASID_INC       0x1
+extern unsigned long smtc_asid_mask;
+#define ASID_MASK      (smtc_asid_mask)
+#define HW_ASID_MASK   0xff
+/* End SMTC/34K debug hack */
+#else /* FIXME: not correct for R6000 */
+
+#define ASID_INC       0x1
+#define ASID_MASK      0xff
 
-#ifdef CONFIG_MIPS_MT_SMTC
-#define SMTC_HW_ASID_MASK              0xff
-extern unsigned int smtc_asid_mask;
 #endif
 
 #define cpu_context(cpu, mm)   ((mm)->context.asid[cpu])
-#define cpu_asid(cpu, mm)      ASID_MASK(cpu_context((cpu), (mm)))
+#define cpu_asid(cpu, mm)      (cpu_context((cpu), (mm)) & ASID_MASK)
 #define asid_cache(cpu)                (cpu_data[cpu].asid_cache)
 
 static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
 {
 }
 
+/*
+ *  All unused by hardware upper bits will be considered
+ *  as a software asid extension.
+ */
+#define ASID_VERSION_MASK  ((unsigned long)~(ASID_MASK|(ASID_MASK-1)))
+#define ASID_FIRST_VERSION ((unsigned long)(~ASID_VERSION_MASK) + 1)
+
 #ifndef CONFIG_MIPS_MT_SMTC
 /* Normal, classic MIPS get_new_mmu_context */
 static inline void
@@ -137,10 +114,10 @@ get_new_mmu_context(struct mm_struct *mm, unsigned long cpu)
        extern void kvm_local_flush_tlb_all(void);
        unsigned long asid = asid_cache(cpu);
 
-       if (!ASID_MASK((asid = ASID_INC(asid)))) {
+       if (! ((asid += ASID_INC) & ASID_MASK) ) {
                if (cpu_has_vtag_icache)
                        flush_icache_all();
-#ifdef CONFIG_VIRTUALIZATION
+#ifdef CONFIG_KVM
                kvm_local_flush_tlb_all();      /* start new asid cycle */
 #else
                local_flush_tlb_all();  /* start new asid cycle */
@@ -200,7 +177,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
         * free up the ASID value for use and flush any old
         * instances of it from the TLB.
         */
-       oldasid = ASID_MASK(read_c0_entryhi());
+       oldasid = (read_c0_entryhi() & ASID_MASK);
        if(smtc_live_asid[mytlb][oldasid]) {
                smtc_live_asid[mytlb][oldasid] &= ~(0x1 << cpu);
                if(smtc_live_asid[mytlb][oldasid] == 0)
@@ -211,7 +188,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
         * having ASID_MASK smaller than the hardware maximum,
         * make sure no "soft" bits become "hard"...
         */
-       write_c0_entryhi((read_c0_entryhi() & ~SMTC_HW_ASID_MASK) |
+       write_c0_entryhi((read_c0_entryhi() & ~HW_ASID_MASK) |
                         cpu_asid(cpu, next));
        ehb(); /* Make sure it propagates to TCStatus */
        evpe(mtflags);
@@ -264,15 +241,15 @@ activate_mm(struct mm_struct *prev, struct mm_struct *next)
 #ifdef CONFIG_MIPS_MT_SMTC
        /* See comments for similar code above */
        mtflags = dvpe();
-       oldasid = ASID_MASK(read_c0_entryhi());
+       oldasid = read_c0_entryhi() & ASID_MASK;
        if(smtc_live_asid[mytlb][oldasid]) {
                smtc_live_asid[mytlb][oldasid] &= ~(0x1 << cpu);
                if(smtc_live_asid[mytlb][oldasid] == 0)
                         smtc_flush_tlb_asid(oldasid);
        }
        /* See comments for similar code above */
-       write_c0_entryhi((read_c0_entryhi() & ~SMTC_HW_ASID_MASK) |
-                        cpu_asid(cpu, next));
+       write_c0_entryhi((read_c0_entryhi() & ~HW_ASID_MASK) |
+                        cpu_asid(cpu, next));
        ehb(); /* Make sure it propagates to TCStatus */
        evpe(mtflags);
 #else
@@ -309,14 +286,14 @@ drop_mmu_context(struct mm_struct *mm, unsigned cpu)
 #ifdef CONFIG_MIPS_MT_SMTC
                /* See comments for similar code above */
                prevvpe = dvpe();
-               oldasid = ASID_MASK(read_c0_entryhi());
+               oldasid = (read_c0_entryhi() & ASID_MASK);
                if (smtc_live_asid[mytlb][oldasid]) {
                        smtc_live_asid[mytlb][oldasid] &= ~(0x1 << cpu);
                        if(smtc_live_asid[mytlb][oldasid] == 0)
                                smtc_flush_tlb_asid(oldasid);
                }
                /* See comments for similar code above */
-               write_c0_entryhi((read_c0_entryhi() & ~SMTC_HW_ASID_MASK)
+               write_c0_entryhi((read_c0_entryhi() & ~HW_ASID_MASK)
                                | cpu_asid(cpu, mm));
                ehb(); /* Make sure it propagates to TCStatus */
                evpe(prevvpe);
index eab99e5..f59552f 100644 (file)
@@ -46,7 +46,6 @@
 #endif /* CONFIG_MIPS_HUGE_TLB_SUPPORT */
 
 #include <linux/pfn.h>
-#include <asm/io.h>
 
 extern void build_clear_page(void);
 extern void build_copy_page(void);
@@ -151,6 +150,7 @@ typedef struct { unsigned long pgprot; } pgprot_t;
     ((unsigned long)(x) - PAGE_OFFSET + PHYS_OFFSET)
 #endif
 #define __va(x)                ((void *)((unsigned long)(x) + PAGE_OFFSET - PHYS_OFFSET))
+#include <asm/io.h>
 
 /*
  * RELOC_HIDE was originally added by 6007b903dfe5f1d13e0c711ac2894bdd4a61b1ad
@@ -171,14 +171,13 @@ typedef struct { unsigned long pgprot; } pgprot_t;
 
 #ifdef CONFIG_FLATMEM
 
-#define pfn_valid(pfn)                                                 \
-({                                                                     \
-       unsigned long __pfn = (pfn);                                    \
-       /* avoid <linux/bootmem.h> include hell */                      \
-       extern unsigned long min_low_pfn;                               \
-                                                                       \
-       __pfn >= min_low_pfn && __pfn < max_mapnr;                      \
-})
+static inline int pfn_valid(unsigned long pfn)
+{
+       /* avoid <linux/mm.h> include hell */
+       extern unsigned long max_mapnr;
+
+       return pfn >= ARCH_PFN_OFFSET && pfn < max_mapnr;
+}
 
 #elif defined(CONFIG_SPARSEMEM)
 
index 71686c8..1470b7b 100644 (file)
@@ -28,7 +28,6 @@
 /*
  * System setup and hardware flags..
  */
-extern void (*cpu_wait)(void);
 
 extern unsigned int vced_count, vcei_count;
 
index a3186f2..5e6cd09 100644 (file)
 #include <asm/isadep.h>
 #include <uapi/asm/ptrace.h>
 
+/*
+ * This struct defines the way the registers are stored on the stack during a
+ * system call/exception. As usual the registers k0/k1 aren't being saved.
+ */
+struct pt_regs {
+#ifdef CONFIG_32BIT
+       /* Pad bytes for argument save space on the stack. */
+       unsigned long pad0[6];
+#endif
+
+       /* Saved main processor registers. */
+       unsigned long regs[32];
+
+       /* Saved special registers. */
+       unsigned long cp0_status;
+       unsigned long hi;
+       unsigned long lo;
+#ifdef CONFIG_CPU_HAS_SMARTMIPS
+       unsigned long acx;
+#endif
+       unsigned long cp0_badvaddr;
+       unsigned long cp0_cause;
+       unsigned long cp0_epc;
+#ifdef CONFIG_MIPS_MT_SMTC
+       unsigned long cp0_tcstatus;
+#endif /* CONFIG_MIPS_MT_SMTC */
+#ifdef CONFIG_CPU_CAVIUM_OCTEON
+       unsigned long long mpl[3];        /* MTM{0,1,2} */
+       unsigned long long mtp[3];        /* MTP{0,1,2} */
+#endif
+} __aligned(8);
+
 struct task_struct;
 
 extern int ptrace_getregs(struct task_struct *child, __s64 __user *data);
diff --git a/arch/mips/include/uapi/asm/kvm.h b/arch/mips/include/uapi/asm/kvm.h
new file mode 100644 (file)
index 0000000..f09ff5a
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * 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) 2012  MIPS Technologies, Inc.  All rights reserved.
+ * Copyright (C) 2013 Cavium, Inc.
+ * Authors: Sanjay Lal <sanjayl@kymasys.com>
+ */
+
+#ifndef __LINUX_KVM_MIPS_H
+#define __LINUX_KVM_MIPS_H
+
+#include <linux/types.h>
+
+/*
+ * KVM MIPS specific structures and definitions.
+ *
+ * Some parts derived from the x86 version of this file.
+ */
+
+/*
+ * for KVM_GET_REGS and KVM_SET_REGS
+ *
+ * If Config[AT] is zero (32-bit CPU), the register contents are
+ * stored in the lower 32-bits of the struct kvm_regs fields and sign
+ * extended to 64-bits.
+ */
+struct kvm_regs {
+       /* out (KVM_GET_REGS) / in (KVM_SET_REGS) */
+       __u64 gpr[32];
+       __u64 hi;
+       __u64 lo;
+       __u64 pc;
+};
+
+/*
+ * for KVM_GET_FPU and KVM_SET_FPU
+ *
+ * If Status[FR] is zero (32-bit FPU), the upper 32-bits of the FPRs
+ * are zero filled.
+ */
+struct kvm_fpu {
+       __u64 fpr[32];
+       __u32 fir;
+       __u32 fccr;
+       __u32 fexr;
+       __u32 fenr;
+       __u32 fcsr;
+       __u32 pad;
+};
+
+
+/*
+ * For MIPS, we use KVM_SET_ONE_REG and KVM_GET_ONE_REG to access CP0
+ * registers.  The id field is broken down as follows:
+ *
+ *  bits[2..0]   - Register 'sel' index.
+ *  bits[7..3]   - Register 'rd'  index.
+ *  bits[15..8]  - Must be zero.
+ *  bits[31..16] - 1 -> CP0 registers.
+ *  bits[51..32] - Must be zero.
+ *  bits[63..52] - As per linux/kvm.h
+ *
+ * Other sets registers may be added in the future.  Each set would
+ * have its own identifier in bits[31..16].
+ *
+ * The registers defined in struct kvm_regs are also accessible, the
+ * id values for these are below.
+ */
+
+#define KVM_REG_MIPS_R0 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 0)
+#define KVM_REG_MIPS_R1 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 1)
+#define KVM_REG_MIPS_R2 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 2)
+#define KVM_REG_MIPS_R3 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 3)
+#define KVM_REG_MIPS_R4 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 4)
+#define KVM_REG_MIPS_R5 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 5)
+#define KVM_REG_MIPS_R6 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 6)
+#define KVM_REG_MIPS_R7 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 7)
+#define KVM_REG_MIPS_R8 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 8)
+#define KVM_REG_MIPS_R9 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 9)
+#define KVM_REG_MIPS_R10 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 10)
+#define KVM_REG_MIPS_R11 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 11)
+#define KVM_REG_MIPS_R12 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 12)
+#define KVM_REG_MIPS_R13 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 13)
+#define KVM_REG_MIPS_R14 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 14)
+#define KVM_REG_MIPS_R15 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 15)
+#define KVM_REG_MIPS_R16 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 16)
+#define KVM_REG_MIPS_R17 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 17)
+#define KVM_REG_MIPS_R18 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 18)
+#define KVM_REG_MIPS_R19 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 19)
+#define KVM_REG_MIPS_R20 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 20)
+#define KVM_REG_MIPS_R21 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 21)
+#define KVM_REG_MIPS_R22 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 22)
+#define KVM_REG_MIPS_R23 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 23)
+#define KVM_REG_MIPS_R24 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 24)
+#define KVM_REG_MIPS_R25 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 25)
+#define KVM_REG_MIPS_R26 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 26)
+#define KVM_REG_MIPS_R27 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 27)
+#define KVM_REG_MIPS_R28 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 28)
+#define KVM_REG_MIPS_R29 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 29)
+#define KVM_REG_MIPS_R30 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 30)
+#define KVM_REG_MIPS_R31 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 31)
+
+#define KVM_REG_MIPS_HI (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 32)
+#define KVM_REG_MIPS_LO (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 33)
+#define KVM_REG_MIPS_PC (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 34)
+
+/*
+ * KVM MIPS specific structures and definitions
+ *
+ */
+struct kvm_debug_exit_arch {
+       __u64 epc;
+};
+
+/* for KVM_SET_GUEST_DEBUG */
+struct kvm_guest_debug_arch {
+};
+
+/* definition of registers in kvm_run */
+struct kvm_sync_regs {
+};
+
+/* dummy definition */
+struct kvm_sregs {
+};
+
+struct kvm_mips_interrupt {
+       /* in */
+       __u32 cpu;
+       __u32 irq;
+};
+
+#endif /* __LINUX_KVM_MIPS_H */
index 4d58d84..b26f7e3 100644 (file)
 #define DSP_CONTROL    77
 #define ACX            78
 
+#ifndef __KERNEL__
 /*
  * This struct defines the way the registers are stored on the stack during a
  * system call/exception. As usual the registers k0/k1 aren't being saved.
  */
 struct pt_regs {
-#ifdef CONFIG_32BIT
-       /* Pad bytes for argument save space on the stack. */
-       unsigned long pad0[6];
-#endif
-
        /* Saved main processor registers. */
        unsigned long regs[32];
 
@@ -39,20 +35,11 @@ struct pt_regs {
        unsigned long cp0_status;
        unsigned long hi;
        unsigned long lo;
-#ifdef CONFIG_CPU_HAS_SMARTMIPS
-       unsigned long acx;
-#endif
        unsigned long cp0_badvaddr;
        unsigned long cp0_cause;
        unsigned long cp0_epc;
-#ifdef CONFIG_MIPS_MT_SMTC
-       unsigned long cp0_tcstatus;
-#endif /* CONFIG_MIPS_MT_SMTC */
-#ifdef CONFIG_CPU_CAVIUM_OCTEON
-       unsigned long long mpl[3];        /* MTM{0,1,2} */
-       unsigned long long mtp[3];        /* MTP{0,1,2} */
-#endif
 } __attribute__ ((aligned (8)));
+#endif /* __KERNEL__ */
 
 /* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
 #define PTRACE_GETREGS         12
index 16338b8..1dee279 100644 (file)
 #define __NR_process_vm_writev         (__NR_Linux + 305)
 #define __NR_kcmp                      (__NR_Linux + 306)
 #define __NR_finit_module              (__NR_Linux + 307)
+#define __NR_getdents64                        (__NR_Linux + 308)
 
 /*
  * Offset of the last Linux 64-bit flavoured syscall
  */
-#define __NR_Linux_syscalls            307
+#define __NR_Linux_syscalls            308
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
 
 #define __NR_64_Linux                  5000
-#define __NR_64_Linux_syscalls         307
+#define __NR_64_Linux_syscalls         308
 
 #if _MIPS_SIM == _MIPS_SIM_NABI32
 
index 6ad9e04..423d871 100644 (file)
@@ -4,7 +4,7 @@
 
 extra-y                := head.o vmlinux.lds
 
-obj-y          += cpu-probe.o branch.o entry.o genex.o irq.o process.o \
+obj-y          += cpu-probe.o branch.o entry.o genex.o idle.o irq.o process.o \
                   prom.o ptrace.o reset.o setup.o signal.o syscall.o \
                   time.o topology.o traps.o unaligned.o watch.o vdso.o
 
index e06f777..1188e00 100644 (file)
@@ -119,4 +119,15 @@ MODULE_AUTHOR("Ralf Baechle (ralf@linux-mips.org)");
 #undef TASK_SIZE
 #define TASK_SIZE TASK_SIZE32
 
+#undef cputime_to_timeval
+#define cputime_to_timeval cputime_to_compat_timeval
+static __inline__ void
+cputime_to_compat_timeval(const cputime_t cputime, struct compat_timeval *value)
+{
+       unsigned long jiffies = cputime_to_jiffies(cputime);
+
+       value->tv_usec = (jiffies % HZ) * (1000000L / HZ);
+       value->tv_sec = jiffies / HZ;
+}
+
 #include "../../../fs/binfmt_elf.c"
index 97c5a16..202e581 100644 (file)
@@ -162,4 +162,15 @@ MODULE_AUTHOR("Ralf Baechle (ralf@linux-mips.org)");
 #undef TASK_SIZE
 #define TASK_SIZE TASK_SIZE32
 
+#undef cputime_to_timeval
+#define cputime_to_timeval cputime_to_compat_timeval
+static __inline__ void
+cputime_to_compat_timeval(const cputime_t cputime, struct compat_timeval *value)
+{
+       unsigned long jiffies = cputime_to_jiffies(cputime);
+
+       value->tv_usec = (jiffies % HZ) * (1000000L / HZ);
+       value->tv_sec = jiffies / HZ;
+}
+
 #include "../../../fs/binfmt_elf.c"
index 4bbffdb..c6568bf 100644 (file)
 #include <asm/spram.h>
 #include <asm/uaccess.h>
 
-/*
- * Not all of the MIPS CPUs have the "wait" instruction available. Moreover,
- * the implementation of the "wait" feature differs between CPU families. This
- * points to the function that implements CPU specific wait.
- * The wait instruction stops the pipeline and reduces the power consumption of
- * the CPU very much.
- */
-void (*cpu_wait)(void);
-EXPORT_SYMBOL(cpu_wait);
-
-static void r3081_wait(void)
-{
-       unsigned long cfg = read_c0_conf();
-       write_c0_conf(cfg | R30XX_CONF_HALT);
-}
-
-static void r39xx_wait(void)
-{
-       local_irq_disable();
-       if (!need_resched())
-               write_c0_conf(read_c0_conf() | TX39_CONF_HALT);
-       local_irq_enable();
-}
-
-extern void r4k_wait(void);
-
-/*
- * This variant is preferable as it allows testing need_resched and going to
- * sleep depending on the outcome atomically.  Unfortunately the "It is
- * implementation-dependent whether the pipeline restarts when a non-enabled
- * interrupt is requested" restriction in the MIPS32/MIPS64 architecture makes
- * using this version a gamble.
- */
-void r4k_wait_irqoff(void)
-{
-       local_irq_disable();
-       if (!need_resched())
-               __asm__("       .set    push            \n"
-                       "       .set    mips3           \n"
-                       "       wait                    \n"
-                       "       .set    pop             \n");
-       local_irq_enable();
-       __asm__("       .globl __pastwait       \n"
-               "__pastwait:                    \n");
-}
-
-/*
- * The RM7000 variant has to handle erratum 38.         The workaround is to not
- * have any pending stores when the WAIT instruction is executed.
- */
-static void rm7k_wait_irqoff(void)
-{
-       local_irq_disable();
-       if (!need_resched())
-               __asm__(
-               "       .set    push                                    \n"
-               "       .set    mips3                                   \n"
-               "       .set    noat                                    \n"
-               "       mfc0    $1, $12                                 \n"
-               "       sync                                            \n"
-               "       mtc0    $1, $12         # stalls until W stage  \n"
-               "       wait                                            \n"
-               "       mtc0    $1, $12         # stalls until W stage  \n"
-               "       .set    pop                                     \n");
-       local_irq_enable();
-}
-
-/*
- * The Au1xxx wait is available only if using 32khz counter or
- * external timer source, but specifically not CP0 Counter.
- * alchemy/common/time.c may override cpu_wait!
- */
-static void au1k_wait(void)
-{
-       __asm__("       .set    mips3                   \n"
-               "       cache   0x14, 0(%0)             \n"
-               "       cache   0x14, 32(%0)            \n"
-               "       sync                            \n"
-               "       nop                             \n"
-               "       wait                            \n"
-               "       nop                             \n"
-               "       nop                             \n"
-               "       nop                             \n"
-               "       nop                             \n"
-               "       .set    mips0                   \n"
-               : : "r" (au1k_wait));
-}
-
-static int __initdata nowait;
-
-static int __init wait_disable(char *s)
-{
-       nowait = 1;
-
-       return 1;
-}
-
-__setup("nowait", wait_disable);
-
 static int __cpuinitdata mips_fpu_disabled;
 
 static int __init fpu_disable(char *s)
@@ -150,105 +51,6 @@ static int __init dsp_disable(char *s)
 
 __setup("nodsp", dsp_disable);
 
-void __init check_wait(void)
-{
-       struct cpuinfo_mips *c = &current_cpu_data;
-
-       if (nowait) {
-               printk("Wait instruction disabled.\n");
-               return;
-       }
-
-       switch (c->cputype) {
-       case CPU_R3081:
-       case CPU_R3081E:
-               cpu_wait = r3081_wait;
-               break;
-       case CPU_TX3927:
-               cpu_wait = r39xx_wait;
-               break;
-       case CPU_R4200:
-/*     case CPU_R4300: */
-       case CPU_R4600:
-       case CPU_R4640:
-       case CPU_R4650:
-       case CPU_R4700:
-       case CPU_R5000:
-       case CPU_R5500:
-       case CPU_NEVADA:
-       case CPU_4KC:
-       case CPU_4KEC:
-       case CPU_4KSC:
-       case CPU_5KC:
-       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:
-       case CPU_JZRISC:
-       case CPU_LOONGSON1:
-       case CPU_XLR:
-       case CPU_XLP:
-               cpu_wait = r4k_wait;
-               break;
-
-       case CPU_RM7000:
-               cpu_wait = rm7k_wait_irqoff;
-               break;
-
-       case CPU_M14KC:
-       case CPU_M14KEC:
-       case CPU_24K:
-       case CPU_34K:
-       case CPU_1004K:
-               cpu_wait = r4k_wait;
-               if (read_c0_config7() & MIPS_CONF7_WII)
-                       cpu_wait = r4k_wait_irqoff;
-               break;
-
-       case CPU_74K:
-               cpu_wait = r4k_wait;
-               if ((c->processor_id & 0xff) >= PRID_REV_ENCODE_332(2, 1, 0))
-                       cpu_wait = r4k_wait_irqoff;
-               break;
-
-       case CPU_TX49XX:
-               cpu_wait = r4k_wait_irqoff;
-               break;
-       case CPU_ALCHEMY:
-               cpu_wait = au1k_wait;
-               break;
-       case CPU_20KC:
-               /*
-                * WAIT on Rev1.0 has E1, E2, E3 and E16.
-                * WAIT on Rev2.0 and Rev3.0 has E16.
-                * Rev3.1 WAIT is nop, why bother
-                */
-               if ((c->processor_id & 0xff) <= 0x64)
-                       break;
-
-               /*
-                * Another rev is incremeting c0_count at a reduced clock
-                * rate while in WAIT mode.  So we basically have the choice
-                * between using the cp0 timer as clocksource or avoiding
-                * the WAIT instruction.  Until more details are known,
-                * disable the use of WAIT for 20Kc entirely.
-                  cpu_wait = r4k_wait;
-                */
-               break;
-       case CPU_RM9000:
-               if ((c->processor_id & 0x00ff) >= 0x40)
-                       cpu_wait = r4k_wait;
-               break;
-       default:
-               break;
-       }
-}
-
 static inline void check_errata(void)
 {
        struct cpuinfo_mips *c = &current_cpu_data;
index 35bed0d..3be9e7b 100644 (file)
@@ -2,6 +2,7 @@
 #include <linux/bootmem.h>
 #include <linux/crash_dump.h>
 #include <asm/uaccess.h>
+#include <linux/slab.h>
 
 static int __init parse_savemaxmem(char *p)
 {
index cf5509f..dba90ec 100644 (file)
 #define MCOUNT_OFFSET_INSNS 4
 #endif
 
+#ifdef CONFIG_DYNAMIC_FTRACE
+
 /* Arch override because MIPS doesn't need to run this from stop_machine() */
 void arch_ftrace_update_code(int command)
 {
        ftrace_modify_all_code(command);
 }
 
+#endif
+
 /*
  * Check if the address is in kernel space
  *
index 5c2ba9f..31fa856 100644 (file)
@@ -122,7 +122,7 @@ handle_vcei:
        __FINIT
 
        .align  5       /* 32 byte rollback region */
-LEAF(r4k_wait)
+LEAF(__r4k_wait)
        .set    push
        .set    noreorder
        /* start of rollback region */
@@ -146,14 +146,14 @@ LEAF(r4k_wait)
        jr      ra
        nop
        .set    pop
-       END(r4k_wait)
+       END(__r4k_wait)
 
        .macro  BUILD_ROLLBACK_PROLOGUE handler
        FEXPORT(rollback_\handler)
        .set    push
        .set    noat
        MFC0    k0, CP0_EPC
-       PTR_LA  k1, r4k_wait
+       PTR_LA  k1, __r4k_wait
        ori     k0, 0x1f        /* 32 byte rollback region */
        xori    k0, 0x1f
        bne     k0, k1, 9f
@@ -493,7 +493,7 @@ NESTED(nmi_handler, PT_SIZE, sp)
        .set    noreorder
        /* check if TLB contains a entry for EPC */
        MFC0    k1, CP0_ENTRYHI
-       andi    k1, 0xff        /* ASID_MASK patched at run-time!! */
+       andi    k1, 0xff        /* ASID_MASK */
        MFC0    k0, CP0_EPC
        PTR_SRL k0, _PAGE_SHIFT + 1
        PTR_SLL k0, _PAGE_SHIFT + 1
diff --git a/arch/mips/kernel/idle.c b/arch/mips/kernel/idle.c
new file mode 100644 (file)
index 0000000..0c655de
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ * MIPS idle loop and WAIT instruction support.
+ *
+ * Copyright (C) xxxx  the Anonymous
+ * Copyright (C) 1994 - 2006 Ralf Baechle
+ * Copyright (C) 2003, 2004  Maciej W. Rozycki
+ * Copyright (C) 2001, 2004, 2011, 2012         MIPS Technologies, 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/export.h>
+#include <linux/init.h>
+#include <linux/irqflags.h>
+#include <linux/printk.h>
+#include <linux/sched.h>
+#include <asm/cpu.h>
+#include <asm/cpu-info.h>
+#include <asm/idle.h>
+#include <asm/mipsregs.h>
+
+/*
+ * Not all of the MIPS CPUs have the "wait" instruction available. Moreover,
+ * the implementation of the "wait" feature differs between CPU families. This
+ * points to the function that implements CPU specific wait.
+ * The wait instruction stops the pipeline and reduces the power consumption of
+ * the CPU very much.
+ */
+void (*cpu_wait)(void);
+EXPORT_SYMBOL(cpu_wait);
+
+static void r3081_wait(void)
+{
+       unsigned long cfg = read_c0_conf();
+       write_c0_conf(cfg | R30XX_CONF_HALT);
+       local_irq_enable();
+}
+
+static void r39xx_wait(void)
+{
+       if (!need_resched())
+               write_c0_conf(read_c0_conf() | TX39_CONF_HALT);
+       local_irq_enable();
+}
+
+void r4k_wait(void)
+{
+       local_irq_enable();
+       __r4k_wait();
+}
+
+/*
+ * This variant is preferable as it allows testing need_resched and going to
+ * sleep depending on the outcome atomically.  Unfortunately the "It is
+ * implementation-dependent whether the pipeline restarts when a non-enabled
+ * interrupt is requested" restriction in the MIPS32/MIPS64 architecture makes
+ * using this version a gamble.
+ */
+void r4k_wait_irqoff(void)
+{
+       if (!need_resched())
+               __asm__(
+               "       .set    push            \n"
+               "       .set    mips3           \n"
+               "       wait                    \n"
+               "       .set    pop             \n");
+       local_irq_enable();
+       __asm__(
+       "       .globl __pastwait       \n"
+       "__pastwait:                    \n");
+}
+
+/*
+ * The RM7000 variant has to handle erratum 38.         The workaround is to not
+ * have any pending stores when the WAIT instruction is executed.
+ */
+static void rm7k_wait_irqoff(void)
+{
+       if (!need_resched())
+               __asm__(
+               "       .set    push                                    \n"
+               "       .set    mips3                                   \n"
+               "       .set    noat                                    \n"
+               "       mfc0    $1, $12                                 \n"
+               "       sync                                            \n"
+               "       mtc0    $1, $12         # stalls until W stage  \n"
+               "       wait                                            \n"
+               "       mtc0    $1, $12         # stalls until W stage  \n"
+               "       .set    pop                                     \n");
+       local_irq_enable();
+}
+
+/*
+ * Au1 'wait' is only useful when the 32kHz counter is used as timer,
+ * since coreclock (and the cp0 counter) stops upon executing it. Only an
+ * interrupt can wake it, so they must be enabled before entering idle modes.
+ */
+static void au1k_wait(void)
+{
+       unsigned long c0status = read_c0_status() | 1;  /* irqs on */
+
+       __asm__(
+       "       .set    mips3                   \n"
+       "       cache   0x14, 0(%0)             \n"
+       "       cache   0x14, 32(%0)            \n"
+       "       sync                            \n"
+       "       mtc0    %1, $12                 \n" /* wr c0status */
+       "       wait                            \n"
+       "       nop                             \n"
+       "       nop                             \n"
+       "       nop                             \n"
+       "       nop                             \n"
+       "       .set    mips0                   \n"
+       : : "r" (au1k_wait), "r" (c0status));
+}
+
+static int __initdata nowait;
+
+static int __init wait_disable(char *s)
+{
+       nowait = 1;
+
+       return 1;
+}
+
+__setup("nowait", wait_disable);
+
+void __init check_wait(void)
+{
+       struct cpuinfo_mips *c = &current_cpu_data;
+
+       if (nowait) {
+               printk("Wait instruction disabled.\n");
+               return;
+       }
+
+       switch (c->cputype) {
+       case CPU_R3081:
+       case CPU_R3081E:
+               cpu_wait = r3081_wait;
+               break;
+       case CPU_TX3927:
+               cpu_wait = r39xx_wait;
+               break;
+       case CPU_R4200:
+/*     case CPU_R4300: */
+       case CPU_R4600:
+       case CPU_R4640:
+       case CPU_R4650:
+       case CPU_R4700:
+       case CPU_R5000:
+       case CPU_R5500:
+       case CPU_NEVADA:
+       case CPU_4KC:
+       case CPU_4KEC:
+       case CPU_4KSC:
+       case CPU_5KC:
+       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:
+       case CPU_JZRISC:
+       case CPU_LOONGSON1:
+       case CPU_XLR:
+       case CPU_XLP:
+               cpu_wait = r4k_wait;
+               break;
+
+       case CPU_RM7000:
+               cpu_wait = rm7k_wait_irqoff;
+               break;
+
+       case CPU_M14KC:
+       case CPU_M14KEC:
+       case CPU_24K:
+       case CPU_34K:
+       case CPU_1004K:
+               cpu_wait = r4k_wait;
+               if (read_c0_config7() & MIPS_CONF7_WII)
+                       cpu_wait = r4k_wait_irqoff;
+               break;
+
+       case CPU_74K:
+               cpu_wait = r4k_wait;
+               if ((c->processor_id & 0xff) >= PRID_REV_ENCODE_332(2, 1, 0))
+                       cpu_wait = r4k_wait_irqoff;
+               break;
+
+       case CPU_TX49XX:
+               cpu_wait = r4k_wait_irqoff;
+               break;
+       case CPU_ALCHEMY:
+               cpu_wait = au1k_wait;
+               break;
+       case CPU_20KC:
+               /*
+                * WAIT on Rev1.0 has E1, E2, E3 and E16.
+                * WAIT on Rev2.0 and Rev3.0 has E16.
+                * Rev3.1 WAIT is nop, why bother
+                */
+               if ((c->processor_id & 0xff) <= 0x64)
+                       break;
+
+               /*
+                * Another rev is incremeting c0_count at a reduced clock
+                * rate while in WAIT mode.  So we basically have the choice
+                * between using the cp0 timer as clocksource or avoiding
+                * the WAIT instruction.  Until more details are known,
+                * disable the use of WAIT for 20Kc entirely.
+                  cpu_wait = r4k_wait;
+                */
+               break;
+       case CPU_RM9000:
+               if ((c->processor_id & 0x00ff) >= 0x40)
+                       cpu_wait = r4k_wait;
+               break;
+       default:
+               break;
+       }
+}
+
+static void smtc_idle_hook(void)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+       void smtc_idle_loop_hook(void);
+
+       smtc_idle_loop_hook();
+#endif
+}
+
+void arch_cpu_idle(void)
+{
+       smtc_idle_hook();
+       if (cpu_wait)
+               cpu_wait();
+       else
+               local_irq_enable();
+}
index 12bc4eb..1f8187a 100644 (file)
@@ -207,7 +207,10 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p)
 
 void __kprobes arch_remove_kprobe(struct kprobe *p)
 {
-       free_insn_slot(p->ainsn.insn, 0);
+       if (p->ainsn.insn) {
+               free_insn_slot(p->ainsn.insn, 0);
+               p->ainsn.insn = NULL;
+       }
 }
 
 static void save_previous_kprobe(struct kprobe_ctlblk *kcb)
index d1d576b..0b29646 100644 (file)
@@ -165,10 +165,3 @@ asmlinkage long sys32_fallocate(int fd, int mode, unsigned offset_a2,
        return sys_fallocate(fd, mode, merge_64(offset_a2, offset_a3),
                             merge_64(len_a4, len_a5));
 }
-
-SYSCALL_DEFINE6(32_fanotify_mark, int, fanotify_fd, unsigned int, flags,
-               u64, a3, u64, a4, int, dfd, const char  __user *, pathname)
-{
-       return sys_fanotify_mark(fanotify_fd, flags, merge_64(a3, a4),
-                                dfd, pathname);
-}
index a3e4614..acb3437 100644 (file)
@@ -10,6 +10,7 @@
 #include <asm/bootinfo.h>
 #include <asm/cpu.h>
 #include <asm/cpu-features.h>
+#include <asm/idle.h>
 #include <asm/mipsregs.h>
 #include <asm/processor.h>
 #include <asm/prom.h>
index eb902c1..c6a041d 100644 (file)
@@ -51,19 +51,6 @@ void arch_cpu_idle_dead(void)
 }
 #endif
 
-void arch_cpu_idle(void)
-{
-#ifdef CONFIG_MIPS_MT_SMTC
-       extern void smtc_idle_loop_hook(void);
-
-       smtc_idle_loop_hook();
-#endif
-       if (cpu_wait)
-               (*cpu_wait)();
-       else
-               local_irq_enable();
-}
-
 asmlinkage void ret_from_fork(void);
 asmlinkage void ret_from_kernel_thread(void);
 
@@ -224,6 +211,9 @@ struct mips_frame_info {
        int             pc_offset;
 };
 
+#define J_TARGET(pc,target)    \
+               (((unsigned long)(pc) & 0xf0000000) | ((target) << 2))
+
 static inline int is_ra_save_ins(union mips_instruction *ip)
 {
 #ifdef CONFIG_CPU_MICROMIPS
@@ -264,7 +254,7 @@ static inline int is_ra_save_ins(union mips_instruction *ip)
 #endif
 }
 
-static inline int is_jal_jalr_jr_ins(union mips_instruction *ip)
+static inline int is_jump_ins(union mips_instruction *ip)
 {
 #ifdef CONFIG_CPU_MICROMIPS
        /*
@@ -288,6 +278,8 @@ static inline int is_jal_jalr_jr_ins(union mips_instruction *ip)
                return 0;
        return (((ip->u_format.uimmediate >> 6) & mm_jalr_op) == mm_jalr_op);
 #else
+       if (ip->j_format.opcode == j_op)
+               return 1;
        if (ip->j_format.opcode == jal_op)
                return 1;
        if (ip->r_format.opcode != spec_op)
@@ -350,7 +342,7 @@ static int get_frame_info(struct mips_frame_info *info)
 
        for (i = 0; i < max_insns; i++, ip++) {
 
-               if (is_jal_jalr_jr_ins(ip))
+               if (is_jump_ins(ip))
                        break;
                if (!info->frame_size) {
                        if (is_sp_move_ins(ip))
@@ -393,15 +385,42 @@ err:
 
 static struct mips_frame_info schedule_mfi __read_mostly;
 
+#ifdef CONFIG_KALLSYMS
+static unsigned long get___schedule_addr(void)
+{
+       return kallsyms_lookup_name("__schedule");
+}
+#else
+static unsigned long get___schedule_addr(void)
+{
+       union mips_instruction *ip = (void *)schedule;
+       int max_insns = 8;
+       int i;
+
+       for (i = 0; i < max_insns; i++, ip++) {
+               if (ip->j_format.opcode == j_op)
+                       return J_TARGET(ip, ip->j_format.target);
+       }
+       return 0;
+}
+#endif
+
 static int __init frame_info_init(void)
 {
        unsigned long size = 0;
 #ifdef CONFIG_KALLSYMS
        unsigned long ofs;
+#endif
+       unsigned long addr;
+
+       addr = get___schedule_addr();
+       if (!addr)
+               addr = (unsigned long)schedule;
 
-       kallsyms_lookup_size_offset((unsigned long)schedule, &size, &ofs);
+#ifdef CONFIG_KALLSYMS
+       kallsyms_lookup_size_offset(addr, &size, &ofs);
 #endif
-       schedule_mfi.func = schedule;
+       schedule_mfi.func = (void *)addr;
        schedule_mfi.func_size = size;
 
        get_frame_info(&schedule_mfi);
index 93c070b..6fa198d 100644 (file)
@@ -40,6 +40,7 @@
 #include <asm/processor.h>
 #include <asm/vpe.h>
 #include <asm/rtlx.h>
+#include <asm/setup.h>
 
 static struct rtlx_info *rtlx;
 static int major;
index 36cfd40..97a5909 100644 (file)
@@ -423,4 +423,5 @@ sys_call_table:
        PTR     sys_process_vm_writev           /* 5305 */
        PTR     sys_kcmp
        PTR     sys_finit_module
+       PTR     sys_getdents64
        .size   sys_call_table,.-sys_call_table
index 103bfe5..74f485d 100644 (file)
@@ -529,7 +529,7 @@ sys_call_table:
        PTR     sys_accept4
        PTR     compat_sys_recvmmsg             /* 4335 */
        PTR     sys_fanotify_init
-       PTR     sys_32_fanotify_mark
+       PTR     compat_sys_fanotify_mark
        PTR     sys_prlimit64
        PTR     sys_name_to_handle_at
        PTR     compat_sys_open_by_handle_at    /* 4340 */
index c17619f..6e7862a 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/atomic.h>
 #include <asm/cpu.h>
 #include <asm/processor.h>
+#include <asm/idle.h>
 #include <asm/r4k-timer.h>
 #include <asm/mmu_context.h>
 #include <asm/time.h>
index 31d22f3..75a4fd7 100644 (file)
@@ -34,6 +34,7 @@
 #include <asm/hardirq.h>
 #include <asm/hazards.h>
 #include <asm/irq.h>
+#include <asm/idle.h>
 #include <asm/mmu_context.h>
 #include <asm/mipsregs.h>
 #include <asm/cacheflush.h>
@@ -111,7 +112,7 @@ static int vpe0limit;
 static int ipibuffers;
 static int nostlb;
 static int asidmask;
-unsigned int smtc_asid_mask = 0xff;
+unsigned long smtc_asid_mask = 0xff;
 
 static int __init vpe0tcs(char *str)
 {
@@ -858,7 +859,6 @@ void smtc_send_ipi(int cpu, int type, unsigned int action)
        unsigned long flags;
        int mtflags;
        unsigned long tcrestart;
-       extern void r4k_wait_irqoff(void), __pastwait(void);
        int set_resched_flag = (type == LINUX_SMP_IPI &&
                                action == SMP_RESCHEDULE_YOURSELF);
 
@@ -914,8 +914,7 @@ void smtc_send_ipi(int cpu, int type, unsigned int action)
                         */
                        if (cpu_wait == r4k_wait_irqoff) {
                                tcrestart = read_tc_c0_tcrestart();
-                               if (tcrestart >= (unsigned long)r4k_wait_irqoff
-                                   && tcrestart < (unsigned long)__pastwait) {
+                               if (address_is_in_r4k_wait_irqoff(tcrestart)) {
                                        write_tc_c0_tcrestart(__pastwait);
                                        tcstatus &= ~TCSTATUS_IXMT;
                                        write_tc_c0_tcstatus(tcstatus);
@@ -1395,7 +1394,7 @@ void smtc_get_new_mmu_context(struct mm_struct *mm, unsigned long cpu)
        asid = asid_cache(cpu);
 
        do {
-               if (!ASID_MASK(ASID_INC(asid))) {
+               if (!((asid += ASID_INC) & ASID_MASK) ) {
                        if (cpu_has_vtag_icache)
                                flush_icache_all();
                        /* Traverse all online CPUs (hack requires contiguous range) */
@@ -1414,7 +1413,7 @@ void smtc_get_new_mmu_context(struct mm_struct *mm, unsigned long cpu)
                                                mips_ihb();
                                        }
                                        tcstat = read_tc_c0_tcstatus();
-                                       smtc_live_asid[tlb][ASID_MASK(tcstat)] |= (asiduse)(0x1 << i);
+                                       smtc_live_asid[tlb][(tcstat & ASID_MASK)] |= (asiduse)(0x1 << i);
                                        if (!prevhalt)
                                                write_tc_c0_tchalt(0);
                                }
@@ -1423,7 +1422,7 @@ void smtc_get_new_mmu_context(struct mm_struct *mm, unsigned long cpu)
                                asid = ASID_FIRST_VERSION;
                        local_flush_tlb_all();  /* start new asid cycle */
                }
-       } while (smtc_live_asid[tlb][ASID_MASK(asid)]);
+       } while (smtc_live_asid[tlb][(asid & ASID_MASK)]);
 
        /*
         * SMTC shares the TLB within VPEs and possibly across all VPEs.
@@ -1461,7 +1460,7 @@ void smtc_flush_tlb_asid(unsigned long asid)
                tlb_read();
                ehb();
                ehi = read_c0_entryhi();
-               if (ASID_MASK(ehi) == asid) {
+               if ((ehi & ASID_MASK) == asid) {
                    /*
                     * Invalidate only entries with specified ASID,
                     * makiing sure all entries differ.
index 77cff1f..a75ae40 100644 (file)
@@ -41,6 +41,7 @@
 #include <asm/dsp.h>
 #include <asm/fpu.h>
 #include <asm/fpu_emulator.h>
+#include <asm/idle.h>
 #include <asm/mipsregs.h>
 #include <asm/mipsmtregs.h>
 #include <asm/module.h>
@@ -57,7 +58,6 @@
 #include <asm/uasm.h>
 
 extern void check_wait(void);
-extern asmlinkage void r4k_wait(void);
 extern asmlinkage void rollback_handle_int(void);
 extern asmlinkage void handle_int(void);
 extern u32 handle_tlbl[];
@@ -897,22 +897,24 @@ out_sigsegv:
 
 asmlinkage void do_tr(struct pt_regs *regs)
 {
-       unsigned int opcode, tcode = 0;
+       u32 opcode, tcode = 0;
        u16 instr[2];
-       unsigned long epc = exception_epc(regs);
+       unsigned long epc = msk_isa16_mode(exception_epc(regs));
 
-       if ((__get_user(instr[0], (u16 __user *)msk_isa16_mode(epc))) ||
-               (__get_user(instr[1], (u16 __user *)msk_isa16_mode(epc + 2))))
+       if (get_isa16_mode(regs->cp0_epc)) {
+               if (__get_user(instr[0], (u16 __user *)(epc + 0)) ||
+                   __get_user(instr[1], (u16 __user *)(epc + 2)))
                        goto out_sigsegv;
-       opcode = (instr[0] << 16) | instr[1];
-
-       /* Immediate versions don't provide a code.  */
-       if (!(opcode & OPCODE)) {
-               if (get_isa16_mode(regs->cp0_epc))
-                       /* microMIPS */
-                       tcode = (opcode >> 12) & 0x1f;
-               else
-                       tcode = ((opcode >> 6) & ((1 << 10) - 1));
+               opcode = (instr[0] << 16) | instr[1];
+               /* Immediate versions don't provide a code.  */
+               if (!(opcode & OPCODE))
+                       tcode = (opcode >> 12) & ((1 << 4) - 1);
+       } else {
+               if (__get_user(opcode, (u32 __user *)epc))
+                       goto out_sigsegv;
+               /* Immediate versions don't provide a code.  */
+               if (!(opcode & OPCODE))
+                       tcode = (opcode >> 6) & ((1 << 10) - 1);
        }
 
        do_trap_or_bp(regs, tcode, "Trap");
@@ -1542,7 +1544,7 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs)
                extern char except_vec_vi, except_vec_vi_lui;
                extern char except_vec_vi_ori, except_vec_vi_end;
                extern char rollback_except_vec_vi;
-               char *vec_start = (cpu_wait == r4k_wait) ?
+               char *vec_start = using_rollback_handler() ?
                        &rollback_except_vec_vi : &except_vec_vi;
 #ifdef CONFIG_MIPS_MT_SMTC
                /*
@@ -1656,7 +1658,6 @@ void __cpuinit per_cpu_trap_init(bool is_boot_cpu)
        unsigned int cpu = smp_processor_id();
        unsigned int status_set = ST0_CU0;
        unsigned int hwrena = cpu_hwrena_impl_bits;
-       unsigned long asid = 0;
 #ifdef CONFIG_MIPS_MT_SMTC
        int secondaryTC = 0;
        int bootTC = (cpu == 0);
@@ -1740,9 +1741,8 @@ void __cpuinit per_cpu_trap_init(bool is_boot_cpu)
        }
 #endif /* CONFIG_MIPS_MT_SMTC */
 
-       asid = ASID_FIRST_VERSION;
-       cpu_data[cpu].asid_cache = asid;
-       TLBMISS_HANDLER_SETUP();
+       if (!cpu_data[cpu].asid_cache)
+               cpu_data[cpu].asid_cache = ASID_FIRST_VERSION;
 
        atomic_inc(&init_mm.mm_count);
        current->active_mm = &init_mm;
@@ -1814,10 +1814,8 @@ void __init trap_init(void)
        extern char except_vec4;
        extern char except_vec3_r4000;
        unsigned long i;
-       int rollback;
 
        check_wait();
-       rollback = (cpu_wait == r4k_wait);
 
 #if defined(CONFIG_KGDB)
        if (kgdb_early_setup)
@@ -1894,7 +1892,8 @@ void __init trap_init(void)
        if (board_be_init)
                board_be_init();
 
-       set_except_vector(0, rollback ? rollback_handle_int : handle_int);
+       set_except_vector(0, using_rollback_handler() ? rollback_handle_int
+                                                     : handle_int);
        set_except_vector(1, handle_tlbm);
        set_except_vector(2, handle_tlbl);
        set_except_vector(3, handle_tlbs);
index e0dad02..dd203e5 100644 (file)
@@ -195,7 +195,7 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
 long
 kvm_arch_dev_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
 {
-       return -EINVAL;
+       return -ENOIOCTLCMD;
 }
 
 void kvm_arch_free_memslot(struct kvm_memory_slot *free,
@@ -401,7 +401,7 @@ int
 kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
                                    struct kvm_guest_debug *dbg)
 {
-       return -EINVAL;
+       return -ENOIOCTLCMD;
 }
 
 int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
@@ -475,14 +475,248 @@ int
 kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
                                struct kvm_mp_state *mp_state)
 {
-       return -EINVAL;
+       return -ENOIOCTLCMD;
 }
 
 int
 kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
                                struct kvm_mp_state *mp_state)
 {
-       return -EINVAL;
+       return -ENOIOCTLCMD;
+}
+
+#define MIPS_CP0_32(_R, _S)                                    \
+       (KVM_REG_MIPS | KVM_REG_SIZE_U32 | 0x10000 | (8 * (_R) + (_S)))
+
+#define MIPS_CP0_64(_R, _S)                                    \
+       (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 0x10000 | (8 * (_R) + (_S)))
+
+#define KVM_REG_MIPS_CP0_INDEX         MIPS_CP0_32(0, 0)
+#define KVM_REG_MIPS_CP0_ENTRYLO0      MIPS_CP0_64(2, 0)
+#define KVM_REG_MIPS_CP0_ENTRYLO1      MIPS_CP0_64(3, 0)
+#define KVM_REG_MIPS_CP0_CONTEXT       MIPS_CP0_64(4, 0)
+#define KVM_REG_MIPS_CP0_USERLOCAL     MIPS_CP0_64(4, 2)
+#define KVM_REG_MIPS_CP0_PAGEMASK      MIPS_CP0_32(5, 0)
+#define KVM_REG_MIPS_CP0_PAGEGRAIN     MIPS_CP0_32(5, 1)
+#define KVM_REG_MIPS_CP0_WIRED         MIPS_CP0_32(6, 0)
+#define KVM_REG_MIPS_CP0_HWRENA                MIPS_CP0_32(7, 0)
+#define KVM_REG_MIPS_CP0_BADVADDR      MIPS_CP0_64(8, 0)
+#define KVM_REG_MIPS_CP0_COUNT         MIPS_CP0_32(9, 0)
+#define KVM_REG_MIPS_CP0_ENTRYHI       MIPS_CP0_64(10, 0)
+#define KVM_REG_MIPS_CP0_COMPARE       MIPS_CP0_32(11, 0)
+#define KVM_REG_MIPS_CP0_STATUS                MIPS_CP0_32(12, 0)
+#define KVM_REG_MIPS_CP0_CAUSE         MIPS_CP0_32(13, 0)
+#define KVM_REG_MIPS_CP0_EBASE         MIPS_CP0_64(15, 1)
+#define KVM_REG_MIPS_CP0_CONFIG                MIPS_CP0_32(16, 0)
+#define KVM_REG_MIPS_CP0_CONFIG1       MIPS_CP0_32(16, 1)
+#define KVM_REG_MIPS_CP0_CONFIG2       MIPS_CP0_32(16, 2)
+#define KVM_REG_MIPS_CP0_CONFIG3       MIPS_CP0_32(16, 3)
+#define KVM_REG_MIPS_CP0_CONFIG7       MIPS_CP0_32(16, 7)
+#define KVM_REG_MIPS_CP0_XCONTEXT      MIPS_CP0_64(20, 0)
+#define KVM_REG_MIPS_CP0_ERROREPC      MIPS_CP0_64(30, 0)
+
+static u64 kvm_mips_get_one_regs[] = {
+       KVM_REG_MIPS_R0,
+       KVM_REG_MIPS_R1,
+       KVM_REG_MIPS_R2,
+       KVM_REG_MIPS_R3,
+       KVM_REG_MIPS_R4,
+       KVM_REG_MIPS_R5,
+       KVM_REG_MIPS_R6,
+       KVM_REG_MIPS_R7,
+       KVM_REG_MIPS_R8,
+       KVM_REG_MIPS_R9,
+       KVM_REG_MIPS_R10,
+       KVM_REG_MIPS_R11,
+       KVM_REG_MIPS_R12,
+       KVM_REG_MIPS_R13,
+       KVM_REG_MIPS_R14,
+       KVM_REG_MIPS_R15,
+       KVM_REG_MIPS_R16,
+       KVM_REG_MIPS_R17,
+       KVM_REG_MIPS_R18,
+       KVM_REG_MIPS_R19,
+       KVM_REG_MIPS_R20,
+       KVM_REG_MIPS_R21,
+       KVM_REG_MIPS_R22,
+       KVM_REG_MIPS_R23,
+       KVM_REG_MIPS_R24,
+       KVM_REG_MIPS_R25,
+       KVM_REG_MIPS_R26,
+       KVM_REG_MIPS_R27,
+       KVM_REG_MIPS_R28,
+       KVM_REG_MIPS_R29,
+       KVM_REG_MIPS_R30,
+       KVM_REG_MIPS_R31,
+
+       KVM_REG_MIPS_HI,
+       KVM_REG_MIPS_LO,
+       KVM_REG_MIPS_PC,
+
+       KVM_REG_MIPS_CP0_INDEX,
+       KVM_REG_MIPS_CP0_CONTEXT,
+       KVM_REG_MIPS_CP0_PAGEMASK,
+       KVM_REG_MIPS_CP0_WIRED,
+       KVM_REG_MIPS_CP0_BADVADDR,
+       KVM_REG_MIPS_CP0_ENTRYHI,
+       KVM_REG_MIPS_CP0_STATUS,
+       KVM_REG_MIPS_CP0_CAUSE,
+       /* EPC set via kvm_regs, et al. */
+       KVM_REG_MIPS_CP0_CONFIG,
+       KVM_REG_MIPS_CP0_CONFIG1,
+       KVM_REG_MIPS_CP0_CONFIG2,
+       KVM_REG_MIPS_CP0_CONFIG3,
+       KVM_REG_MIPS_CP0_CONFIG7,
+       KVM_REG_MIPS_CP0_ERROREPC
+};
+
+static int kvm_mips_get_reg(struct kvm_vcpu *vcpu,
+                           const struct kvm_one_reg *reg)
+{
+       struct mips_coproc *cop0 = vcpu->arch.cop0;
+       s64 v;
+
+       switch (reg->id) {
+       case KVM_REG_MIPS_R0 ... KVM_REG_MIPS_R31:
+               v = (long)vcpu->arch.gprs[reg->id - KVM_REG_MIPS_R0];
+               break;
+       case KVM_REG_MIPS_HI:
+               v = (long)vcpu->arch.hi;
+               break;
+       case KVM_REG_MIPS_LO:
+               v = (long)vcpu->arch.lo;
+               break;
+       case KVM_REG_MIPS_PC:
+               v = (long)vcpu->arch.pc;
+               break;
+
+       case KVM_REG_MIPS_CP0_INDEX:
+               v = (long)kvm_read_c0_guest_index(cop0);
+               break;
+       case KVM_REG_MIPS_CP0_CONTEXT:
+               v = (long)kvm_read_c0_guest_context(cop0);
+               break;
+       case KVM_REG_MIPS_CP0_PAGEMASK:
+               v = (long)kvm_read_c0_guest_pagemask(cop0);
+               break;
+       case KVM_REG_MIPS_CP0_WIRED:
+               v = (long)kvm_read_c0_guest_wired(cop0);
+               break;
+       case KVM_REG_MIPS_CP0_BADVADDR:
+               v = (long)kvm_read_c0_guest_badvaddr(cop0);
+               break;
+       case KVM_REG_MIPS_CP0_ENTRYHI:
+               v = (long)kvm_read_c0_guest_entryhi(cop0);
+               break;
+       case KVM_REG_MIPS_CP0_STATUS:
+               v = (long)kvm_read_c0_guest_status(cop0);
+               break;
+       case KVM_REG_MIPS_CP0_CAUSE:
+               v = (long)kvm_read_c0_guest_cause(cop0);
+               break;
+       case KVM_REG_MIPS_CP0_ERROREPC:
+               v = (long)kvm_read_c0_guest_errorepc(cop0);
+               break;
+       case KVM_REG_MIPS_CP0_CONFIG:
+               v = (long)kvm_read_c0_guest_config(cop0);
+               break;
+       case KVM_REG_MIPS_CP0_CONFIG1:
+               v = (long)kvm_read_c0_guest_config1(cop0);
+               break;
+       case KVM_REG_MIPS_CP0_CONFIG2:
+               v = (long)kvm_read_c0_guest_config2(cop0);
+               break;
+       case KVM_REG_MIPS_CP0_CONFIG3:
+               v = (long)kvm_read_c0_guest_config3(cop0);
+               break;
+       case KVM_REG_MIPS_CP0_CONFIG7:
+               v = (long)kvm_read_c0_guest_config7(cop0);
+               break;
+       default:
+               return -EINVAL;
+       }
+       if ((reg->id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U64) {
+               u64 __user *uaddr64 = (u64 __user *)(long)reg->addr;
+               return put_user(v, uaddr64);
+       } else if ((reg->id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U32) {
+               u32 __user *uaddr32 = (u32 __user *)(long)reg->addr;
+               u32 v32 = (u32)v;
+               return put_user(v32, uaddr32);
+       } else {
+               return -EINVAL;
+       }
+}
+
+static int kvm_mips_set_reg(struct kvm_vcpu *vcpu,
+                           const struct kvm_one_reg *reg)
+{
+       struct mips_coproc *cop0 = vcpu->arch.cop0;
+       u64 v;
+
+       if ((reg->id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U64) {
+               u64 __user *uaddr64 = (u64 __user *)(long)reg->addr;
+
+               if (get_user(v, uaddr64) != 0)
+                       return -EFAULT;
+       } else if ((reg->id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U32) {
+               u32 __user *uaddr32 = (u32 __user *)(long)reg->addr;
+               s32 v32;
+
+               if (get_user(v32, uaddr32) != 0)
+                       return -EFAULT;
+               v = (s64)v32;
+       } else {
+               return -EINVAL;
+       }
+
+       switch (reg->id) {
+       case KVM_REG_MIPS_R0:
+               /* Silently ignore requests to set $0 */
+               break;
+       case KVM_REG_MIPS_R1 ... KVM_REG_MIPS_R31:
+               vcpu->arch.gprs[reg->id - KVM_REG_MIPS_R0] = v;
+               break;
+       case KVM_REG_MIPS_HI:
+               vcpu->arch.hi = v;
+               break;
+       case KVM_REG_MIPS_LO:
+               vcpu->arch.lo = v;
+               break;
+       case KVM_REG_MIPS_PC:
+               vcpu->arch.pc = v;
+               break;
+
+       case KVM_REG_MIPS_CP0_INDEX:
+               kvm_write_c0_guest_index(cop0, v);
+               break;
+       case KVM_REG_MIPS_CP0_CONTEXT:
+               kvm_write_c0_guest_context(cop0, v);
+               break;
+       case KVM_REG_MIPS_CP0_PAGEMASK:
+               kvm_write_c0_guest_pagemask(cop0, v);
+               break;
+       case KVM_REG_MIPS_CP0_WIRED:
+               kvm_write_c0_guest_wired(cop0, v);
+               break;
+       case KVM_REG_MIPS_CP0_BADVADDR:
+               kvm_write_c0_guest_badvaddr(cop0, v);
+               break;
+       case KVM_REG_MIPS_CP0_ENTRYHI:
+               kvm_write_c0_guest_entryhi(cop0, v);
+               break;
+       case KVM_REG_MIPS_CP0_STATUS:
+               kvm_write_c0_guest_status(cop0, v);
+               break;
+       case KVM_REG_MIPS_CP0_CAUSE:
+               kvm_write_c0_guest_cause(cop0, v);
+               break;
+       case KVM_REG_MIPS_CP0_ERROREPC:
+               kvm_write_c0_guest_errorepc(cop0, v);
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
 }
 
 long
@@ -491,9 +725,38 @@ kvm_arch_vcpu_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
        struct kvm_vcpu *vcpu = filp->private_data;
        void __user *argp = (void __user *)arg;
        long r;
-       int intr;
 
        switch (ioctl) {
+       case KVM_SET_ONE_REG:
+       case KVM_GET_ONE_REG: {
+               struct kvm_one_reg reg;
+               if (copy_from_user(&reg, argp, sizeof(reg)))
+                       return -EFAULT;
+               if (ioctl == KVM_SET_ONE_REG)
+                       return kvm_mips_set_reg(vcpu, &reg);
+               else
+                       return kvm_mips_get_reg(vcpu, &reg);
+       }
+       case KVM_GET_REG_LIST: {
+               struct kvm_reg_list __user *user_list = argp;
+               u64 __user *reg_dest;
+               struct kvm_reg_list reg_list;
+               unsigned n;
+
+               if (copy_from_user(&reg_list, user_list, sizeof(reg_list)))
+                       return -EFAULT;
+               n = reg_list.n;
+               reg_list.n = ARRAY_SIZE(kvm_mips_get_one_regs);
+               if (copy_to_user(user_list, &reg_list, sizeof(reg_list)))
+                       return -EFAULT;
+               if (n < reg_list.n)
+                       return -E2BIG;
+               reg_dest = user_list->reg;
+               if (copy_to_user(reg_dest, kvm_mips_get_one_regs,
+                                sizeof(kvm_mips_get_one_regs)))
+                       return -EFAULT;
+               return 0;
+       }
        case KVM_NMI:
                /* Treat the NMI as a CPU reset */
                r = kvm_mips_reset_vcpu(vcpu);
@@ -505,8 +768,6 @@ kvm_arch_vcpu_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
                        if (copy_from_user(&irq, argp, sizeof(irq)))
                                goto out;
 
-                       intr = (int)irq.irq;
-
                        kvm_debug("[%d] %s: irq: %d\n", vcpu->vcpu_id, __func__,
                                  irq.irq);
 
@@ -514,7 +775,7 @@ kvm_arch_vcpu_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
                        break;
                }
        default:
-               r = -EINVAL;
+               r = -ENOIOCTLCMD;
        }
 
 out:
@@ -565,7 +826,7 @@ long kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
 
        switch (ioctl) {
        default:
-               r = -EINVAL;
+               r = -ENOIOCTLCMD;
        }
 
        return r;
@@ -593,13 +854,13 @@ void kvm_arch_exit(void)
 int
 kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs)
 {
-       return -ENOTSUPP;
+       return -ENOIOCTLCMD;
 }
 
 int
 kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs)
 {
-       return -ENOTSUPP;
+       return -ENOIOCTLCMD;
 }
 
 int kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
@@ -609,12 +870,12 @@ int kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
 
 int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
 {
-       return -ENOTSUPP;
+       return -ENOIOCTLCMD;
 }
 
 int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
 {
-       return -ENOTSUPP;
+       return -ENOIOCTLCMD;
 }
 
 int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf)
@@ -627,6 +888,9 @@ int kvm_dev_ioctl_check_extension(long ext)
        int r;
 
        switch (ext) {
+       case KVM_CAP_ONE_REG:
+               r = 1;
+               break;
        case KVM_CAP_COALESCED_MMIO:
                r = KVM_COALESCED_MMIO_PAGE_OFFSET;
                break;
@@ -635,7 +899,6 @@ int kvm_dev_ioctl_check_extension(long ext)
                break;
        }
        return r;
-
 }
 
 int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
@@ -677,28 +940,28 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
 {
        int i;
 
-       for (i = 0; i < 32; i++)
-               vcpu->arch.gprs[i] = regs->gprs[i];
-
+       for (i = 1; i < ARRAY_SIZE(vcpu->arch.gprs); i++)
+               vcpu->arch.gprs[i] = regs->gpr[i];
+       vcpu->arch.gprs[0] = 0; /* zero is special, and cannot be set. */
        vcpu->arch.hi = regs->hi;
        vcpu->arch.lo = regs->lo;
        vcpu->arch.pc = regs->pc;
 
-       return kvm_mips_callbacks->vcpu_ioctl_set_regs(vcpu, regs);
+       return 0;
 }
 
 int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
 {
        int i;
 
-       for (i = 0; i < 32; i++)
-               regs->gprs[i] = vcpu->arch.gprs[i];
+       for (i = 0; i < ARRAY_SIZE(vcpu->arch.gprs); i++)
+               regs->gpr[i] = vcpu->arch.gprs[i];
 
        regs->hi = vcpu->arch.hi;
        regs->lo = vcpu->arch.lo;
        regs->pc = vcpu->arch.pc;
 
-       return kvm_mips_callbacks->vcpu_ioctl_get_regs(vcpu, regs);
+       return 0;
 }
 
 void kvm_mips_comparecount_func(unsigned long data)
index 2b2bac9..4b6274b 100644 (file)
@@ -525,16 +525,18 @@ kvm_mips_emulate_CP0(uint32_t inst, uint32_t *opc, uint32_t cause,
                                printk("MTCz, cop0->reg[EBASE]: %#lx\n",
                                       kvm_read_c0_guest_ebase(cop0));
                        } else if (rd == MIPS_CP0_TLB_HI && sel == 0) {
-                               uint32_t nasid = ASID_MASK(vcpu->arch.gprs[rt]);
+                               uint32_t nasid =
+                                   vcpu->arch.gprs[rt] & ASID_MASK;
                                if ((KSEGX(vcpu->arch.gprs[rt]) != CKSEG0)
                                    &&
-                                   (ASID_MASK(kvm_read_c0_guest_entryhi(cop0))
-                                     != nasid)) {
+                                   ((kvm_read_c0_guest_entryhi(cop0) &
+                                     ASID_MASK) != nasid)) {
 
                                        kvm_debug
                                            ("MTCz, change ASID from %#lx to %#lx\n",
-                                            ASID_MASK(kvm_read_c0_guest_entryhi(cop0)),
-                                            ASID_MASK(vcpu->arch.gprs[rt]));
+                                            kvm_read_c0_guest_entryhi(cop0) &
+                                            ASID_MASK,
+                                            vcpu->arch.gprs[rt] & ASID_MASK);
 
                                        /* Blow away the shadow host TLBs */
                                        kvm_mips_flush_host_tlb(1);
@@ -986,7 +988,8 @@ kvm_mips_emulate_cache(uint32_t inst, uint32_t *opc, uint32_t cause,
                 * resulting handler will do the right thing
                 */
                index = kvm_mips_guest_tlb_lookup(vcpu, (va & VPN2_MASK) |
-                                                 ASID_MASK(kvm_read_c0_guest_entryhi(cop0)));
+                                                 (kvm_read_c0_guest_entryhi
+                                                  (cop0) & ASID_MASK));
 
                if (index < 0) {
                        vcpu->arch.host_cp0_entryhi = (va & VPN2_MASK);
@@ -1151,7 +1154,7 @@ kvm_mips_emulate_tlbmiss_ld(unsigned long cause, uint32_t *opc,
        struct kvm_vcpu_arch *arch = &vcpu->arch;
        enum emulation_result er = EMULATE_DONE;
        unsigned long entryhi = (vcpu->arch.  host_cp0_badvaddr & VPN2_MASK) |
-                               ASID_MASK(kvm_read_c0_guest_entryhi(cop0));
+                               (kvm_read_c0_guest_entryhi(cop0) & ASID_MASK);
 
        if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
                /* save old pc */
@@ -1198,7 +1201,7 @@ kvm_mips_emulate_tlbinv_ld(unsigned long cause, uint32_t *opc,
        enum emulation_result er = EMULATE_DONE;
        unsigned long entryhi =
                (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) |
-               ASID_MASK(kvm_read_c0_guest_entryhi(cop0));
+               (kvm_read_c0_guest_entryhi(cop0) & ASID_MASK);
 
        if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
                /* save old pc */
@@ -1243,7 +1246,7 @@ kvm_mips_emulate_tlbmiss_st(unsigned long cause, uint32_t *opc,
        struct kvm_vcpu_arch *arch = &vcpu->arch;
        enum emulation_result er = EMULATE_DONE;
        unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) |
-                               ASID_MASK(kvm_read_c0_guest_entryhi(cop0));
+                               (kvm_read_c0_guest_entryhi(cop0) & ASID_MASK);
 
        if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
                /* save old pc */
@@ -1287,7 +1290,7 @@ kvm_mips_emulate_tlbinv_st(unsigned long cause, uint32_t *opc,
        struct kvm_vcpu_arch *arch = &vcpu->arch;
        enum emulation_result er = EMULATE_DONE;
        unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) |
-               ASID_MASK(kvm_read_c0_guest_entryhi(cop0));
+               (kvm_read_c0_guest_entryhi(cop0) & ASID_MASK);
 
        if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
                /* save old pc */
@@ -1356,7 +1359,7 @@ kvm_mips_emulate_tlbmod(unsigned long cause, uint32_t *opc,
 {
        struct mips_coproc *cop0 = vcpu->arch.cop0;
        unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) |
-                               ASID_MASK(kvm_read_c0_guest_entryhi(cop0));
+                               (kvm_read_c0_guest_entryhi(cop0) & ASID_MASK);
        struct kvm_vcpu_arch *arch = &vcpu->arch;
        enum emulation_result er = EMULATE_DONE;
 
@@ -1783,8 +1786,8 @@ kvm_mips_handle_tlbmiss(unsigned long cause, uint32_t *opc,
         */
        index = kvm_mips_guest_tlb_lookup(vcpu,
                                          (va & VPN2_MASK) |
-                                         ASID_MASK(kvm_read_c0_guest_entryhi
-                                          (vcpu->arch.cop0)));
+                                         (kvm_read_c0_guest_entryhi
+                                          (vcpu->arch.cop0) & ASID_MASK));
        if (index < 0) {
                if (exccode == T_TLB_LD_MISS) {
                        er = kvm_mips_emulate_tlbmiss_ld(cause, opc, run, vcpu);
index 89511a9..c777dd3 100644 (file)
@@ -17,6 +17,8 @@
 #include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/kvm_host.h>
+#include <linux/srcu.h>
+
 
 #include <asm/cpu.h>
 #include <asm/bootinfo.h>
@@ -51,13 +53,13 @@ EXPORT_SYMBOL(kvm_mips_is_error_pfn);
 
 uint32_t kvm_mips_get_kernel_asid(struct kvm_vcpu *vcpu)
 {
-       return ASID_MASK(vcpu->arch.guest_kernel_asid[smp_processor_id()]);
+       return vcpu->arch.guest_kernel_asid[smp_processor_id()] & ASID_MASK;
 }
 
 
 uint32_t kvm_mips_get_user_asid(struct kvm_vcpu *vcpu)
 {
-       return ASID_MASK(vcpu->arch.guest_user_asid[smp_processor_id()]);
+       return vcpu->arch.guest_user_asid[smp_processor_id()] & ASID_MASK;
 }
 
 inline uint32_t kvm_mips_get_commpage_asid (struct kvm_vcpu *vcpu)
@@ -84,7 +86,7 @@ void kvm_mips_dump_host_tlbs(void)
        old_pagemask = read_c0_pagemask();
 
        printk("HOST TLBs:\n");
-       printk("ASID: %#lx\n", ASID_MASK(read_c0_entryhi()));
+       printk("ASID: %#lx\n", read_c0_entryhi() & ASID_MASK);
 
        for (i = 0; i < current_cpu_data.tlbsize; i++) {
                write_c0_index(i);
@@ -169,21 +171,27 @@ void kvm_mips_dump_shadow_tlbs(struct kvm_vcpu *vcpu)
        }
 }
 
-static void kvm_mips_map_page(struct kvm *kvm, gfn_t gfn)
+static int kvm_mips_map_page(struct kvm *kvm, gfn_t gfn)
 {
+       int srcu_idx, err = 0;
        pfn_t pfn;
 
        if (kvm->arch.guest_pmap[gfn] != KVM_INVALID_PAGE)
-               return;
+               return 0;
 
+        srcu_idx = srcu_read_lock(&kvm->srcu);
        pfn = kvm_mips_gfn_to_pfn(kvm, gfn);
 
        if (kvm_mips_is_error_pfn(pfn)) {
-               panic("Couldn't get pfn for gfn %#" PRIx64 "!\n", gfn);
+               kvm_err("Couldn't get pfn for gfn %#" PRIx64 "!\n", gfn);
+               err = -EFAULT;
+               goto out;
        }
 
        kvm->arch.guest_pmap[gfn] = pfn;
-       return;
+out:
+       srcu_read_unlock(&kvm->srcu, srcu_idx);
+       return err;
 }
 
 /* Translate guest KSEG0 addresses to Host PA */
@@ -207,7 +215,10 @@ unsigned long kvm_mips_translate_guest_kseg0_to_hpa(struct kvm_vcpu *vcpu,
                        gva);
                return KVM_INVALID_PAGE;
        }
-       kvm_mips_map_page(vcpu->kvm, gfn);
+
+       if (kvm_mips_map_page(vcpu->kvm, gfn) < 0)
+               return KVM_INVALID_ADDR;
+
        return (kvm->arch.guest_pmap[gfn] << PAGE_SHIFT) + offset;
 }
 
@@ -310,8 +321,11 @@ int kvm_mips_handle_kseg0_tlb_fault(unsigned long badvaddr,
        even = !(gfn & 0x1);
        vaddr = badvaddr & (PAGE_MASK << 1);
 
-       kvm_mips_map_page(vcpu->kvm, gfn);
-       kvm_mips_map_page(vcpu->kvm, gfn ^ 0x1);
+       if (kvm_mips_map_page(vcpu->kvm, gfn) < 0)
+               return -1;
+
+       if (kvm_mips_map_page(vcpu->kvm, gfn ^ 0x1) < 0)
+               return -1;
 
        if (even) {
                pfn0 = kvm->arch.guest_pmap[gfn];
@@ -389,8 +403,11 @@ kvm_mips_handle_mapped_seg_tlb_fault(struct kvm_vcpu *vcpu,
                pfn0 = 0;
                pfn1 = 0;
        } else {
-               kvm_mips_map_page(kvm, mips3_tlbpfn_to_paddr(tlb->tlb_lo0) >> PAGE_SHIFT);
-               kvm_mips_map_page(kvm, mips3_tlbpfn_to_paddr(tlb->tlb_lo1) >> PAGE_SHIFT);
+               if (kvm_mips_map_page(kvm, mips3_tlbpfn_to_paddr(tlb->tlb_lo0) >> PAGE_SHIFT) < 0)
+                       return -1;
+
+               if (kvm_mips_map_page(kvm, mips3_tlbpfn_to_paddr(tlb->tlb_lo1) >> PAGE_SHIFT) < 0)
+                       return -1;
 
                pfn0 = kvm->arch.guest_pmap[mips3_tlbpfn_to_paddr(tlb->tlb_lo0) >> PAGE_SHIFT];
                pfn1 = kvm->arch.guest_pmap[mips3_tlbpfn_to_paddr(tlb->tlb_lo1) >> PAGE_SHIFT];
@@ -428,7 +445,7 @@ int kvm_mips_guest_tlb_lookup(struct kvm_vcpu *vcpu, unsigned long entryhi)
 
        for (i = 0; i < KVM_MIPS_GUEST_TLB_SIZE; i++) {
                if (((TLB_VPN2(tlb[i]) & ~tlb[i].tlb_mask) == ((entryhi & VPN2_MASK) & ~tlb[i].tlb_mask)) &&
-                       (TLB_IS_GLOBAL(tlb[i]) || (TLB_ASID(tlb[i]) == ASID_MASK(entryhi)))) {
+                       (TLB_IS_GLOBAL(tlb[i]) || (TLB_ASID(tlb[i]) == (entryhi & ASID_MASK)))) {
                        index = i;
                        break;
                }
@@ -626,7 +643,7 @@ kvm_get_new_mmu_context(struct mm_struct *mm, unsigned long cpu,
 {
        unsigned long asid = asid_cache(cpu);
 
-       if (!(ASID_MASK(ASID_INC(asid)))) {
+       if (!((asid += ASID_INC) & ASID_MASK)) {
                if (cpu_has_vtag_icache) {
                        flush_icache_all();
                }
@@ -804,7 +821,8 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
        if (!newasid) {
                /* If we preempted while the guest was executing, then reload the pre-empted ASID */
                if (current->flags & PF_VCPU) {
-                       write_c0_entryhi(ASID_MASK(vcpu->arch.preempt_entryhi));
+                       write_c0_entryhi(vcpu->arch.
+                                        preempt_entryhi & ASID_MASK);
                        ehb();
                }
        } else {
@@ -816,11 +834,13 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
                 */
                if (current->flags & PF_VCPU) {
                        if (KVM_GUEST_KERNEL_MODE(vcpu))
-                               write_c0_entryhi(ASID_MASK(vcpu->arch.
-                                                guest_kernel_asid[cpu]));
+                               write_c0_entryhi(vcpu->arch.
+                                                guest_kernel_asid[cpu] &
+                                                ASID_MASK);
                        else
-                               write_c0_entryhi(ASID_MASK(vcpu->arch.
-                                                guest_user_asid[cpu]));
+                               write_c0_entryhi(vcpu->arch.
+                                                guest_user_asid[cpu] &
+                                                ASID_MASK);
                        ehb();
                }
        }
@@ -879,7 +899,8 @@ uint32_t kvm_get_inst(uint32_t *opc, struct kvm_vcpu *vcpu)
                            kvm_mips_guest_tlb_lookup(vcpu,
                                                      ((unsigned long) opc & VPN2_MASK)
                                                      |
-                                                     ASID_MASK(kvm_read_c0_guest_entryhi(cop0)));
+                                                     (kvm_read_c0_guest_entryhi
+                                                      (cop0) & ASID_MASK));
                        if (index < 0) {
                                kvm_err
                                    ("%s: get_user_failed for %p, vcpu: %p, ASID: %#lx\n",
index 466aeef..30d7253 100644 (file)
@@ -345,54 +345,6 @@ static int kvm_trap_emul_handle_break(struct kvm_vcpu *vcpu)
        return ret;
 }
 
-static int
-kvm_trap_emul_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
-{
-       struct mips_coproc *cop0 = vcpu->arch.cop0;
-
-       kvm_write_c0_guest_index(cop0, regs->cp0reg[MIPS_CP0_TLB_INDEX][0]);
-       kvm_write_c0_guest_context(cop0, regs->cp0reg[MIPS_CP0_TLB_CONTEXT][0]);
-       kvm_write_c0_guest_badvaddr(cop0, regs->cp0reg[MIPS_CP0_BAD_VADDR][0]);
-       kvm_write_c0_guest_entryhi(cop0, regs->cp0reg[MIPS_CP0_TLB_HI][0]);
-       kvm_write_c0_guest_epc(cop0, regs->cp0reg[MIPS_CP0_EXC_PC][0]);
-
-       kvm_write_c0_guest_status(cop0, regs->cp0reg[MIPS_CP0_STATUS][0]);
-       kvm_write_c0_guest_cause(cop0, regs->cp0reg[MIPS_CP0_CAUSE][0]);
-       kvm_write_c0_guest_pagemask(cop0,
-                                   regs->cp0reg[MIPS_CP0_TLB_PG_MASK][0]);
-       kvm_write_c0_guest_wired(cop0, regs->cp0reg[MIPS_CP0_TLB_WIRED][0]);
-       kvm_write_c0_guest_errorepc(cop0, regs->cp0reg[MIPS_CP0_ERROR_PC][0]);
-
-       return 0;
-}
-
-static int
-kvm_trap_emul_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
-{
-       struct mips_coproc *cop0 = vcpu->arch.cop0;
-
-       regs->cp0reg[MIPS_CP0_TLB_INDEX][0] = kvm_read_c0_guest_index(cop0);
-       regs->cp0reg[MIPS_CP0_TLB_CONTEXT][0] = kvm_read_c0_guest_context(cop0);
-       regs->cp0reg[MIPS_CP0_BAD_VADDR][0] = kvm_read_c0_guest_badvaddr(cop0);
-       regs->cp0reg[MIPS_CP0_TLB_HI][0] = kvm_read_c0_guest_entryhi(cop0);
-       regs->cp0reg[MIPS_CP0_EXC_PC][0] = kvm_read_c0_guest_epc(cop0);
-
-       regs->cp0reg[MIPS_CP0_STATUS][0] = kvm_read_c0_guest_status(cop0);
-       regs->cp0reg[MIPS_CP0_CAUSE][0] = kvm_read_c0_guest_cause(cop0);
-       regs->cp0reg[MIPS_CP0_TLB_PG_MASK][0] =
-           kvm_read_c0_guest_pagemask(cop0);
-       regs->cp0reg[MIPS_CP0_TLB_WIRED][0] = kvm_read_c0_guest_wired(cop0);
-       regs->cp0reg[MIPS_CP0_ERROR_PC][0] = kvm_read_c0_guest_errorepc(cop0);
-
-       regs->cp0reg[MIPS_CP0_CONFIG][0] = kvm_read_c0_guest_config(cop0);
-       regs->cp0reg[MIPS_CP0_CONFIG][1] = kvm_read_c0_guest_config1(cop0);
-       regs->cp0reg[MIPS_CP0_CONFIG][2] = kvm_read_c0_guest_config2(cop0);
-       regs->cp0reg[MIPS_CP0_CONFIG][3] = kvm_read_c0_guest_config3(cop0);
-       regs->cp0reg[MIPS_CP0_CONFIG][7] = kvm_read_c0_guest_config7(cop0);
-
-       return 0;
-}
-
 static int kvm_trap_emul_vm_init(struct kvm *kvm)
 {
        return 0;
@@ -471,8 +423,6 @@ static struct kvm_mips_callbacks kvm_trap_emul_callbacks = {
        .dequeue_io_int = kvm_mips_dequeue_io_int_cb,
        .irq_deliver = kvm_mips_irq_deliver_cb,
        .irq_clear = kvm_mips_irq_clear_cb,
-       .vcpu_ioctl_get_regs = kvm_trap_emul_ioctl_get_regs,
-       .vcpu_ioctl_set_regs = kvm_trap_emul_ioctl_set_regs,
 };
 
 int kvm_mips_emulation_init(struct kvm_mips_callbacks **install_callbacks)
index 9861c86..850821d 100644 (file)
@@ -144,10 +144,6 @@ static int gptu_probe(struct platform_device *pdev)
        }
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(&pdev->dev, "Failed to get resource\n");
-               return -ENOMEM;
-       }
 
        /* remap gptu register range */
        gptu_membase = devm_ioremap_resource(&pdev->dev, res);
@@ -169,6 +165,8 @@ static int gptu_probe(struct platform_device *pdev)
        if (((gptu_r32(GPTU_ID) >> 8) & 0xff) != GPTU_MAGIC) {
                dev_err(&pdev->dev, "Failed to find magic\n");
                gptu_hwexit();
+               clk_disable(clk);
+               clk_put(clk);
                return -ENAVAIL;
        }
 
index 8a12d00..32b9f21 100644 (file)
@@ -11,7 +11,6 @@
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/tlbdebug.h>
-#include <asm/mmu_context.h>
 
 static inline const char *msk2str(unsigned int mask)
 {
@@ -56,7 +55,7 @@ static void dump_tlb(int first, int last)
        s_pagemask = read_c0_pagemask();
        s_entryhi = read_c0_entryhi();
        s_index = read_c0_index();
-       asid = ASID_MASK(s_entryhi);
+       asid = s_entryhi & 0xff;
 
        for (i = first; i <= last; i++) {
                write_c0_index(i);
@@ -86,7 +85,7 @@ static void dump_tlb(int first, int last)
 
                        printk("va=%0*lx asid=%02lx\n",
                               width, (entryhi & ~0x1fffUL),
-                              ASID_MASK(entryhi));
+                              entryhi & 0xff);
                        printk("\t[pa=%0*llx c=%d d=%d v=%d g=%d] ",
                               width,
                               (entrylo0 << 6) & PAGE_MASK, c0,
index 8327698..91615c2 100644 (file)
@@ -9,7 +9,6 @@
 #include <linux/mm.h>
 
 #include <asm/mipsregs.h>
-#include <asm/mmu_context.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/tlbdebug.h>
@@ -22,7 +21,7 @@ static void dump_tlb(int first, int last)
        unsigned int asid;
        unsigned long entryhi, entrylo0;
 
-       asid = ASID_MASK(read_c0_entryhi());
+       asid = read_c0_entryhi() & 0xfc0;
 
        for (i = first; i <= last; i++) {
                write_c0_index(i<<8);
@@ -36,7 +35,7 @@ static void dump_tlb(int first, int last)
 
                /* Unused entries have a virtual address of KSEG0.  */
                if ((entryhi & 0xffffe000) != 0x80000000
-                   && (ASID_MASK(entryhi) == asid)) {
+                   && (entryhi & 0xfc0) == asid) {
                        /*
                         * Only print entries in use
                         */
@@ -45,7 +44,7 @@ static void dump_tlb(int first, int last)
                        printk("va=%08lx asid=%08lx"
                               "  [pa=%06lx n=%d d=%d v=%d g=%d]",
                               (entryhi & 0xffffe000),
-                              ASID_MASK(entryhi),
+                              entryhi & 0xfc0,
                               entrylo0 & PAGE_MASK,
                               (entrylo0 & (1 << 11)) ? 1 : 0,
                               (entrylo0 & (1 << 10)) ? 1 : 0,
index 35c8c64..65bfbb5 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/init.h>
 #include <linux/pm.h>
 
+#include <asm/idle.h>
 #include <asm/reboot.h>
 
 #include <loongson.h>
index d4f610f..547f34b 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <linux/io.h>
 #include <linux/pm.h>
+#include <asm/idle.h>
 #include <asm/reboot.h>
 
 #include <loongson1.h>
index 4a13c15..a63d1ed 100644 (file)
@@ -51,7 +51,7 @@ void local_flush_tlb_all(void)
 #endif
 
        local_irq_save(flags);
-       old_ctx = ASID_MASK(read_c0_entryhi());
+       old_ctx = read_c0_entryhi() & ASID_MASK;
        write_c0_entrylo0(0);
        entry = r3k_have_wired_reg ? read_c0_wired() : 8;
        for (; entry < current_cpu_data.tlbsize; entry++) {
@@ -87,13 +87,13 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
 
 #ifdef DEBUG_TLB
                printk("[tlbrange<%lu,0x%08lx,0x%08lx>]",
-                       ASID_MASK(cpu_context(cpu, mm)), start, end);
+                       cpu_context(cpu, mm) & ASID_MASK, start, end);
 #endif
                local_irq_save(flags);
                size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
                if (size <= current_cpu_data.tlbsize) {
-                       int oldpid = ASID_MASK(read_c0_entryhi());
-                       int newpid = ASID_MASK(cpu_context(cpu, mm));
+                       int oldpid = read_c0_entryhi() & ASID_MASK;
+                       int newpid = cpu_context(cpu, mm) & ASID_MASK;
 
                        start &= PAGE_MASK;
                        end += PAGE_SIZE - 1;
@@ -166,10 +166,10 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
 #ifdef DEBUG_TLB
                printk("[tlbpage<%lu,0x%08lx>]", cpu_context(cpu, vma->vm_mm), page);
 #endif
-               newpid = ASID_MASK(cpu_context(cpu, vma->vm_mm));
+               newpid = cpu_context(cpu, vma->vm_mm) & ASID_MASK;
                page &= PAGE_MASK;
                local_irq_save(flags);
-               oldpid = ASID_MASK(read_c0_entryhi());
+               oldpid = read_c0_entryhi() & ASID_MASK;
                write_c0_entryhi(page | newpid);
                BARRIER;
                tlb_probe();
@@ -197,10 +197,10 @@ void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte)
        if (current->active_mm != vma->vm_mm)
                return;
 
-       pid = ASID_MASK(read_c0_entryhi());
+       pid = read_c0_entryhi() & ASID_MASK;
 
 #ifdef DEBUG_TLB
-       if ((pid != ASID_MASK(cpu_context(cpu, vma->vm_mm))) || (cpu_context(cpu, vma->vm_mm) == 0)) {
+       if ((pid != (cpu_context(cpu, vma->vm_mm) & ASID_MASK)) || (cpu_context(cpu, vma->vm_mm) == 0)) {
                printk("update_mmu_cache: Wheee, bogus tlbpid mmpid=%lu tlbpid=%d\n",
                       (cpu_context(cpu, vma->vm_mm)), pid);
        }
@@ -241,7 +241,7 @@ void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
 
                local_irq_save(flags);
                /* Save old context and create impossible VPN2 value */
-               old_ctx = ASID_MASK(read_c0_entryhi());
+               old_ctx = read_c0_entryhi() & ASID_MASK;
                old_pagemask = read_c0_pagemask();
                w = read_c0_wired();
                write_c0_wired(w + 1);
@@ -264,7 +264,7 @@ void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
 #endif
 
                local_irq_save(flags);
-               old_ctx = ASID_MASK(read_c0_entryhi());
+               old_ctx = read_c0_entryhi() & ASID_MASK;
                write_c0_entrylo0(entrylo0);
                write_c0_entryhi(entryhi);
                write_c0_index(wired);
index 09653b2..c643de4 100644 (file)
@@ -287,7 +287,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
 
        ENTER_CRITICAL(flags);
 
-       pid = ASID_MASK(read_c0_entryhi());
+       pid = read_c0_entryhi() & ASID_MASK;
        address &= (PAGE_MASK << 1);
        write_c0_entryhi(address | pid);
        pgdp = pgd_offset(vma->vm_mm, address);
index 122f920..91c2499 100644 (file)
@@ -195,7 +195,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
        if (current->active_mm != vma->vm_mm)
                return;
 
-       pid = ASID_MASK(read_c0_entryhi());
+       pid = read_c0_entryhi() & ASID_MASK;
 
        local_irq_save(flags);
        address &= PAGE_MASK;
index 4d46d37..afeef93 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/init.h>
 #include <linux/cache.h>
 
-#include <asm/mmu_context.h>
 #include <asm/cacheflush.h>
 #include <asm/pgtable.h>
 #include <asm/war.h>
@@ -302,82 +301,6 @@ static u32 tlb_handler[128] __cpuinitdata;
 static struct uasm_label labels[128] __cpuinitdata;
 static struct uasm_reloc relocs[128] __cpuinitdata;
 
-#ifdef CONFIG_64BIT
-static int check_for_high_segbits __cpuinitdata;
-#endif
-
-static void __cpuinit insn_fixup(unsigned int **start, unsigned int **stop,
-                                       unsigned int i_const)
-{
-       unsigned int **p;
-
-       for (p = start; p < stop; p++) {
-#ifndef CONFIG_CPU_MICROMIPS
-               unsigned int *ip;
-
-               ip = *p;
-               *ip = (*ip & 0xffff0000) | i_const;
-#else
-               unsigned short *ip;
-
-               ip = ((unsigned short *)((unsigned int)*p - 1));
-               if ((*ip & 0xf000) == 0x4000) {
-                       *ip &= 0xfff1;
-                       *ip |= (i_const << 1);
-               } else if ((*ip & 0xf000) == 0x6000) {
-                       *ip &= 0xfff1;
-                       *ip |= ((i_const >> 2) << 1);
-               } else {
-                       ip++;
-                       *ip = i_const;
-               }
-#endif
-               local_flush_icache_range((unsigned long)ip,
-                                        (unsigned long)ip + sizeof(*ip));
-       }
-}
-
-#define asid_insn_fixup(section, const)                                        \
-do {                                                                   \
-       extern unsigned int *__start_ ## section;                       \
-       extern unsigned int *__stop_ ## section;                        \
-       insn_fixup(&__start_ ## section, &__stop_ ## section, const);   \
-} while(0)
-
-/*
- * Caller is assumed to flush the caches before the first context switch.
- */
-static void __cpuinit setup_asid(unsigned int inc, unsigned int mask,
-                                unsigned int version_mask,
-                                unsigned int first_version)
-{
-       extern asmlinkage void handle_ri_rdhwr_vivt(void);
-       unsigned long *vivt_exc;
-
-#ifdef CONFIG_CPU_MICROMIPS
-       /*
-        * Worst case optimised microMIPS addiu instructions support
-        * only a 3-bit immediate value.
-        */
-       if(inc > 7)
-               panic("Invalid ASID increment value!");
-#endif
-       asid_insn_fixup(__asid_inc, inc);
-       asid_insn_fixup(__asid_mask, mask);
-       asid_insn_fixup(__asid_version_mask, version_mask);
-       asid_insn_fixup(__asid_first_version, first_version);
-
-       /* Patch up the 'handle_ri_rdhwr_vivt' handler. */
-       vivt_exc = (unsigned long *) &handle_ri_rdhwr_vivt;
-#ifdef CONFIG_CPU_MICROMIPS
-       vivt_exc = (unsigned long *)((unsigned long) vivt_exc - 1);
-#endif
-       vivt_exc++;
-       *vivt_exc = (*vivt_exc & ~mask) | mask;
-
-       current_cpu_data.asid_cache = first_version;
-}
-
 static int check_for_high_segbits __cpuinitdata;
 
 static unsigned int kscratch_used_mask __cpuinitdata;
@@ -2256,7 +2179,6 @@ void __cpuinit build_tlb_refill_handler(void)
        case CPU_TX3922:
        case CPU_TX3927:
 #ifndef CONFIG_MIPS_PGD_C0_CONTEXT
-               setup_asid(0x40, 0xfc0, 0xf000, ASID_FIRST_VERSION_R3000);
                if (cpu_has_local_ebase)
                        build_r3000_tlb_refill_handler();
                if (!run_once) {
@@ -2282,11 +2204,6 @@ void __cpuinit build_tlb_refill_handler(void)
                break;
 
        default:
-#ifndef CONFIG_MIPS_MT_SMTC
-               setup_asid(0x1, 0xff, 0xff00, ASID_FIRST_VERSION_R4000);
-#else
-               setup_asid(0x1, smtc_asid_mask, 0xff00, ASID_FIRST_VERSION_R4000);
-#endif
                if (!run_once) {
                        scratch_reg = allocate_kscratch();
 #ifdef CONFIG_MIPS_PGD_C0_CONTEXT
index af31914..eaa99d2 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/pm.h>
 #include <linux/bootmem.h>
 
+#include <asm/idle.h>
 #include <asm/reboot.h>
 #include <asm/time.h>
 #include <asm/bootinfo.h>
index e3e0941..89c8c10 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/serial_8250.h>
 #include <linux/pm.h>
 
+#include <asm/idle.h>
 #include <asm/reboot.h>
 #include <asm/time.h>
 #include <asm/bootinfo.h>
index 0edb89a..1c98975 100644 (file)
@@ -83,7 +83,7 @@ static inline unsigned char str2hexnum(unsigned char c)
        return 0; /* foo */
 }
 
-static inline int str2eaddr(unsigned char *ea, unsigned char *str)
+int str2eaddr(unsigned char *ea, unsigned char *str)
 {
        int index = 0;
        unsigned char num = 0;
index 1651cfd..396b296 100644 (file)
@@ -12,6 +12,7 @@
 
 #include <asm/bootinfo.h>
 #include <asm/cacheflush.h>
+#include <asm/idle.h>
 #include <asm/r4kcache.h>
 #include <asm/reboot.h>
 #include <asm/smp-ops.h>
index ef7da1e..e3203d4 100644 (file)
                        reg-shift = <2>;
                };
        };
+
+       usb@101c0000 {
+               compatible = "ralink,rt3050-usb", "snps,dwc2";
+               reg = <0x101c0000 40000>;
+
+               interrupt-parent = <&intc>;
+               interrupts = <18>;
+
+               status = "disabled";
+       };
 };
index c18c9a8..0ac73ea 100644 (file)
@@ -43,4 +43,8 @@
                        reg = <0x50000 0x7b0000>;
                };
        };
+
+       usb@101c0000 {
+               status = "ok";
+       };
 };
index fb15695..6b5f340 100644 (file)
@@ -88,7 +88,7 @@ void __init plat_mem_setup(void)
        __dt_setup_arch(&__dtb_start);
 
        if (soc_info.mem_size)
-               add_memory_region(soc_info.mem_base, soc_info.mem_size,
+               add_memory_region(soc_info.mem_base, soc_info.mem_size * SZ_1M,
                                  BOOT_MEM_RAM);
        else
                detect_memory_region(soc_info.mem_base,
index 5364aab..681e7f8 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/slab.h>
 #include <linux/irq.h>
 #include <asm/bootinfo.h>
+#include <asm/idle.h>
 #include <asm/time.h>
 #include <asm/reboot.h>
 #include <asm/r4kcache.h>
index 70a3f90..d7f7558 100644 (file)
@@ -27,6 +27,7 @@
 
 #include <asm/cacheflush.h>
 #include <asm/cpu.h>
+#include <asm/idle.h>
 #include <asm/io.h>
 #include <asm/processor.h>
 #include <asm/reboot.h>
index cc5474b..80beb18 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/kernel.h>
 
 #include <asm/cacheflush.h>
+#include <asm/idle.h>
 #include <asm/mipsregs.h>
 #include <asm/processor.h>
 
index 8137c25..6f31cc0 100644 (file)
@@ -103,4 +103,6 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
        return channel ? 15 : 14;
 }
 
+#include <asm-generic/pci_iomap.h>
+
 #endif /* _ASM_PCI_H */
index 68fcab8..222152a 100644 (file)
@@ -60,6 +60,7 @@ ENTRY(ret_from_kernel_thread)
        mov     (REG_D0,fp),d0
        mov     (REG_A0,fp),a0
        calls   (a0)
+       GET_THREAD_INFO a2              # A2 must be set on return from sys_exit()
        clr     d0
        mov     d0,(REG_D0,fp)
        jmp     syscall_exit
@@ -107,10 +108,10 @@ syscall_exit_work:
        and     EPSW_nSL,d0
        beq     resume_kernel           # returning to supervisor mode
 
-       btst    _TIF_SYSCALL_TRACE,d2
-       beq     work_pending
        LOCAL_IRQ_ENABLE                # could let syscall_trace_exit() call
                                        # schedule() instead
+       btst    _TIF_SYSCALL_TRACE,d2
+       beq     work_pending
        mov     fp,d0
        call    syscall_trace_exit[],0  # do_syscall_trace(regs)
        jmp     resume_userspace
@@ -123,6 +124,7 @@ work_pending:
 work_resched:
        call    schedule[],0
 
+resume_userspace:
        # make sure we don't miss an interrupt setting need_resched or
        # sigpending between sampling and the rti
        LOCAL_IRQ_DISABLE
@@ -131,6 +133,8 @@ work_resched:
        mov     (TI_flags,a2),d2
        btst    _TIF_WORK_MASK,d2
        beq     restore_all
+
+       LOCAL_IRQ_ENABLE
        btst    _TIF_NEED_RESCHED,d2
        bne     work_resched
 
@@ -169,17 +173,6 @@ ret_from_intr:
        and     EPSW_nSL,d0
        beq     resume_kernel           # returning to supervisor mode
 
-ENTRY(resume_userspace)
-       # make sure we don't miss an interrupt setting need_resched or
-       # sigpending between sampling and the rti
-       LOCAL_IRQ_DISABLE
-
-       # is there any work to be done on int/exception return?
-       mov     (TI_flags,a2),d2
-       btst    _TIF_WORK_MASK,d2
-       bne     work_pending
-       jmp     restore_all
-
 #ifdef CONFIG_PREEMPT
 ENTRY(resume_kernel)
        LOCAL_IRQ_DISABLE
index 1adcf02..e37fac0 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/delay.h>
 #include <linux/irq.h>
 #include <asm/io.h>
+#include <asm/irq.h>
 #include "pci-asb2305.h"
 
 unsigned int pci_probe = 1;
index cad060f..6507dab 100644 (file)
@@ -245,7 +245,7 @@ config SMP
 
 config IRQSTACKS
        bool "Use separate kernel stacks when processing interrupts"
-       default n
+       default y
        help
          If you say Y here the kernel will use separate kernel stacks
          for handling hard and soft interrupts.  This can help avoid
index 2f967cc..96ec398 100644 (file)
@@ -23,24 +23,21 @@ NM          = sh $(srctree)/arch/parisc/nm
 CHECKFLAGS     += -D__hppa__=1
 LIBGCC         = $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
 
-MACHINE                := $(shell uname -m)
-NATIVE         := $(if $(filter parisc%,$(MACHINE)),1,0)
-
 ifdef CONFIG_64BIT
 UTS_MACHINE    := parisc64
 CHECKFLAGS     += -D__LP64__=1 -m64
-WIDTH          := 64
+CC_ARCHES      = hppa64
 else # 32-bit
-WIDTH          :=
+CC_ARCHES      = hppa hppa2.0 hppa1.1
 endif
 
-# attempt to help out folks who are cross-compiling
-ifeq ($(NATIVE),1)
-CROSS_COMPILE  := hppa$(WIDTH)-linux-
-else
- ifeq ($(CROSS_COMPILE),)
- CROSS_COMPILE := hppa$(WIDTH)-linux-gnu-
- endif
+ifneq ($(SUBARCH),$(UTS_MACHINE))
+       ifeq ($(CROSS_COMPILE),)
+               CC_SUFFIXES = linux linux-gnu unknown-linux-gnu
+               CROSS_COMPILE := $(call cc-cross-prefix, \
+                       $(foreach a,$(CC_ARCHES), \
+                       $(foreach s,$(CC_SUFFIXES),$(a)-$(s)-)))
      endif
 endif
 
 OBJCOPY_FLAGS =-O binary -R .note -R .comment -S
@@ -69,7 +66,7 @@ KBUILD_CFLAGS_KERNEL += -mlong-calls
 endif
 
 # select which processor to optimise for
-cflags-$(CONFIG_PA7100)                += -march=1.1 -mschedule=7100
+cflags-$(CONFIG_PA7000)                += -march=1.1 -mschedule=7100
 cflags-$(CONFIG_PA7200)                += -march=1.1 -mschedule=7200
 cflags-$(CONFIG_PA7100LC)      += -march=1.1 -mschedule=7100LC
 cflags-$(CONFIG_PA7300LC)      += -march=1.1 -mschedule=7300
index 89fb400..0da8482 100644 (file)
        SAVE_SP  (%sr4, PT_SR4 (\regs))
        SAVE_SP  (%sr5, PT_SR5 (\regs))
        SAVE_SP  (%sr6, PT_SR6 (\regs))
-       SAVE_SP  (%sr7, PT_SR7 (\regs))
 
        SAVE_CR  (%cr17, PT_IASQ0(\regs))
        mtctl    %r0,   %cr17
index 12373c4..241c345 100644 (file)
 #include <linux/threads.h>
 #include <linux/irq.h>
 
+#ifdef CONFIG_IRQSTACKS
+#define __ARCH_HAS_DO_SOFTIRQ
+#endif
+
 typedef struct {
        unsigned int __softirq_pending;
-#ifdef CONFIG_DEBUG_STACKOVERFLOW
        unsigned int kernel_stack_usage;
-#endif
+       unsigned int irq_stack_usage;
 #ifdef CONFIG_SMP
        unsigned int irq_resched_count;
        unsigned int irq_call_count;
 #endif
+       unsigned int irq_unaligned_count;
+       unsigned int irq_fpassist_count;
        unsigned int irq_tlb_count;
 } ____cacheline_aligned irq_cpustat_t;
 
@@ -28,6 +33,7 @@ DECLARE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat);
 #define __ARCH_IRQ_STAT
 #define __IRQ_STAT(cpu, member) (irq_stat[cpu].member)
 #define inc_irq_stat(member)   this_cpu_inc(irq_stat.member)
+#define __inc_irq_stat(member) __this_cpu_inc(irq_stat.member)
 #define local_softirq_pending()        this_cpu_read(irq_stat.__softirq_pending)
 
 #define __ARCH_SET_SOFTIRQ_PENDING
index 0e625ab..cc50d33 100644 (file)
@@ -39,17 +39,14 @@ extern unsigned char pfnnid_map[PFNNID_MAP_MAX];
 static inline int pfn_to_nid(unsigned long pfn)
 {
        unsigned int i;
-       unsigned char r;
 
        if (unlikely(pfn_is_io(pfn)))
                return 0;
 
        i = pfn >> PFNNID_SHIFT;
        BUG_ON(i >= ARRAY_SIZE(pfnnid_map));
-       r = pfnnid_map[i];
-       BUG_ON(r == 0xff);
 
-       return (int)r;
+       return (int)pfnnid_map[i];
 }
 
 static inline int pfn_valid(int pfn)
index 0640155..cc2290a 100644 (file)
@@ -17,7 +17,6 @@
 #include <asm/ptrace.h>
 #include <asm/types.h>
 #include <asm/percpu.h>
-
 #endif /* __ASSEMBLY__ */
 
 /*
 
 #ifndef __ASSEMBLY__
 
-/*
- * IRQ STACK - used for irq handler
- */
-#ifdef __KERNEL__
-
-#define IRQ_STACK_SIZE      (4096 << 2) /* 16k irq stack size */
-
-union irq_stack_union {
-       unsigned long stack[IRQ_STACK_SIZE/sizeof(unsigned long)];
-};
-
-DECLARE_PER_CPU(union irq_stack_union, irq_stack_union);
-
-void call_on_stack(unsigned long p1, void *func, unsigned long new_stack);
-
-#endif /* __KERNEL__ */
-
 /*
  * Data detected about CPUs at boot time which is the same for all CPU's.
  * HP boxes are SMP - ie identical processors.
index 5709c5e..14285ca 100644 (file)
@@ -394,7 +394,7 @@ EXPORT_SYMBOL(print_pci_hwpath);
 static void setup_bus_id(struct parisc_device *padev)
 {
        struct hardware_path path;
-       char name[20];
+       char name[28];
        char *output = name;
        int i;
 
index 4bb96ad..e8f07dd 100644 (file)
        rsm     PSW_SM_I, %r0   /* barrier for "Relied upon Translation */
        mtsp    %r0, %sr4
        mtsp    %r0, %sr5
-       mfsp    %sr7, %r1
-       or,=    %r0,%r1,%r0     /* Only save sr7 in sr3 if sr7 != 0 */
-       mtsp    %r1, %sr3
+       mtsp    %r0, %sr6
        tovirt_r1 %r29
        load32  KERNEL_PSW, %r1
 
        rsm     PSW_SM_QUIET,%r0        /* second "heavy weight" ctl op */
-       mtsp    %r0, %sr6
-       mtsp    %r0, %sr7
        mtctl   %r0, %cr17      /* Clear IIASQ tail */
        mtctl   %r0, %cr17      /* Clear IIASQ head */
        mtctl   %r1, %ipsw
 
        /* we save the registers in the task struct */
 
+       copy    %r30, %r17
        mfctl   %cr30, %r1
+       ldo     THREAD_SZ_ALGN(%r1), %r30
+       mtsp    %r0,%sr7
+       mtsp    %r16,%sr3
        tophys  %r1,%r9
        LDREG   TI_TASK(%r9), %r1       /* thread_info -> task_struct */
        tophys  %r1,%r9
        ldo     TASK_REGS(%r9),%r9
-       STREG   %r30, PT_GR30(%r9)
+       STREG   %r17,PT_GR30(%r9)
        STREG   %r29,PT_GR29(%r9)
        STREG   %r26,PT_GR26(%r9)
+       STREG   %r16,PT_SR7(%r9)
        copy    %r9,%r29
-       mfctl   %cr30, %r1
-       ldo     THREAD_SZ_ALGN(%r1), %r30
        .endm
 
        .macro  get_stack_use_r30
        /* we put a struct pt_regs on the stack and save the registers there */
 
        tophys  %r30,%r9
-       STREG   %r30,PT_GR30(%r9)
+       copy    %r30,%r1
        ldo     PT_SZ_ALGN(%r30),%r30
+       STREG   %r1,PT_GR30(%r9)
        STREG   %r29,PT_GR29(%r9)
        STREG   %r26,PT_GR26(%r9)
+       STREG   %r16,PT_SR7(%r9)
        copy    %r9,%r29
        .endm
 
        L2_ptep         \pgd,\pte,\index,\va,\fault
        .endm
 
+       /* Acquire pa_dbit_lock lock. */
+       .macro          dbit_lock       spc,tmp,tmp1
+#ifdef CONFIG_SMP
+       cmpib,COND(=),n 0,\spc,2f
+       load32          PA(pa_dbit_lock),\tmp
+1:     LDCW            0(\tmp),\tmp1
+       cmpib,COND(=)   0,\tmp1,1b
+       nop
+2:
+#endif
+       .endm
+
+       /* Release pa_dbit_lock lock without reloading lock address. */
+       .macro          dbit_unlock0    spc,tmp
+#ifdef CONFIG_SMP
+       or,COND(=)      %r0,\spc,%r0
+       stw             \spc,0(\tmp)
+#endif
+       .endm
+
+       /* Release pa_dbit_lock lock. */
+       .macro          dbit_unlock1    spc,tmp
+#ifdef CONFIG_SMP
+       load32          PA(pa_dbit_lock),\tmp
+       dbit_unlock0    \spc,\tmp
+#endif
+       .endm
+
        /* Set the _PAGE_ACCESSED bit of the PTE.  Be clever and
         * don't needlessly dirty the cache line if it was already set */
-       .macro          update_ptep     ptep,pte,tmp,tmp1
+       .macro          update_ptep     spc,ptep,pte,tmp,tmp1
+#ifdef CONFIG_SMP
+       or,COND(=)      %r0,\spc,%r0
+       LDREG           0(\ptep),\pte
+#endif
        ldi             _PAGE_ACCESSED,\tmp1
        or              \tmp1,\pte,\tmp
        and,COND(<>)    \tmp1,\pte,%r0
 
        /* Set the dirty bit (and accessed bit).  No need to be
         * clever, this is only used from the dirty fault */
-       .macro          update_dirty    ptep,pte,tmp
+       .macro          update_dirty    spc,ptep,pte,tmp
+#ifdef CONFIG_SMP
+       or,COND(=)      %r0,\spc,%r0
+       LDREG           0(\ptep),\pte
+#endif
        ldi             _PAGE_ACCESSED|_PAGE_DIRTY,\tmp
        or              \tmp,\pte,\pte
        STREG           \pte,0(\ptep)
@@ -1111,11 +1148,13 @@ dtlb_miss_20w:
 
        L3_ptep         ptp,pte,t0,va,dtlb_check_alias_20w
 
-       update_ptep     ptp,pte,t0,t1
+       dbit_lock       spc,t0,t1
+       update_ptep     spc,ptp,pte,t0,t1
 
        make_insert_tlb spc,pte,prot
        
        idtlbt          pte,prot
+       dbit_unlock1    spc,t0
 
        rfir
        nop
@@ -1135,11 +1174,13 @@ nadtlb_miss_20w:
 
        L3_ptep         ptp,pte,t0,va,nadtlb_check_alias_20w
 
-       update_ptep     ptp,pte,t0,t1
+       dbit_lock       spc,t0,t1
+       update_ptep     spc,ptp,pte,t0,t1
 
        make_insert_tlb spc,pte,prot
 
        idtlbt          pte,prot
+       dbit_unlock1    spc,t0
 
        rfir
        nop
@@ -1161,7 +1202,8 @@ dtlb_miss_11:
 
        L2_ptep         ptp,pte,t0,va,dtlb_check_alias_11
 
-       update_ptep     ptp,pte,t0,t1
+       dbit_lock       spc,t0,t1
+       update_ptep     spc,ptp,pte,t0,t1
 
        make_insert_tlb_11      spc,pte,prot
 
@@ -1172,6 +1214,7 @@ dtlb_miss_11:
        idtlbp          prot,(%sr1,va)
 
        mtsp            t0, %sr1        /* Restore sr1 */
+       dbit_unlock1    spc,t0
 
        rfir
        nop
@@ -1192,7 +1235,8 @@ nadtlb_miss_11:
 
        L2_ptep         ptp,pte,t0,va,nadtlb_check_alias_11
 
-       update_ptep     ptp,pte,t0,t1
+       dbit_lock       spc,t0,t1
+       update_ptep     spc,ptp,pte,t0,t1
 
        make_insert_tlb_11      spc,pte,prot
 
@@ -1204,6 +1248,7 @@ nadtlb_miss_11:
        idtlbp          prot,(%sr1,va)
 
        mtsp            t0, %sr1        /* Restore sr1 */
+       dbit_unlock1    spc,t0
 
        rfir
        nop
@@ -1224,13 +1269,15 @@ dtlb_miss_20:
 
        L2_ptep         ptp,pte,t0,va,dtlb_check_alias_20
 
-       update_ptep     ptp,pte,t0,t1
+       dbit_lock       spc,t0,t1
+       update_ptep     spc,ptp,pte,t0,t1
 
        make_insert_tlb spc,pte,prot
 
        f_extend        pte,t0
 
        idtlbt          pte,prot
+       dbit_unlock1    spc,t0
 
        rfir
        nop
@@ -1250,13 +1297,15 @@ nadtlb_miss_20:
 
        L2_ptep         ptp,pte,t0,va,nadtlb_check_alias_20
 
-       update_ptep     ptp,pte,t0,t1
+       dbit_lock       spc,t0,t1
+       update_ptep     spc,ptp,pte,t0,t1
 
        make_insert_tlb spc,pte,prot
 
        f_extend        pte,t0
        
         idtlbt          pte,prot
+       dbit_unlock1    spc,t0
 
        rfir
        nop
@@ -1357,11 +1406,13 @@ itlb_miss_20w:
 
        L3_ptep         ptp,pte,t0,va,itlb_fault
 
-       update_ptep     ptp,pte,t0,t1
+       dbit_lock       spc,t0,t1
+       update_ptep     spc,ptp,pte,t0,t1
 
        make_insert_tlb spc,pte,prot
        
        iitlbt          pte,prot
+       dbit_unlock1    spc,t0
 
        rfir
        nop
@@ -1379,11 +1430,13 @@ naitlb_miss_20w:
 
        L3_ptep         ptp,pte,t0,va,naitlb_check_alias_20w
 
-       update_ptep     ptp,pte,t0,t1
+       dbit_lock       spc,t0,t1
+       update_ptep     spc,ptp,pte,t0,t1
 
        make_insert_tlb spc,pte,prot
 
        iitlbt          pte,prot
+       dbit_unlock1    spc,t0
 
        rfir
        nop
@@ -1405,7 +1458,8 @@ itlb_miss_11:
 
        L2_ptep         ptp,pte,t0,va,itlb_fault
 
-       update_ptep     ptp,pte,t0,t1
+       dbit_lock       spc,t0,t1
+       update_ptep     spc,ptp,pte,t0,t1
 
        make_insert_tlb_11      spc,pte,prot
 
@@ -1416,6 +1470,7 @@ itlb_miss_11:
        iitlbp          prot,(%sr1,va)
 
        mtsp            t0, %sr1        /* Restore sr1 */
+       dbit_unlock1    spc,t0
 
        rfir
        nop
@@ -1427,7 +1482,8 @@ naitlb_miss_11:
 
        L2_ptep         ptp,pte,t0,va,naitlb_check_alias_11
 
-       update_ptep     ptp,pte,t0,t1
+       dbit_lock       spc,t0,t1
+       update_ptep     spc,ptp,pte,t0,t1
 
        make_insert_tlb_11      spc,pte,prot
 
@@ -1438,6 +1494,7 @@ naitlb_miss_11:
        iitlbp          prot,(%sr1,va)
 
        mtsp            t0, %sr1        /* Restore sr1 */
+       dbit_unlock1    spc,t0
 
        rfir
        nop
@@ -1459,13 +1516,15 @@ itlb_miss_20:
 
        L2_ptep         ptp,pte,t0,va,itlb_fault
 
-       update_ptep     ptp,pte,t0,t1
+       dbit_lock       spc,t0,t1
+       update_ptep     spc,ptp,pte,t0,t1
 
        make_insert_tlb spc,pte,prot
 
        f_extend        pte,t0  
 
        iitlbt          pte,prot
+       dbit_unlock1    spc,t0
 
        rfir
        nop
@@ -1477,13 +1536,15 @@ naitlb_miss_20:
 
        L2_ptep         ptp,pte,t0,va,naitlb_check_alias_20
 
-       update_ptep     ptp,pte,t0,t1
+       dbit_lock       spc,t0,t1
+       update_ptep     spc,ptp,pte,t0,t1
 
        make_insert_tlb spc,pte,prot
 
        f_extend        pte,t0
 
        iitlbt          pte,prot
+       dbit_unlock1    spc,t0
 
        rfir
        nop
@@ -1507,29 +1568,13 @@ dbit_trap_20w:
 
        L3_ptep         ptp,pte,t0,va,dbit_fault
 
-#ifdef CONFIG_SMP
-       cmpib,COND(=),n        0,spc,dbit_nolock_20w
-       load32          PA(pa_dbit_lock),t0
-
-dbit_spin_20w:
-       LDCW            0(t0),t1
-       cmpib,COND(=)         0,t1,dbit_spin_20w
-       nop
-
-dbit_nolock_20w:
-#endif
-       update_dirty    ptp,pte,t1
+       dbit_lock       spc,t0,t1
+       update_dirty    spc,ptp,pte,t1
 
        make_insert_tlb spc,pte,prot
                
        idtlbt          pte,prot
-#ifdef CONFIG_SMP
-       cmpib,COND(=),n        0,spc,dbit_nounlock_20w
-       ldi             1,t1
-       stw             t1,0(t0)
-
-dbit_nounlock_20w:
-#endif
+       dbit_unlock0    spc,t0
 
        rfir
        nop
@@ -1543,18 +1588,8 @@ dbit_trap_11:
 
        L2_ptep         ptp,pte,t0,va,dbit_fault
 
-#ifdef CONFIG_SMP
-       cmpib,COND(=),n        0,spc,dbit_nolock_11
-       load32          PA(pa_dbit_lock),t0
-
-dbit_spin_11:
-       LDCW            0(t0),t1
-       cmpib,=         0,t1,dbit_spin_11
-       nop
-
-dbit_nolock_11:
-#endif
-       update_dirty    ptp,pte,t1
+       dbit_lock       spc,t0,t1
+       update_dirty    spc,ptp,pte,t1
 
        make_insert_tlb_11      spc,pte,prot
 
@@ -1565,13 +1600,7 @@ dbit_nolock_11:
        idtlbp          prot,(%sr1,va)
 
        mtsp            t1, %sr1     /* Restore sr1 */
-#ifdef CONFIG_SMP
-       cmpib,COND(=),n        0,spc,dbit_nounlock_11
-       ldi             1,t1
-       stw             t1,0(t0)
-
-dbit_nounlock_11:
-#endif
+       dbit_unlock0    spc,t0
 
        rfir
        nop
@@ -1583,32 +1612,15 @@ dbit_trap_20:
 
        L2_ptep         ptp,pte,t0,va,dbit_fault
 
-#ifdef CONFIG_SMP
-       cmpib,COND(=),n        0,spc,dbit_nolock_20
-       load32          PA(pa_dbit_lock),t0
-
-dbit_spin_20:
-       LDCW            0(t0),t1
-       cmpib,=         0,t1,dbit_spin_20
-       nop
-
-dbit_nolock_20:
-#endif
-       update_dirty    ptp,pte,t1
+       dbit_lock       spc,t0,t1
+       update_dirty    spc,ptp,pte,t1
 
        make_insert_tlb spc,pte,prot
 
        f_extend        pte,t1
        
         idtlbt          pte,prot
-
-#ifdef CONFIG_SMP
-       cmpib,COND(=),n        0,spc,dbit_nounlock_20
-       ldi             1,t1
-       stw             t1,0(t0)
-
-dbit_nounlock_20:
-#endif
+       dbit_unlock0    spc,t0
 
        rfir
        nop
index f7752f6..9e2d2e4 100644 (file)
@@ -222,6 +222,7 @@ static struct hp_hardware hp_hardware_list[] = {
        {HPHW_NPROC,0x5DD,0x4,0x81,"Duet W2"},
        {HPHW_NPROC,0x5DE,0x4,0x81,"Piccolo W+"},
        {HPHW_NPROC,0x5DF,0x4,0x81,"Cantata W2"},
+       {HPHW_NPROC,0x5DF,0x0,0x00,"Marcato W+? (rp5470)"},
        {HPHW_NPROC,0x5E0,0x4,0x91,"Cantata DC- W2"},
        {HPHW_NPROC,0x5E1,0x4,0x91,"Crescendo DC- W2"},
        {HPHW_NPROC,0x5E2,0x4,0x91,"Crescendo 650 W2"},
index e255db0..2e6443b 100644 (file)
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
 #include <linux/seq_file.h>
-#include <linux/spinlock.h>
 #include <linux/types.h>
 #include <asm/io.h>
 
 #include <asm/smp.h>
+#include <asm/ldcw.h>
 
 #undef PARISC_IRQ_CR16_COUNTS
 
@@ -166,22 +166,36 @@ int arch_show_interrupts(struct seq_file *p, int prec)
        seq_printf(p, "%*s: ", prec, "STK");
        for_each_online_cpu(j)
                seq_printf(p, "%10u ", irq_stats(j)->kernel_stack_usage);
-       seq_printf(p, "  Kernel stack usage\n");
+       seq_puts(p, "  Kernel stack usage\n");
+# ifdef CONFIG_IRQSTACKS
+       seq_printf(p, "%*s: ", prec, "IST");
+       for_each_online_cpu(j)
+               seq_printf(p, "%10u ", irq_stats(j)->irq_stack_usage);
+       seq_puts(p, "  Interrupt stack usage\n");
+# endif
 #endif
 #ifdef CONFIG_SMP
        seq_printf(p, "%*s: ", prec, "RES");
        for_each_online_cpu(j)
                seq_printf(p, "%10u ", irq_stats(j)->irq_resched_count);
-       seq_printf(p, "  Rescheduling interrupts\n");
+       seq_puts(p, "  Rescheduling interrupts\n");
        seq_printf(p, "%*s: ", prec, "CAL");
        for_each_online_cpu(j)
                seq_printf(p, "%10u ", irq_stats(j)->irq_call_count);
-       seq_printf(p, "  Function call interrupts\n");
+       seq_puts(p, "  Function call interrupts\n");
 #endif
+       seq_printf(p, "%*s: ", prec, "UAH");
+       for_each_online_cpu(j)
+               seq_printf(p, "%10u ", irq_stats(j)->irq_unaligned_count);
+       seq_puts(p, "  Unaligned access handler traps\n");
+       seq_printf(p, "%*s: ", prec, "FPA");
+       for_each_online_cpu(j)
+               seq_printf(p, "%10u ", irq_stats(j)->irq_fpassist_count);
+       seq_puts(p, "  Floating point assist traps\n");
        seq_printf(p, "%*s: ", prec, "TLB");
        for_each_online_cpu(j)
                seq_printf(p, "%10u ", irq_stats(j)->irq_tlb_count);
-       seq_printf(p, "  TLB shootdowns\n");
+       seq_puts(p, "  TLB shootdowns\n");
        return 0;
 }
 
@@ -366,6 +380,24 @@ static inline int eirr_to_irq(unsigned long eirr)
        return (BITS_PER_LONG - bit) + TIMER_IRQ;
 }
 
+#ifdef CONFIG_IRQSTACKS
+/*
+ * IRQ STACK - used for irq handler
+ */
+#define IRQ_STACK_SIZE      (4096 << 2) /* 16k irq stack size */
+
+union irq_stack_union {
+       unsigned long stack[IRQ_STACK_SIZE/sizeof(unsigned long)];
+       volatile unsigned int slock[4];
+       volatile unsigned int lock[1];
+};
+
+DEFINE_PER_CPU(union irq_stack_union, irq_stack_union) = {
+               .slock = { 1,1,1,1 },
+       };
+#endif
+
+
 int sysctl_panic_on_stackoverflow = 1;
 
 static inline void stack_overflow_check(struct pt_regs *regs)
@@ -378,6 +410,7 @@ static inline void stack_overflow_check(struct pt_regs *regs)
        unsigned long sp = regs->gr[30];
        unsigned long stack_usage;
        unsigned int *last_usage;
+       int cpu = smp_processor_id();
 
        /* if sr7 != 0, we interrupted a userspace process which we do not want
         * to check for stack overflow. We will only check the kernel stack. */
@@ -386,7 +419,31 @@ static inline void stack_overflow_check(struct pt_regs *regs)
 
        /* calculate kernel stack usage */
        stack_usage = sp - stack_start;
-       last_usage = &per_cpu(irq_stat.kernel_stack_usage, smp_processor_id());
+#ifdef CONFIG_IRQSTACKS
+       if (likely(stack_usage <= THREAD_SIZE))
+               goto check_kernel_stack; /* found kernel stack */
+
+       /* check irq stack usage */
+       stack_start = (unsigned long) &per_cpu(irq_stack_union, cpu).stack;
+       stack_usage = sp - stack_start;
+
+       last_usage = &per_cpu(irq_stat.irq_stack_usage, cpu);
+       if (unlikely(stack_usage > *last_usage))
+               *last_usage = stack_usage;
+
+       if (likely(stack_usage < (IRQ_STACK_SIZE - STACK_MARGIN)))
+               return;
+
+       pr_emerg("stackcheck: %s will most likely overflow irq stack "
+                "(sp:%lx, stk bottom-top:%lx-%lx)\n",
+               current->comm, sp, stack_start, stack_start + IRQ_STACK_SIZE);
+       goto panic_check;
+
+check_kernel_stack:
+#endif
+
+       /* check kernel stack usage */
+       last_usage = &per_cpu(irq_stat.kernel_stack_usage, cpu);
 
        if (unlikely(stack_usage > *last_usage))
                *last_usage = stack_usage;
@@ -398,31 +455,66 @@ static inline void stack_overflow_check(struct pt_regs *regs)
                 "(sp:%lx, stk bottom-top:%lx-%lx)\n",
                current->comm, sp, stack_start, stack_start + THREAD_SIZE);
 
+#ifdef CONFIG_IRQSTACKS
+panic_check:
+#endif
        if (sysctl_panic_on_stackoverflow)
                panic("low stack detected by irq handler - check messages\n");
 #endif
 }
 
 #ifdef CONFIG_IRQSTACKS
-DEFINE_PER_CPU(union irq_stack_union, irq_stack_union);
+/* in entry.S: */
+void call_on_stack(unsigned long p1, void *func, unsigned long new_stack);
 
 static void execute_on_irq_stack(void *func, unsigned long param1)
 {
-       unsigned long *irq_stack_start;
+       union irq_stack_union *union_ptr;
        unsigned long irq_stack;
-       int cpu = smp_processor_id();
+       volatile unsigned int *irq_stack_in_use;
+
+       union_ptr = &per_cpu(irq_stack_union, smp_processor_id());
+       irq_stack = (unsigned long) &union_ptr->stack;
+       irq_stack = ALIGN(irq_stack + sizeof(irq_stack_union.slock),
+                        64); /* align for stack frame usage */
 
-       irq_stack_start = &per_cpu(irq_stack_union, cpu).stack[0];
-       irq_stack = (unsigned long) irq_stack_start;
-       irq_stack = ALIGN(irq_stack, 16); /* align for stack frame usage */
+       /* We may be called recursive. If we are already using the irq stack,
+        * just continue to use it. Use spinlocks to serialize
+        * the irq stack usage.
+        */
+       irq_stack_in_use = (volatile unsigned int *)__ldcw_align(union_ptr);
+       if (!__ldcw(irq_stack_in_use)) {
+               void (*direct_call)(unsigned long p1) = func;
 
-       BUG_ON(*irq_stack_start); /* report bug if we were called recursive. */
-       *irq_stack_start = 1;
+               /* We are using the IRQ stack already.
+                * Do direct call on current stack. */
+               direct_call(param1);
+               return;
+       }
 
        /* This is where we switch to the IRQ stack. */
        call_on_stack(param1, func, irq_stack);
 
-       *irq_stack_start = 0;
+       /* free up irq stack usage. */
+       *irq_stack_in_use = 1;
+}
+
+asmlinkage void do_softirq(void)
+{
+       __u32 pending;
+       unsigned long flags;
+
+       if (in_interrupt())
+               return;
+
+       local_irq_save(flags);
+
+       pending = local_softirq_pending();
+
+       if (pending)
+               execute_on_irq_stack(__do_softirq, 0);
+
+       local_irq_restore(flags);
 }
 #endif /* CONFIG_IRQSTACKS */
 
index 5e1de60..36d7f40 100644 (file)
@@ -605,14 +605,14 @@ ENTRY(copy_user_page_asm)
        convert_phys_for_tlb_insert20 %r26      /* convert phys addr to tlb insert format */
        convert_phys_for_tlb_insert20 %r23      /* convert phys addr to tlb insert format */
        depd            %r24,63,22, %r28        /* Form aliased virtual address 'to' */
-       depdi           0, 63,PAGE_SHIFT, %r28  /* Clear any offset bits */
+       depdi           0, 63,PAGE_SHIFT, %r28  /* Clear any offset bits */
        copy            %r28, %r29
        depdi           1, 41,1, %r29           /* Form aliased virtual address 'from' */
 #else
        extrw,u         %r26, 24,25, %r26       /* convert phys addr to tlb insert format */
        extrw,u         %r23, 24,25, %r23       /* convert phys addr to tlb insert format */
        depw            %r24, 31,22, %r28       /* Form aliased virtual address 'to' */
-       depwi           0, 31,12, %r28          /* Clear any offset bits */
+       depwi           0, 31,PAGE_SHIFT, %r28  /* Clear any offset bits */
        copy            %r28, %r29
        depwi           1, 9,1, %r29            /* Form aliased virtual address 'from' */
 #endif
@@ -762,7 +762,7 @@ ENTRY(clear_user_page_asm)
 #else
        extrw,u         %r26, 24,25, %r26       /* convert phys addr to tlb insert format */
        depw            %r25, 31,22, %r28       /* Form aliased virtual address 'to' */
-       depwi           0, 31,12, %r28          /* Clear any offset bits */
+       depwi           0, 31,PAGE_SHIFT, %r28  /* Clear any offset bits */
 #endif
 
        /* Purge any old translation */
@@ -846,7 +846,7 @@ ENTRY(flush_dcache_page_asm)
 #else
        extrw,u         %r26, 24,25, %r26       /* convert phys addr to tlb insert format */
        depw            %r25, 31,22, %r28       /* Form aliased virtual address 'to' */
-       depwi           0, 31,12, %r28          /* Clear any offset bits */
+       depwi           0, 31,PAGE_SHIFT, %r28  /* Clear any offset bits */
 #endif
 
        /* Purge any old translation */
@@ -918,11 +918,11 @@ ENTRY(flush_icache_page_asm)
 #endif
        convert_phys_for_tlb_insert20 %r26      /* convert phys addr to tlb insert format */
        depd            %r25, 63,22, %r28       /* Form aliased virtual address 'to' */
-       depdi           0, 63,PAGE_SHIFT, %r28  /* Clear any offset bits */
+       depdi           0, 63,PAGE_SHIFT, %r28  /* Clear any offset bits */
 #else
        extrw,u         %r26, 24,25, %r26       /* convert phys addr to tlb insert format */
        depw            %r25, 31,22, %r28       /* Form aliased virtual address 'to' */
-       depwi           0, 31,12, %r28          /* Clear any offset bits */
+       depwi           0, 31,PAGE_SHIFT, %r28  /* Clear any offset bits */
 #endif
 
        /* Purge any old translation */
index 76b63e7..1e95b20 100644 (file)
@@ -69,7 +69,8 @@ void __init setup_cmdline(char **cmdline_p)
                /* called from hpux boot loader */
                boot_command_line[0] = '\0';
        } else {
-               strcpy(boot_command_line, (char *)__va(boot_args[1]));
+               strlcpy(boot_command_line, (char *)__va(boot_args[1]),
+                       COMMAND_LINE_SIZE);
 
 #ifdef CONFIG_BLK_DEV_INITRD
                if (boot_args[2] != 0) /* did palo pass us a ramdisk? */
index f517e08..a134ff4 100644 (file)
@@ -59,11 +59,3 @@ asmlinkage long sys32_unimplemented(int r26, int r25, int r24, int r23,
        current->comm, current->pid, r20);
     return -ENOSYS;
 }
-
-asmlinkage long compat_sys_fanotify_mark(int fan_fd, int flags, u32 mask_hi,
-                                        u32 mask_lo, int fd,
-                                        const char __user *pathname)
-{
-       return sys_fanotify_mark(fan_fd, flags, ((u64)mask_hi << 32) | mask_lo,
-                                fd, pathname);
-}
index fe41a98..04e47c6 100644 (file)
@@ -646,6 +646,7 @@ void notrace handle_interruption(int code, struct pt_regs *regs)
        case 14:
                /* Assist Exception Trap, i.e. floating point exception. */
                die_if_kernel("Floating point exception", regs, 0); /* quiet */
+               __inc_irq_stat(irq_fpassist_count);
                handle_fpe(regs);
                return;
 
index 234e368..d7c0acb 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/signal.h>
 #include <linux/ratelimit.h>
 #include <asm/uaccess.h>
+#include <asm/hardirq.h>
 
 /* #define DEBUG_UNALIGNED 1 */
 
@@ -454,6 +455,8 @@ void handle_unaligned(struct pt_regs *regs)
        struct siginfo si;
        register int flop=0;    /* true if this is a flop */
 
+       __inc_irq_stat(irq_unaligned_count);
+
        /* log a message with pacing */
        if (user_mode(regs)) {
                if (current->thread.flags & PARISC_UAC_SIGBUS) {
index ce939ac..1c96564 100644 (file)
@@ -1069,7 +1069,7 @@ void flush_tlb_all(void)
 {
        int do_recycle;
 
-       inc_irq_stat(irq_tlb_count);
+       __inc_irq_stat(irq_tlb_count);
        do_recycle = 0;
        spin_lock(&sid_lock);
        if (dirty_space_ids > RECYCLE_THRESHOLD) {
@@ -1090,7 +1090,7 @@ void flush_tlb_all(void)
 #else
 void flush_tlb_all(void)
 {
-       inc_irq_stat(irq_tlb_count);
+       __inc_irq_stat(irq_tlb_count);
        spin_lock(&sid_lock);
        flush_tlb_all_local(NULL);
        recycle_sids();
index 5416e28..863d877 100644 (file)
@@ -262,8 +262,31 @@ config PPC_EARLY_DEBUG_OPAL_HVSI
          Select this to enable early debugging for the PowerNV platform
          using an "hvsi" console
 
+config PPC_EARLY_DEBUG_MEMCONS
+       bool "In memory console"
+       help
+         Select this to enable early debugging using an in memory console.
+         This console provides input and output buffers stored within the
+         kernel BSS and should be safe to select on any system. A debugger
+         can then be used to read kernel output or send input to the console.
 endchoice
 
+config PPC_MEMCONS_OUTPUT_SIZE
+       int "In memory console output buffer size"
+       depends on PPC_EARLY_DEBUG_MEMCONS
+       default 4096
+       help
+         Selects the size of the output buffer (in bytes) of the in memory
+         console.
+
+config PPC_MEMCONS_INPUT_SIZE
+       int "In memory console input buffer size"
+       depends on PPC_EARLY_DEBUG_MEMCONS
+       default 128
+       help
+         Selects the size of the input buffer (in bytes) of the in memory
+         console.
+
 config PPC_EARLY_DEBUG_OPAL
        def_bool y
        depends on PPC_EARLY_DEBUG_OPAL_RAW || PPC_EARLY_DEBUG_OPAL_HVSI
index f791962..139a830 100644 (file)
@@ -136,7 +136,6 @@ CONFIG_HID_SMARTJOYPLUS=m
 CONFIG_USB_HIDDEV=y
 CONFIG_USB=m
 CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
-CONFIG_USB_SUSPEND=y
 CONFIG_USB_MON=m
 CONFIG_USB_EHCI_HCD=m
 # CONFIG_USB_EHCI_HCD_PPC_OF is not set
diff --git a/arch/powerpc/include/asm/context_tracking.h b/arch/powerpc/include/asm/context_tracking.h
new file mode 100644 (file)
index 0000000..b6f5a33
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef _ASM_POWERPC_CONTEXT_TRACKING_H
+#define _ASM_POWERPC_CONTEXT_TRACKING_H
+
+#ifdef CONFIG_CONTEXT_TRACKING
+#define SCHEDULE_USER bl       .schedule_user
+#else
+#define SCHEDULE_USER bl       .schedule
+#endif
+
+#endif
index 26807e5..6f3887d 100644 (file)
@@ -176,6 +176,7 @@ extern const char *powerpc_base_platform;
 #define CPU_FTR_CFAR                   LONG_ASM_CONST(0x0100000000000000)
 #define        CPU_FTR_HAS_PPR                 LONG_ASM_CONST(0x0200000000000000)
 #define CPU_FTR_DAWR                   LONG_ASM_CONST(0x0400000000000000)
+#define CPU_FTR_DABRX                  LONG_ASM_CONST(0x0800000000000000)
 
 #ifndef __ASSEMBLY__
 
@@ -394,19 +395,20 @@ extern const char *powerpc_base_platform;
            CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | CPU_FTR_ARCH_201 | \
            CPU_FTR_ALTIVEC_COMP | CPU_FTR_CAN_NAP | CPU_FTR_MMCRA | \
            CPU_FTR_CP_USE_DCBTZ | CPU_FTR_STCX_CHECKS_ADDRESS | \
-           CPU_FTR_HVMODE)
+           CPU_FTR_HVMODE | CPU_FTR_DABRX)
 #define CPU_FTRS_POWER5        (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
            CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
            CPU_FTR_MMCRA | CPU_FTR_SMT | \
            CPU_FTR_COHERENT_ICACHE | CPU_FTR_PURR | \
-           CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB)
+           CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_DABRX)
 #define CPU_FTRS_POWER6 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
            CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
            CPU_FTR_MMCRA | CPU_FTR_SMT | \
            CPU_FTR_COHERENT_ICACHE | \
            CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \
            CPU_FTR_DSCR | CPU_FTR_UNALIGNED_LD_STD | \
-           CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_CFAR)
+           CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_CFAR | \
+           CPU_FTR_DABRX)
 #define CPU_FTRS_POWER7 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
            CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | CPU_FTR_ARCH_206 |\
            CPU_FTR_MMCRA | CPU_FTR_SMT | \
@@ -415,7 +417,7 @@ extern const char *powerpc_base_platform;
            CPU_FTR_DSCR | CPU_FTR_SAO  | CPU_FTR_ASYM_SMT | \
            CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \
            CPU_FTR_ICSWX | CPU_FTR_CFAR | CPU_FTR_HVMODE | \
-           CPU_FTR_VMX_COPY | CPU_FTR_HAS_PPR)
+           CPU_FTR_VMX_COPY | CPU_FTR_HAS_PPR | CPU_FTR_DABRX)
 #define CPU_FTRS_POWER8 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
            CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | CPU_FTR_ARCH_206 |\
            CPU_FTR_MMCRA | CPU_FTR_SMT | \
@@ -430,14 +432,15 @@ extern const char *powerpc_base_platform;
            CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
            CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \
            CPU_FTR_PAUSE_ZERO  | CPU_FTR_CELL_TB_BUG | CPU_FTR_CP_USE_DCBTZ | \
-           CPU_FTR_UNALIGNED_LD_STD)
+           CPU_FTR_UNALIGNED_LD_STD | CPU_FTR_DABRX)
 #define CPU_FTRS_PA6T (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
            CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_ALTIVEC_COMP | \
-           CPU_FTR_PURR | CPU_FTR_REAL_LE)
+           CPU_FTR_PURR | CPU_FTR_REAL_LE | CPU_FTR_DABRX)
 #define CPU_FTRS_COMPATIBLE    (CPU_FTR_USE_TB | CPU_FTR_PPCAS_ARCH_V2)
 
 #define CPU_FTRS_A2 (CPU_FTR_USE_TB | CPU_FTR_SMT | CPU_FTR_DBELL | \
-                    CPU_FTR_NOEXECUTE | CPU_FTR_NODSISRALIGN | CPU_FTR_ICSWX)
+                    CPU_FTR_NOEXECUTE | CPU_FTR_NODSISRALIGN | \
+                    CPU_FTR_ICSWX | CPU_FTR_DABRX )
 
 #ifdef __powerpc64__
 #ifdef CONFIG_PPC_BOOK3E
index 0df5464..681bc03 100644 (file)
@@ -52,6 +52,7 @@
 #define FW_FEATURE_BEST_ENERGY ASM_CONST(0x0000000080000000)
 #define FW_FEATURE_TYPE1_AFFINITY ASM_CONST(0x0000000100000000)
 #define FW_FEATURE_PRRN                ASM_CONST(0x0000000200000000)
+#define FW_FEATURE_OPALv3      ASM_CONST(0x0000000400000000)
 
 #ifndef __ASSEMBLY__
 
@@ -69,7 +70,8 @@ enum {
                FW_FEATURE_SET_MODE | FW_FEATURE_BEST_ENERGY |
                FW_FEATURE_TYPE1_AFFINITY | FW_FEATURE_PRRN,
        FW_FEATURE_PSERIES_ALWAYS = 0,
-       FW_FEATURE_POWERNV_POSSIBLE = FW_FEATURE_OPAL | FW_FEATURE_OPALv2,
+       FW_FEATURE_POWERNV_POSSIBLE = FW_FEATURE_OPAL | FW_FEATURE_OPALv2 |
+               FW_FEATURE_OPALv3,
        FW_FEATURE_POWERNV_ALWAYS = 0,
        FW_FEATURE_PS3_POSSIBLE = FW_FEATURE_LPAR | FW_FEATURE_PS3_LV1,
        FW_FEATURE_PS3_ALWAYS = FW_FEATURE_LPAR | FW_FEATURE_PS3_LV1,
index cf4df8e..0c7f2bf 100644 (file)
 #define H_GET_MPP              0x2D4
 #define H_HOME_NODE_ASSOCIATIVITY 0x2EC
 #define H_BEST_ENERGY          0x2F4
+#define H_XIRR_X               0x2FC
 #define H_RANDOM               0x300
 #define H_COP                  0x304
 #define H_GET_MPP_X            0x314
index d615b28..ba713f1 100644 (file)
@@ -96,11 +96,12 @@ static inline bool arch_irqs_disabled(void)
 #endif
 
 #define hard_irq_disable()     do {                    \
+       u8 _was_enabled = get_paca()->soft_enabled;     \
        __hard_irq_disable();                           \
-       if (local_paca->soft_enabled)                   \
-               trace_hardirqs_off();                   \
        get_paca()->soft_enabled = 0;                   \
        get_paca()->irq_happened |= PACA_IRQ_HARD_DIS;  \
+       if (_was_enabled)                               \
+               trace_hardirqs_off();                   \
 } while(0)
 
 static inline bool lazy_irq_pending(void)
index b9dd382..851bac7 100644 (file)
 #define BOOKE_INTERRUPT_DEBUG 15
 
 /* E500 */
-#define BOOKE_INTERRUPT_SPE_UNAVAIL 32
-#define BOOKE_INTERRUPT_SPE_FP_DATA 33
+#define BOOKE_INTERRUPT_SPE_ALTIVEC_UNAVAIL 32
+#define BOOKE_INTERRUPT_SPE_FP_DATA_ALTIVEC_ASSIST 33
+/*
+ * TODO: Unify 32-bit and 64-bit kernel exception handlers to use same defines
+ */
+#define BOOKE_INTERRUPT_SPE_UNAVAIL BOOKE_INTERRUPT_SPE_ALTIVEC_UNAVAIL
+#define BOOKE_INTERRUPT_SPE_FP_DATA BOOKE_INTERRUPT_SPE_FP_DATA_ALTIVEC_ASSIST
+#define BOOKE_INTERRUPT_ALTIVEC_UNAVAIL BOOKE_INTERRUPT_SPE_ALTIVEC_UNAVAIL
+#define BOOKE_INTERRUPT_ALTIVEC_ASSIST \
+                               BOOKE_INTERRUPT_SPE_FP_DATA_ALTIVEC_ASSIST
 #define BOOKE_INTERRUPT_SPE_FP_ROUND 34
 #define BOOKE_INTERRUPT_PERFORMANCE_MONITOR 35
 #define BOOKE_INTERRUPT_DOORBELL 36
 #define BOOKE_INTERRUPT_HV_SYSCALL 40
 #define BOOKE_INTERRUPT_HV_PRIV 41
 
-/* altivec */
-#define BOOKE_INTERRUPT_ALTIVEC_UNAVAIL 42
-#define BOOKE_INTERRUPT_ALTIVEC_ASSIST 43
-
 /* book3s */
 
 #define BOOK3S_INTERRUPT_SYSTEM_RESET  0x100
index b6c8b58..cbb9305 100644 (file)
@@ -243,7 +243,8 @@ enum OpalMCE_TlbErrorType {
 
 enum OpalThreadStatus {
        OPAL_THREAD_INACTIVE = 0x0,
-       OPAL_THREAD_STARTED = 0x1
+       OPAL_THREAD_STARTED = 0x1,
+       OPAL_THREAD_UNAVAILABLE = 0x2 /* opal-v3 */
 };
 
 enum OpalPciBusCompare {
@@ -563,6 +564,8 @@ extern void opal_nvram_init(void);
 
 extern int opal_machine_check(struct pt_regs *regs);
 
+extern void opal_shutdown(void);
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* __OPAL_H */
index 8b11b5b..2c1d8cb 100644 (file)
@@ -174,6 +174,8 @@ struct pci_dn {
 /* Get the pointer to a device_node's pci_dn */
 #define PCI_DN(dn)     ((struct pci_dn *) (dn)->data)
 
+extern struct pci_dn *pci_get_pdn(struct pci_dev *pdev);
+
 extern void * update_dn_pci_info(struct device_node *dn, void *data);
 
 static inline int pci_device_from_OF_node(struct device_node *np,
index 91acb12..b66ae72 100644 (file)
@@ -186,7 +186,7 @@ static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
 
 static inline pgtable_t pmd_pgtable(pmd_t pmd)
 {
-       return (pgtable_t)(pmd_val(pmd) & -sizeof(pte_t)*PTRS_PER_PTE);
+       return (pgtable_t)(pmd_val(pmd) & ~PMD_MASKED_BITS);
 }
 
 static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
index cea8496..2f1b6c5 100644 (file)
@@ -523,6 +523,17 @@ END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,946)
 #define PPC440EP_ERR42
 #endif
 
+/* The following stops all load and store data streams associated with stream
+ * ID (ie. streams created explicitly).  The embedded and server mnemonics for
+ * dcbt are different so we use machine "power4" here explicitly.
+ */
+#define DCBT_STOP_ALL_STREAM_IDS(scratch)      \
+.machine push ;                                        \
+.machine "power4" ;                            \
+       lis     scratch,0x60000000@h;           \
+       dcbt    r0,scratch,0b01010;             \
+.machine pop
+
 /*
  * toreal/fromreal/tophys/tovirt macros. 32-bit BookE makes them
  * keep the address intact to be compatible with code shared with
index d7e67ca..14a6583 100644 (file)
@@ -284,6 +284,12 @@ struct thread_struct {
        unsigned long   ebbrr;
        unsigned long   ebbhr;
        unsigned long   bescr;
+       unsigned long   siar;
+       unsigned long   sdar;
+       unsigned long   sier;
+       unsigned long   mmcr0;
+       unsigned long   mmcr2;
+       unsigned long   mmcra;
 #endif
 };
 
@@ -403,21 +409,16 @@ static inline void prefetchw(const void *x)
 #endif
 
 #ifdef CONFIG_PPC64
-static inline unsigned long get_clean_sp(struct pt_regs *regs, int is_32)
+static inline unsigned long get_clean_sp(unsigned long sp, int is_32)
 {
-       unsigned long sp;
-
        if (is_32)
-               sp = regs->gpr[1] & 0x0ffffffffUL;
-       else
-               sp = regs->gpr[1];
-
+               return sp & 0x0ffffffffUL;
        return sp;
 }
 #else
-static inline unsigned long get_clean_sp(struct pt_regs *regs, int is_32)
+static inline unsigned long get_clean_sp(unsigned long sp, int is_32)
 {
-       return regs->gpr[1];
+       return sp;
 }
 #endif
 
index 3e13e23..d836d94 100644 (file)
@@ -47,7 +47,7 @@
  * generic accessors and iterators here
  */
 #define __real_pte(e,p)        ((real_pte_t) { \
-                       (e), ((e) & _PAGE_COMBO) ? \
+                       (e), (pte_val(e) & _PAGE_COMBO) ? \
                                (pte_val(*((p) + PTRS_PER_PTE))) : 0 })
 #define __rpte_to_hidx(r,index)        ((pte_val((r).pte) & _PAGE_COMBO) ? \
         (((r).hidx >> ((index)<<2)) & 0xf) : ((pte_val((r).pte) >> 12) & 0xf))
index a613651..4a9e408 100644 (file)
 #define MSR_TM_TRANSACTIONAL(x)        (((x) & MSR_TS_MASK) == MSR_TS_T)
 #define MSR_TM_SUSPENDED(x)    (((x) & MSR_TS_MASK) == MSR_TS_S)
 
-/* Reason codes describing kernel causes for transaction aborts.  By
-   convention, bit0 is copied to TEXASR[56] (IBM bit 7) which is set if
-   the failure is persistent.
-*/
-#define TM_CAUSE_RESCHED       0xfe
-#define TM_CAUSE_TLBI          0xfc
-#define TM_CAUSE_FAC_UNAV      0xfa
-#define TM_CAUSE_SYSCALL       0xf9 /* Persistent */
-#define TM_CAUSE_MISC          0xf6
-#define TM_CAUSE_SIGNAL                0xf4
-
 #if defined(CONFIG_PPC_BOOK3S_64)
 #define MSR_64BIT      MSR_SF
 
index a8bc2bb..34fd704 100644 (file)
@@ -264,6 +264,8 @@ extern void rtas_progress(char *s, unsigned short hex);
 extern void rtas_initialize(void);
 extern int rtas_suspend_cpu(struct rtas_suspend_me_data *data);
 extern int rtas_suspend_last_cpu(struct rtas_suspend_me_data *data);
+extern int rtas_online_cpus_mask(cpumask_var_t cpus);
+extern int rtas_offline_cpus_mask(cpumask_var_t cpus);
 extern int rtas_ibm_suspend_me(struct rtas_args *);
 
 struct rtc_time;
index fbe66c4..9322c28 100644 (file)
@@ -3,5 +3,8 @@
 
 #define __ARCH_HAS_SA_RESTORER
 #include <uapi/asm/signal.h>
+#include <uapi/asm/ptrace.h>
+
+extern unsigned long get_tm_stackpointer(struct pt_regs *regs);
 
 #endif /* _ASM_POWERPC_SIGNAL_H */
index 8ceea14..ba7b197 100644 (file)
@@ -97,7 +97,7 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_PERFMON_CTXSW      6       /* perfmon needs ctxsw calls */
 #define TIF_SYSCALL_AUDIT      7       /* syscall auditing active */
 #define TIF_SINGLESTEP         8       /* singlestepping active */
-#define TIF_MEMDIE             9       /* is terminating due to OOM killer */
+#define TIF_NOHZ               9       /* in adaptive nohz mode */
 #define TIF_SECCOMP            10      /* secure computing */
 #define TIF_RESTOREALL         11      /* Restore all regs (implies NOERROR) */
 #define TIF_NOERROR            12      /* Force successful syscall return */
@@ -106,6 +106,7 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_SYSCALL_TRACEPOINT 15      /* syscall tracepoint instrumentation */
 #define TIF_EMULATE_STACK_STORE        16      /* Is an instruction emulation
                                                for stack store? */
+#define TIF_MEMDIE             17      /* is terminating due to OOM killer */
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE     (1<<TIF_SYSCALL_TRACE)
@@ -124,8 +125,10 @@ static inline struct thread_info *current_thread_info(void)
 #define _TIF_UPROBE            (1<<TIF_UPROBE)
 #define _TIF_SYSCALL_TRACEPOINT        (1<<TIF_SYSCALL_TRACEPOINT)
 #define _TIF_EMULATE_STACK_STORE       (1<<TIF_EMULATE_STACK_STORE)
+#define _TIF_NOHZ              (1<<TIF_NOHZ)
 #define _TIF_SYSCALL_T_OR_A    (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \
-                                _TIF_SECCOMP | _TIF_SYSCALL_TRACEPOINT)
+                                _TIF_SECCOMP | _TIF_SYSCALL_TRACEPOINT | \
+                                _TIF_NOHZ)
 
 #define _TIF_USER_WORK_MASK    (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
                                 _TIF_NOTIFY_RESUME | _TIF_UPROBE)
index 4b4449a..9dfbc34 100644 (file)
@@ -5,6 +5,8 @@
  * Copyright 2012 Matt Evans & Michael Neuling, IBM Corporation.
  */
 
+#include <uapi/asm/tm.h>
+
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
 extern void do_load_up_transact_fpu(struct thread_struct *thread);
 extern void do_load_up_transact_altivec(struct thread_struct *thread);
index 5a7510e..dc59091 100644 (file)
@@ -52,6 +52,7 @@ extern void __init udbg_init_40x_realmode(void);
 extern void __init udbg_init_cpm(void);
 extern void __init udbg_init_usbgecko(void);
 extern void __init udbg_init_wsp(void);
+extern void __init udbg_init_memcons(void);
 extern void __init udbg_init_ehv_bc(void);
 extern void __init udbg_init_ps3gelic(void);
 extern void __init udbg_init_debug_opal_raw(void);
index f7bca63..5182c86 100644 (file)
@@ -40,6 +40,7 @@ header-y += statfs.h
 header-y += swab.h
 header-y += termbits.h
 header-y += termios.h
+header-y += tm.h
 header-y += types.h
 header-y += ucontext.h
 header-y += unistd.h
diff --git a/arch/powerpc/include/uapi/asm/tm.h b/arch/powerpc/include/uapi/asm/tm.h
new file mode 100644 (file)
index 0000000..85059a0
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef _ASM_POWERPC_TM_H
+#define _ASM_POWERPC_TM_H
+
+/* Reason codes describing kernel causes for transaction aborts.  By
+ * convention, bit0 is copied to TEXASR[56] (IBM bit 7) which is set if
+ * the failure is persistent.  PAPR saves 0xff-0xe0 for the hypervisor.
+ */
+#define TM_CAUSE_PERSISTENT    0x01
+#define TM_CAUSE_RESCHED       0xde
+#define TM_CAUSE_TLBI          0xdc
+#define TM_CAUSE_FAC_UNAV      0xda
+#define TM_CAUSE_SYSCALL       0xd8  /* future use */
+#define TM_CAUSE_MISC          0xd6  /* future use */
+#define TM_CAUSE_SIGNAL                0xd4
+#define TM_CAUSE_ALIGNMENT     0xd2
+#define TM_CAUSE_EMULATE       0xd0
+
+#endif
index b51a97c..6f16ffa 100644 (file)
@@ -127,6 +127,12 @@ int main(void)
        DEFINE(THREAD_BESCR, offsetof(struct thread_struct, bescr));
        DEFINE(THREAD_EBBHR, offsetof(struct thread_struct, ebbhr));
        DEFINE(THREAD_EBBRR, offsetof(struct thread_struct, ebbrr));
+       DEFINE(THREAD_SIAR, offsetof(struct thread_struct, siar));
+       DEFINE(THREAD_SDAR, offsetof(struct thread_struct, sdar));
+       DEFINE(THREAD_SIER, offsetof(struct thread_struct, sier));
+       DEFINE(THREAD_MMCR0, offsetof(struct thread_struct, mmcr0));
+       DEFINE(THREAD_MMCR2, offsetof(struct thread_struct, mmcr2));
+       DEFINE(THREAD_MMCRA, offsetof(struct thread_struct, mmcra));
 #endif
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
        DEFINE(PACATMSCRATCH, offsetof(struct paca_struct, tm_scratch));
index a283b64..18b5b9c 100644 (file)
@@ -135,8 +135,12 @@ __init_HFSCR:
        blr
 
 __init_TLB:
-       /* Clear the TLB */
-       li      r6,128
+       /*
+        * Clear the TLB using the "IS 3" form of tlbiel instruction
+        * (invalidate by congruence class). P7 has 128 CCs, P8 has 512
+        * so we just always do 512
+        */
+       li      r6,512
        mtctr   r6
        li      r7,0xc00        /* IS field = 0b11 */
        ptesync
index c60bbec..2a45d0f 100644 (file)
@@ -452,7 +452,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .mmu_features           = MMU_FTRS_POWER8,
                .icache_bsize           = 128,
                .dcache_bsize           = 128,
-               .oprofile_type          = PPC_OPROFILE_POWER4,
+               .oprofile_type          = PPC_OPROFILE_INVALID,
                .oprofile_cpu_type      = "ppc64/ibm-compat-v1",
                .cpu_setup              = __setup_cpu_power8,
                .cpu_restore            = __restore_cpu_power8,
@@ -482,7 +482,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .cpu_name               = "POWER7+ (raw)",
                .cpu_features           = CPU_FTRS_POWER7,
                .cpu_user_features      = COMMON_USER_POWER7,
-               .cpu_user_features      = COMMON_USER2_POWER7,
+               .cpu_user_features2     = COMMON_USER2_POWER7,
                .mmu_features           = MMU_FTRS_POWER7,
                .icache_bsize           = 128,
                .dcache_bsize           = 128,
@@ -507,7 +507,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .num_pmcs               = 6,
                .pmc_type               = PPC_PMC_IBM,
                .oprofile_cpu_type      = "ppc64/power8",
-               .oprofile_type          = PPC_OPROFILE_POWER4,
+               .oprofile_type          = PPC_OPROFILE_INVALID,
                .cpu_setup              = __setup_cpu_power8,
                .cpu_restore            = __restore_cpu_power8,
                .platform               = "power8",
index e514de5..22b45a4 100644 (file)
@@ -439,8 +439,6 @@ ret_from_fork:
 ret_from_kernel_thread:
        REST_NVGPRS(r1)
        bl      schedule_tail
-       li      r3,0
-       stw     r3,0(r1)
        mtlr    r14
        mr      r3,r15
        PPC440EP_ERR42
@@ -851,7 +849,7 @@ resume_kernel:
        /* check current_thread_info, _TIF_EMULATE_STACK_STORE */
        CURRENT_THREAD_INFO(r9, r1)
        lwz     r8,TI_FLAGS(r9)
-       andis.  r8,r8,_TIF_EMULATE_STACK_STORE@h
+       andis.  r0,r8,_TIF_EMULATE_STACK_STORE@h
        beq+    1f
 
        addi    r8,r1,INT_FRAME_SIZE    /* Get the kprobed function entry */
index 3fe5259..8741c85 100644 (file)
@@ -33,6 +33,7 @@
 #include <asm/irqflags.h>
 #include <asm/ftrace.h>
 #include <asm/hw_irq.h>
+#include <asm/context_tracking.h>
 
 /*
  * System calls.
@@ -150,7 +151,7 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR)
        CURRENT_THREAD_INFO(r11, r1)
        ld      r10,TI_FLAGS(r11)
        andi.   r11,r10,_TIF_SYSCALL_T_OR_A
-       bne-    syscall_dotrace
+       bne     syscall_dotrace
 .Lsyscall_dotrace_cont:
        cmpldi  0,r0,NR_syscalls
        bge-    syscall_enosys
@@ -376,8 +377,6 @@ _GLOBAL(ret_from_fork)
 _GLOBAL(ret_from_kernel_thread)
        bl      .schedule_tail
        REST_NVGPRS(r1)
-       li      r3,0
-       std     r3,0(r1)
        ld      r14, 0(r14)
        mtlr    r14
        mr      r3,r15
@@ -488,6 +487,13 @@ BEGIN_FTR_SECTION
        ldarx   r6,0,r1
 END_FTR_SECTION_IFSET(CPU_FTR_STCX_CHECKS_ADDRESS)
 
+#ifdef CONFIG_PPC_BOOK3S
+/* Cancel all explict user streams as they will have no use after context
+ * switch and will stop the HW from creating streams itself
+ */
+       DCBT_STOP_ALL_STREAM_IDS(r6)
+#endif
+
        addi    r6,r4,-THREAD   /* Convert THREAD to 'current' */
        std     r6,PACACURRENT(r13)     /* Set new 'current' */
 
@@ -634,7 +640,7 @@ _GLOBAL(ret_from_except_lite)
        andi.   r0,r4,_TIF_NEED_RESCHED
        beq     1f
        bl      .restore_interrupts
-       bl      .schedule
+       SCHEDULE_USER
        b       .ret_from_except_lite
 
 1:     bl      .save_nvgprs
index 42a756e..645170a 100644 (file)
@@ -489,7 +489,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
         */
 
        mfspr   r14,SPRN_DBSR           /* check single-step/branch taken */
-       andis.  r15,r14,DBSR_IC@h
+       andis.  r15,r14,(DBSR_IC|DBSR_BT)@h
        beq+    1f
 
        LOAD_REG_IMMEDIATE(r14,interrupt_base_book3e)
@@ -500,7 +500,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
        bge+    cr1,1f
 
        /* here it looks like we got an inappropriate debug exception. */
-       lis     r14,DBSR_IC@h           /* clear the IC event */
+       lis     r14,(DBSR_IC|DBSR_BT)@h         /* clear the event */
        rlwinm  r11,r11,0,~MSR_DE       /* clear DE in the CSRR1 value */
        mtspr   SPRN_DBSR,r14
        mtspr   SPRN_CSRR1,r11
@@ -555,7 +555,7 @@ kernel_dbg_exc:
         */
 
        mfspr   r14,SPRN_DBSR           /* check single-step/branch taken */
-       andis.  r15,r14,DBSR_IC@h
+       andis.  r15,r14,(DBSR_IC|DBSR_BT)@h
        beq+    1f
 
        LOAD_REG_IMMEDIATE(r14,interrupt_base_book3e)
@@ -566,7 +566,7 @@ kernel_dbg_exc:
        bge+    cr1,1f
 
        /* here it looks like we got an inappropriate debug exception. */
-       lis     r14,DBSR_IC@h           /* clear the IC event */
+       lis     r14,(DBSR_IC|DBSR_BT)@h         /* clear the event */
        rlwinm  r11,r11,0,~MSR_DE       /* clear DE in the DSRR1 value */
        mtspr   SPRN_DBSR,r14
        mtspr   SPRN_DSRR1,r11
index e6eba1b..e783453 100644 (file)
@@ -454,38 +454,14 @@ BEGIN_FTR_SECTION
        xori    r10,r10,(MSR_FE0|MSR_FE1)
        mtmsrd  r10
        sync
-       fmr     0,0
-       fmr     1,1
-       fmr     2,2
-       fmr     3,3
-       fmr     4,4
-       fmr     5,5
-       fmr     6,6
-       fmr     7,7
-       fmr     8,8
-       fmr     9,9
-       fmr     10,10
-       fmr     11,11
-       fmr     12,12
-       fmr     13,13
-       fmr     14,14
-       fmr     15,15
-       fmr     16,16
-       fmr     17,17
-       fmr     18,18
-       fmr     19,19
-       fmr     20,20
-       fmr     21,21
-       fmr     22,22
-       fmr     23,23
-       fmr     24,24
-       fmr     25,25
-       fmr     26,26
-       fmr     27,27
-       fmr     28,28
-       fmr     29,29
-       fmr     30,30
-       fmr     31,31
+
+#define FMR2(n)  fmr (n), (n) ; fmr n+1, n+1
+#define FMR4(n)  FMR2(n) ; FMR2(n+2)
+#define FMR8(n)  FMR4(n) ; FMR4(n+4)
+#define FMR16(n) FMR8(n) ; FMR8(n+8)
+#define FMR32(n) FMR16(n) ; FMR16(n+16)
+       FMR32(0)
+
 FTR_SECTION_ELSE
 /*
  * To denormalise we need to move a copy of the register to itself.
@@ -495,39 +471,25 @@ FTR_SECTION_ELSE
        oris    r10,r10,MSR_VSX@h
        mtmsrd  r10
        sync
-       XVCPSGNDP(0,0,0)
-       XVCPSGNDP(1,1,1)
-       XVCPSGNDP(2,2,2)
-       XVCPSGNDP(3,3,3)
-       XVCPSGNDP(4,4,4)
-       XVCPSGNDP(5,5,5)
-       XVCPSGNDP(6,6,6)
-       XVCPSGNDP(7,7,7)
-       XVCPSGNDP(8,8,8)
-       XVCPSGNDP(9,9,9)
-       XVCPSGNDP(10,10,10)
-       XVCPSGNDP(11,11,11)
-       XVCPSGNDP(12,12,12)
-       XVCPSGNDP(13,13,13)
-       XVCPSGNDP(14,14,14)
-       XVCPSGNDP(15,15,15)
-       XVCPSGNDP(16,16,16)
-       XVCPSGNDP(17,17,17)
-       XVCPSGNDP(18,18,18)
-       XVCPSGNDP(19,19,19)
-       XVCPSGNDP(20,20,20)
-       XVCPSGNDP(21,21,21)
-       XVCPSGNDP(22,22,22)
-       XVCPSGNDP(23,23,23)
-       XVCPSGNDP(24,24,24)
-       XVCPSGNDP(25,25,25)
-       XVCPSGNDP(26,26,26)
-       XVCPSGNDP(27,27,27)
-       XVCPSGNDP(28,28,28)
-       XVCPSGNDP(29,29,29)
-       XVCPSGNDP(30,30,30)
-       XVCPSGNDP(31,31,31)
+
+#define XVCPSGNDP2(n) XVCPSGNDP(n,n,n) ; XVCPSGNDP(n+1,n+1,n+1)
+#define XVCPSGNDP4(n) XVCPSGNDP2(n) ; XVCPSGNDP2(n+2)
+#define XVCPSGNDP8(n) XVCPSGNDP4(n) ; XVCPSGNDP4(n+4)
+#define XVCPSGNDP16(n) XVCPSGNDP8(n) ; XVCPSGNDP8(n+8)
+#define XVCPSGNDP32(n) XVCPSGNDP16(n) ; XVCPSGNDP16(n+16)
+       XVCPSGNDP32(0)
+
 ALT_FTR_SECTION_END_IFCLR(CPU_FTR_ARCH_206)
+
+BEGIN_FTR_SECTION
+       b       denorm_done
+END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
+/*
+ * To denormalise we need to move a copy of the register to itself.
+ * For POWER8 we need to do that for all 64 VSX registers
+ */
+       XVCPSGNDP32(32)
+denorm_done:
        mtspr   SPRN_HSRR0,r11
        mtcrf   0x80,r9
        ld      r9,PACA_EXGEN+EX_R9(r13)
index 466a290..611acdf 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/cpu.h>
+#include <linux/hardirq.h>
 
 #include <asm/page.h>
 #include <asm/current.h>
@@ -335,10 +336,13 @@ void default_machine_kexec(struct kimage *image)
        pr_debug("kexec: Starting switchover sequence.\n");
 
        /* switch to a staticly allocated stack.  Based on irq stack code.
+        * We setup preempt_count to avoid using VMX in memcpy.
         * XXX: the task struct will likely be invalid once we do the copy!
         */
        kexec_stack.thread_info.task = current_thread_info()->task;
        kexec_stack.thread_info.flags = 0;
+       kexec_stack.thread_info.preempt_count = HARDIRQ_OFFSET;
+       kexec_stack.thread_info.cpu = current_thread_info()->cpu;
 
        /* We need a static PACA, too; copy this CPU's PACA over and switch to
         * it.  Also poison per_cpu_offset to catch anyone using non-static
index 19e096b..e469f30 100644 (file)
@@ -657,6 +657,17 @@ _GLOBAL(__ucmpdi2)
        li      r3,2
        blr
 
+_GLOBAL(__bswapdi2)
+       rotlwi  r9,r4,8
+       rotlwi  r10,r3,8
+       rlwimi  r9,r4,24,0,7
+       rlwimi  r10,r3,24,0,7
+       rlwimi  r9,r4,24,16,23
+       rlwimi  r10,r3,24,16,23
+       mr      r3,r9
+       mr      r4,r10
+       blr
+
 _GLOBAL(abs)
        srawi   r4,r3,31
        xor     r3,r3,r4
index 5cfa800..6820e45 100644 (file)
@@ -234,6 +234,17 @@ _GLOBAL(__flush_dcache_icache)
        isync
        blr
 
+_GLOBAL(__bswapdi2)
+       srdi    r8,r3,32
+       rlwinm  r7,r3,8,0xffffffff
+       rlwimi  r7,r3,24,0,7
+       rlwinm  r9,r8,8,0xffffffff
+       rlwimi  r7,r3,24,16,23
+       rlwimi  r9,r8,24,0,7
+       rlwimi  r9,r8,24,16,23
+       sldi    r7,r7,32
+       or      r3,r7,r9
+       blr
 
 #if defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE)
 /*
index f5c5c90..eabeec9 100644 (file)
@@ -359,7 +359,6 @@ static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp,
                                      enum pci_mmap_state mmap_state,
                                      int write_combine)
 {
-       unsigned long prot = pgprot_val(protection);
 
        /* Write combine is always 0 on non-memory space mappings. On
         * memory space, if the user didn't pass 1, we check for a
@@ -376,9 +375,9 @@ static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp,
 
        /* XXX would be nice to have a way to ask for write-through */
        if (write_combine)
-               return pgprot_noncached_wc(prot);
+               return pgprot_noncached_wc(protection);
        else
-               return pgprot_noncached(prot);
+               return pgprot_noncached(protection);
 }
 
 /*
@@ -658,15 +657,6 @@ void pci_resource_to_user(const struct pci_dev *dev, int bar,
  *     ranges. However, some machines (thanks Apple !) tend to split their
  *     space into lots of small contiguous ranges. So we have to coalesce.
  *
- *   - We can only cope with all memory ranges having the same offset
- *     between CPU addresses and PCI addresses. Unfortunately, some bridges
- *     are setup for a large 1:1 mapping along with a small "window" which
- *     maps PCI address 0 to some arbitrary high address of the CPU space in
- *     order to give access to the ISA memory hole.
- *     The way out of here that I've chosen for now is to always set the
- *     offset based on the first resource found, then override it if we
- *     have a different offset and the previous was set by an ISA hole.
- *
  *   - Some busses have IO space not starting at 0, which causes trouble with
  *     the way we do our IO resource renumbering. The code somewhat deals with
  *     it for 64 bits but I would expect problems on 32 bits.
@@ -681,10 +671,9 @@ void pci_process_bridge_OF_ranges(struct pci_controller *hose,
        int rlen;
        int pna = of_n_addr_cells(dev);
        int np = pna + 5;
-       int memno = 0, isa_hole = -1;
+       int memno = 0;
        u32 pci_space;
        unsigned long long pci_addr, cpu_addr, pci_next, cpu_next, size;
-       unsigned long long isa_mb = 0;
        struct resource *res;
 
        printk(KERN_INFO "PCI host bridge %s %s ranges:\n",
@@ -778,8 +767,6 @@ void pci_process_bridge_OF_ranges(struct pci_controller *hose,
                        }
                        /* Handles ISA memory hole space here */
                        if (pci_addr == 0) {
-                               isa_mb = cpu_addr;
-                               isa_hole = memno;
                                if (primary || isa_mem_base == 0)
                                        isa_mem_base = cpu_addr;
                                hose->isa_mem_phys = cpu_addr;
@@ -840,6 +827,7 @@ static void pcibios_fixup_resources(struct pci_dev *dev)
        }
        for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
                struct resource *res = dev->resource + i;
+               struct pci_bus_region reg;
                if (!res->flags)
                        continue;
 
@@ -848,8 +836,9 @@ static void pcibios_fixup_resources(struct pci_dev *dev)
                 * at 0 as unset as well, except if PCI_PROBE_ONLY is also set
                 * since in that case, we don't want to re-assign anything
                 */
+               pcibios_resource_to_bus(dev, &reg, res);
                if (pci_has_flag(PCI_REASSIGN_ALL_RSRC) ||
-                   (res->start == 0 && !pci_has_flag(PCI_PROBE_ONLY))) {
+                   (reg.start == 0 && !pci_has_flag(PCI_PROBE_ONLY))) {
                        /* Only print message if not re-assigning */
                        if (!pci_has_flag(PCI_REASSIGN_ALL_RSRC))
                                pr_debug("PCI:%s Resource %d %016llx-%016llx [%x] "
@@ -1521,9 +1510,10 @@ static void pcibios_setup_phb_resources(struct pci_controller *hose,
        for (i = 0; i < 3; ++i) {
                res = &hose->mem_resources[i];
                if (!res->flags) {
-                       printk(KERN_ERR "PCI: Memory resource 0 not set for "
-                              "host bridge %s (domain %d)\n",
-                              hose->dn->full_name, hose->global_number);
+                       if (i == 0)
+                               printk(KERN_ERR "PCI: Memory resource 0 not set for "
+                                      "host bridge %s (domain %d)\n",
+                                      hose->dn->full_name, hose->global_number);
                        continue;
                }
                offset = hose->mem_offset[i];
index 873050d..2e86296 100644 (file)
@@ -266,3 +266,13 @@ int pcibus_to_node(struct pci_bus *bus)
 }
 EXPORT_SYMBOL(pcibus_to_node);
 #endif
+
+static void quirk_radeon_32bit_msi(struct pci_dev *dev)
+{
+       struct pci_dn *pdn = pci_get_pdn(dev);
+
+       if (pdn)
+               pdn->force_32bit_msi = 1;
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x68f2, quirk_radeon_32bit_msi);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0xaa68, quirk_radeon_32bit_msi);
index e7af165..df03844 100644 (file)
 #include <asm/ppc-pci.h>
 #include <asm/firmware.h>
 
+struct pci_dn *pci_get_pdn(struct pci_dev *pdev)
+{
+       struct device_node *dn = pci_device_to_OF_node(pdev);
+       if (!dn)
+               return NULL;
+       return PCI_DN(dn);
+}
+
 /*
  * Traverse_func that inits the PCI fields of the device node.
  * NOTE: this *must* be done before read/write config to the device.
index 78b8766..c296665 100644 (file)
@@ -143,7 +143,8 @@ EXPORT_SYMBOL(__lshrdi3);
 int __ucmpdi2(unsigned long long, unsigned long long);
 EXPORT_SYMBOL(__ucmpdi2);
 #endif
-
+long long __bswapdi2(long long);
+EXPORT_SYMBOL(__bswapdi2);
 EXPORT_SYMBOL(memcpy);
 EXPORT_SYMBOL(memset);
 EXPORT_SYMBOL(memmove);
index ceb4e7b..b0f3e3f 100644 (file)
@@ -339,6 +339,13 @@ static void set_debug_reg_defaults(struct thread_struct *thread)
 
 static void prime_debug_regs(struct thread_struct *thread)
 {
+       /*
+        * We could have inherited MSR_DE from userspace, since
+        * it doesn't get cleared on exception entry.  Make sure
+        * MSR_DE is clear before we enable any debug events.
+        */
+       mtmsr(mfmsr() & ~MSR_DE);
+
        mtspr(SPRN_IAC1, thread->iac1);
        mtspr(SPRN_IAC2, thread->iac2);
 #if CONFIG_PPC_ADV_DEBUG_IACS > 2
@@ -392,7 +399,8 @@ static inline int __set_dabr(unsigned long dabr, unsigned long dabrx)
 static inline int __set_dabr(unsigned long dabr, unsigned long dabrx)
 {
        mtspr(SPRN_DABR, dabr);
-       mtspr(SPRN_DABRX, dabrx);
+       if (cpu_has_feature(CPU_FTR_DABRX))
+               mtspr(SPRN_DABRX, dabrx);
        return 0;
 }
 #else
@@ -971,6 +979,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
         * do some house keeping and then return from the fork or clone
         * system call, using the stack frame created above.
         */
+       ((unsigned long *)sp)[0] = 0;
        sp -= sizeof(struct pt_regs);
        kregs = (struct pt_regs *) sp;
        sp -= STACK_FRAME_OVERHEAD;
index 3b14d32..98c2fc1 100644 (file)
@@ -32,6 +32,7 @@
 #include <trace/syscall.h>
 #include <linux/hw_breakpoint.h>
 #include <linux/perf_event.h>
+#include <linux/context_tracking.h>
 
 #include <asm/uaccess.h>
 #include <asm/page.h>
@@ -1788,6 +1789,8 @@ long do_syscall_trace_enter(struct pt_regs *regs)
 {
        long ret = 0;
 
+       user_exit();
+
        secure_computing_strict(regs->gpr[0]);
 
        if (test_thread_flag(TIF_SYSCALL_TRACE) &&
@@ -1832,4 +1835,6 @@ void do_syscall_trace_leave(struct pt_regs *regs)
        step = test_thread_flag(TIF_SINGLESTEP);
        if (step || test_thread_flag(TIF_SYSCALL_TRACE))
                tracehook_report_syscall_exit(regs, step);
+
+       user_enter();
 }
index 1fd6e7b..52add6f 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/init.h>
 #include <linux/capability.h>
 #include <linux/delay.h>
+#include <linux/cpu.h>
 #include <linux/smp.h>
 #include <linux/completion.h>
 #include <linux/cpumask.h>
@@ -807,6 +808,95 @@ static void rtas_percpu_suspend_me(void *info)
        __rtas_suspend_cpu((struct rtas_suspend_me_data *)info, 1);
 }
 
+enum rtas_cpu_state {
+       DOWN,
+       UP,
+};
+
+#ifndef CONFIG_SMP
+static int rtas_cpu_state_change_mask(enum rtas_cpu_state state,
+                               cpumask_var_t cpus)
+{
+       if (!cpumask_empty(cpus)) {
+               cpumask_clear(cpus);
+               return -EINVAL;
+       } else
+               return 0;
+}
+#else
+/* On return cpumask will be altered to indicate CPUs changed.
+ * CPUs with states changed will be set in the mask,
+ * CPUs with status unchanged will be unset in the mask. */
+static int rtas_cpu_state_change_mask(enum rtas_cpu_state state,
+                               cpumask_var_t cpus)
+{
+       int cpu;
+       int cpuret = 0;
+       int ret = 0;
+
+       if (cpumask_empty(cpus))
+               return 0;
+
+       for_each_cpu(cpu, cpus) {
+               switch (state) {
+               case DOWN:
+                       cpuret = cpu_down(cpu);
+                       break;
+               case UP:
+                       cpuret = cpu_up(cpu);
+                       break;
+               }
+               if (cpuret) {
+                       pr_debug("%s: cpu_%s for cpu#%d returned %d.\n",
+                                       __func__,
+                                       ((state == UP) ? "up" : "down"),
+                                       cpu, cpuret);
+                       if (!ret)
+                               ret = cpuret;
+                       if (state == UP) {
+                               /* clear bits for unchanged cpus, return */
+                               cpumask_shift_right(cpus, cpus, cpu);
+                               cpumask_shift_left(cpus, cpus, cpu);
+                               break;
+                       } else {
+                               /* clear bit for unchanged cpu, continue */
+                               cpumask_clear_cpu(cpu, cpus);
+                       }
+               }
+       }
+
+       return ret;
+}
+#endif
+
+int rtas_online_cpus_mask(cpumask_var_t cpus)
+{
+       int ret;
+
+       ret = rtas_cpu_state_change_mask(UP, cpus);
+
+       if (ret) {
+               cpumask_var_t tmp_mask;
+
+               if (!alloc_cpumask_var(&tmp_mask, GFP_TEMPORARY))
+                       return ret;
+
+               /* Use tmp_mask to preserve cpus mask from first failure */
+               cpumask_copy(tmp_mask, cpus);
+               rtas_offline_cpus_mask(tmp_mask);
+               free_cpumask_var(tmp_mask);
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL(rtas_online_cpus_mask);
+
+int rtas_offline_cpus_mask(cpumask_var_t cpus)
+{
+       return rtas_cpu_state_change_mask(DOWN, cpus);
+}
+EXPORT_SYMBOL(rtas_offline_cpus_mask);
+
 int rtas_ibm_suspend_me(struct rtas_args *args)
 {
        long state;
@@ -814,6 +904,8 @@ int rtas_ibm_suspend_me(struct rtas_args *args)
        unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
        struct rtas_suspend_me_data data;
        DECLARE_COMPLETION_ONSTACK(done);
+       cpumask_var_t offline_mask;
+       int cpuret;
 
        if (!rtas_service_present("ibm,suspend-me"))
                return -ENOSYS;
@@ -837,11 +929,24 @@ int rtas_ibm_suspend_me(struct rtas_args *args)
                return 0;
        }
 
+       if (!alloc_cpumask_var(&offline_mask, GFP_TEMPORARY))
+               return -ENOMEM;
+
        atomic_set(&data.working, 0);
        atomic_set(&data.done, 0);
        atomic_set(&data.error, 0);
        data.token = rtas_token("ibm,suspend-me");
        data.complete = &done;
+
+       /* All present CPUs must be online */
+       cpumask_andnot(offline_mask, cpu_present_mask, cpu_online_mask);
+       cpuret = rtas_online_cpus_mask(offline_mask);
+       if (cpuret) {
+               pr_err("%s: Could not bring present CPUs online.\n", __func__);
+               atomic_set(&data.error, cpuret);
+               goto out;
+       }
+
        stop_topology_update();
 
        /* Call function on all CPUs.  One of us will make the
@@ -857,6 +962,14 @@ int rtas_ibm_suspend_me(struct rtas_args *args)
 
        start_topology_update();
 
+       /* Take down CPUs not online prior to suspend */
+       cpuret = rtas_offline_cpus_mask(offline_mask);
+       if (cpuret)
+               pr_warn("%s: Could not restore CPUs to offline state.\n",
+                               __func__);
+
+out:
+       free_cpumask_var(offline_mask);
        return atomic_read(&data.error);
 }
 #else /* CONFIG_PPC_PSERIES */
index 5b30224..2f3cdb0 100644 (file)
@@ -89,6 +89,7 @@
 
 /* Array sizes */
 #define VALIDATE_BUF_SIZE 4096    
+#define VALIDATE_MSG_LEN  256
 #define RTAS_MSG_MAXLEN   64
 
 /* Quirk - RTAS requires 4k list length and block size */
@@ -466,7 +467,7 @@ static void validate_flash(struct rtas_validate_flash_t *args_buf)
 }
 
 static int get_validate_flash_msg(struct rtas_validate_flash_t *args_buf, 
-                                  char *msg)
+                                  char *msg, int msglen)
 {
        int n;
 
@@ -474,7 +475,8 @@ static int get_validate_flash_msg(struct rtas_validate_flash_t *args_buf,
                n = sprintf(msg, "%d\n", args_buf->update_results);
                if ((args_buf->update_results >= VALIDATE_CUR_UNKNOWN) ||
                    (args_buf->update_results == VALIDATE_TMP_UPDATE))
-                       n += sprintf(msg + n, "%s\n", args_buf->buf);
+                       n += snprintf(msg + n, msglen - n, "%s\n",
+                                       args_buf->buf);
        } else {
                n = sprintf(msg, "%d\n", args_buf->status);
        }
@@ -486,11 +488,11 @@ static ssize_t validate_flash_read(struct file *file, char __user *buf,
 {
        struct rtas_validate_flash_t *const args_buf =
                &rtas_validate_flash_data;
-       char msg[RTAS_MSG_MAXLEN];
+       char msg[VALIDATE_MSG_LEN];
        int msglen;
 
        mutex_lock(&rtas_validate_flash_mutex);
-       msglen = get_validate_flash_msg(args_buf, msg);
+       msglen = get_validate_flash_msg(args_buf, msg, VALIDATE_MSG_LEN);
        mutex_unlock(&rtas_validate_flash_mutex);
 
        return simple_read_from_buffer(buf, count, ppos, msg, msglen);
index cf12eae..457e97a 100644 (file)
 #include <linux/signal.h>
 #include <linux/uprobes.h>
 #include <linux/key.h>
+#include <linux/context_tracking.h>
 #include <asm/hw_breakpoint.h>
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
 #include <asm/debug.h>
+#include <asm/tm.h>
 
 #include "signal.h"
 
  * through debug.exception-trace sysctl.
  */
 
-int show_unhandled_signals = 0;
+int show_unhandled_signals = 1;
 
 /*
  * Allocate space for the signal frame
  */
-void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
+void __user * get_sigframe(struct k_sigaction *ka, unsigned long sp,
                           size_t frame_size, int is_32)
 {
         unsigned long oldsp, newsp;
 
         /* Default to using normal stack */
-        oldsp = get_clean_sp(regs, is_32);
+        oldsp = get_clean_sp(sp, is_32);
 
        /* Check for alt stack */
        if ((ka->sa.sa_flags & SA_ONSTACK) &&
@@ -159,6 +161,8 @@ static int do_signal(struct pt_regs *regs)
 
 void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
 {
+       user_exit();
+
        if (thread_info_flags & _TIF_UPROBE)
                uprobe_notify_resume(regs);
 
@@ -169,4 +173,41 @@ void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
                clear_thread_flag(TIF_NOTIFY_RESUME);
                tracehook_notify_resume(regs);
        }
+
+       user_enter();
+}
+
+unsigned long get_tm_stackpointer(struct pt_regs *regs)
+{
+       /* When in an active transaction that takes a signal, we need to be
+        * careful with the stack.  It's possible that the stack has moved back
+        * up after the tbegin.  The obvious case here is when the tbegin is
+        * called inside a function that returns before a tend.  In this case,
+        * the stack is part of the checkpointed transactional memory state.
+        * If we write over this non transactionally or in suspend, we are in
+        * trouble because if we get a tm abort, the program counter and stack
+        * pointer will be back at the tbegin but our in memory stack won't be
+        * valid anymore.
+        *
+        * To avoid this, when taking a signal in an active transaction, we
+        * need to use the stack pointer from the checkpointed state, rather
+        * than the speculated state.  This ensures that the signal context
+        * (written tm suspended) will be written below the stack required for
+        * the rollback.  The transaction is aborted becuase of the treclaim,
+        * so any memory written between the tbegin and the signal will be
+        * rolled back anyway.
+        *
+        * For signals taken in non-TM or suspended mode, we use the
+        * normal/non-checkpointed stack pointer.
+        */
+
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+       if (MSR_TM_ACTIVE(regs->msr)) {
+               tm_enable();
+               tm_reclaim(&current->thread, regs->msr, TM_CAUSE_SIGNAL);
+               if (MSR_TM_TRANSACTIONAL(regs->msr))
+                       return current->thread.ckpt_regs.gpr[1];
+       }
+#endif
+       return regs->gpr[1];
 }
index ec84c90..c69b9ae 100644 (file)
@@ -12,7 +12,7 @@
 
 extern void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags);
 
-extern void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
+extern void __user * get_sigframe(struct k_sigaction *ka, unsigned long sp,
                                  size_t frame_size, int is_32);
 
 extern int handle_signal32(unsigned long sig, struct k_sigaction *ka,
index 95068bf..201385c 100644 (file)
@@ -503,12 +503,6 @@ static int save_tm_user_regs(struct pt_regs *regs,
 {
        unsigned long msr = regs->msr;
 
-       /* tm_reclaim rolls back all reg states, updating thread.ckpt_regs,
-        * thread.transact_fpr[], thread.transact_vr[], etc.
-        */
-       tm_enable();
-       tm_reclaim(&current->thread, msr, TM_CAUSE_SIGNAL);
-
        /* Make sure floating point registers are stored in regs */
        flush_fp_to_thread(current);
 
@@ -965,7 +959,7 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
 
        /* Set up Signal Frame */
        /* Put a Real Time Context onto stack */
-       rt_sf = get_sigframe(ka, regs, sizeof(*rt_sf), 1);
+       rt_sf = get_sigframe(ka, get_tm_stackpointer(regs), sizeof(*rt_sf), 1);
        addr = rt_sf;
        if (unlikely(rt_sf == NULL))
                goto badframe;
@@ -1403,7 +1397,7 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka,
        unsigned long tramp;
 
        /* Set up Signal Frame */
-       frame = get_sigframe(ka, regs, sizeof(*frame), 1);
+       frame = get_sigframe(ka, get_tm_stackpointer(regs), sizeof(*frame), 1);
        if (unlikely(frame == NULL))
                goto badframe;
        sc = (struct sigcontext __user *) &frame->sctx;
index c179428..3459473 100644 (file)
@@ -154,11 +154,12 @@ static long setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
  * As above, but Transactional Memory is in use, so deliver sigcontexts
  * containing checkpointed and transactional register states.
  *
- * To do this, we treclaim to gather both sets of registers and set up the
- * 'normal' sigcontext registers with rolled-back register values such that a
- * simple signal handler sees a correct checkpointed register state.
- * If interested, a TM-aware sighandler can examine the transactional registers
- * in the 2nd sigcontext to determine the real origin of the signal.
+ * To do this, we treclaim (done before entering here) to gather both sets of
+ * registers and set up the 'normal' sigcontext registers with rolled-back
+ * register values such that a simple signal handler sees a correct
+ * checkpointed register state.  If interested, a TM-aware sighandler can
+ * examine the transactional registers in the 2nd sigcontext to determine the
+ * real origin of the signal.
  */
 static long setup_tm_sigcontexts(struct sigcontext __user *sc,
                                 struct sigcontext __user *tm_sc,
@@ -184,16 +185,6 @@ static long setup_tm_sigcontexts(struct sigcontext __user *sc,
 
        BUG_ON(!MSR_TM_ACTIVE(regs->msr));
 
-       /* tm_reclaim rolls back all reg states, saving checkpointed (older)
-        * GPRs to thread.ckpt_regs and (if used) FPRs to (newer)
-        * thread.transact_fp and/or VRs to (newer) thread.transact_vr.
-        * THEN we save out FP/VRs, if necessary, to the checkpointed (older)
-        * thread.fr[]/vr[]s.  The transactional (newer) GPRs are on the
-        * stack, in *regs.
-        */
-       tm_enable();
-       tm_reclaim(&current->thread, msr, TM_CAUSE_SIGNAL);
-
        flush_fp_to_thread(current);
 
 #ifdef CONFIG_ALTIVEC
@@ -711,7 +702,7 @@ int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info,
        unsigned long newsp = 0;
        long err = 0;
 
-       frame = get_sigframe(ka, regs, sizeof(*frame), 0);
+       frame = get_sigframe(ka, get_tm_stackpointer(regs), sizeof(*frame), 0);
        if (unlikely(frame == NULL))
                goto badframe;
 
index cd6e19d..8a28587 100644 (file)
@@ -126,11 +126,3 @@ asmlinkage long compat_sys_sync_file_range2(int fd, unsigned int flags,
 
        return sys_sync_file_range(fd, offset, nbytes, flags);
 }
-
-asmlinkage long compat_sys_fanotify_mark(int fanotify_fd, unsigned int flags,
-                                        unsigned mask_hi, unsigned mask_lo,
-                                        int dfd, const char __user *pathname)
-{
-       u64 mask = ((u64)mask_hi << 32) | mask_lo;
-       return sys_fanotify_mark(fanotify_fd, flags, mask, dfd, pathname);
-}
index 83efa2f..f18c79c 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/kdebug.h>
 #include <linux/debugfs.h>
 #include <linux/ratelimit.h>
+#include <linux/context_tracking.h>
 
 #include <asm/emulated_ops.h>
 #include <asm/pgtable.h>
@@ -52,6 +53,7 @@
 #ifdef CONFIG_PPC64
 #include <asm/firmware.h>
 #include <asm/processor.h>
+#include <asm/tm.h>
 #endif
 #include <asm/kexec.h>
 #include <asm/ppc-opcode.h>
@@ -667,6 +669,7 @@ int machine_check_generic(struct pt_regs *regs)
 
 void machine_check_exception(struct pt_regs *regs)
 {
+       enum ctx_state prev_state = exception_enter();
        int recover = 0;
 
        __get_cpu_var(irq_stat).mce_exceptions++;
@@ -683,7 +686,7 @@ void machine_check_exception(struct pt_regs *regs)
                recover = cur_cpu_spec->machine_check(regs);
 
        if (recover > 0)
-               return;
+               goto bail;
 
 #if defined(CONFIG_8xx) && defined(CONFIG_PCI)
        /* the qspan pci read routines can cause machine checks -- Cort
@@ -693,20 +696,23 @@ void machine_check_exception(struct pt_regs *regs)
         * -- BenH
         */
        bad_page_fault(regs, regs->dar, SIGBUS);
-       return;
+       goto bail;
 #endif
 
        if (debugger_fault_handler(regs))
-               return;
+               goto bail;
 
        if (check_io_access(regs))
-               return;
+               goto bail;
 
        die("Machine check", regs, SIGBUS);
 
        /* Must die if the interrupt is not recoverable */
        if (!(regs->msr & MSR_RI))
                panic("Unrecoverable Machine check");
+
+bail:
+       exception_exit(prev_state);
 }
 
 void SMIException(struct pt_regs *regs)
@@ -716,20 +722,29 @@ void SMIException(struct pt_regs *regs)
 
 void unknown_exception(struct pt_regs *regs)
 {
+       enum ctx_state prev_state = exception_enter();
+
        printk("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
               regs->nip, regs->msr, regs->trap);
 
        _exception(SIGTRAP, regs, 0, 0);
+
+       exception_exit(prev_state);
 }
 
 void instruction_breakpoint_exception(struct pt_regs *regs)
 {
+       enum ctx_state prev_state = exception_enter();
+
        if (notify_die(DIE_IABR_MATCH, "iabr_match", regs, 5,
                                        5, SIGTRAP) == NOTIFY_STOP)
-               return;
+               goto bail;
        if (debugger_iabr_match(regs))
-               return;
+               goto bail;
        _exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip);
+
+bail:
+       exception_exit(prev_state);
 }
 
 void RunModeException(struct pt_regs *regs)
@@ -739,15 +754,20 @@ void RunModeException(struct pt_regs *regs)
 
 void __kprobes single_step_exception(struct pt_regs *regs)
 {
+       enum ctx_state prev_state = exception_enter();
+
        clear_single_step(regs);
 
        if (notify_die(DIE_SSTEP, "single_step", regs, 5,
                                        5, SIGTRAP) == NOTIFY_STOP)
-               return;
+               goto bail;
        if (debugger_sstep(regs))
-               return;
+               goto bail;
 
        _exception(SIGTRAP, regs, TRAP_TRACE, regs->nip);
+
+bail:
+       exception_exit(prev_state);
 }
 
 /*
@@ -913,6 +933,28 @@ static int emulate_isel(struct pt_regs *regs, u32 instword)
        return 0;
 }
 
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+static inline bool tm_abort_check(struct pt_regs *regs, int cause)
+{
+        /* If we're emulating a load/store in an active transaction, we cannot
+         * emulate it as the kernel operates in transaction suspended context.
+         * We need to abort the transaction.  This creates a persistent TM
+         * abort so tell the user what caused it with a new code.
+        */
+       if (MSR_TM_TRANSACTIONAL(regs->msr)) {
+               tm_enable();
+               tm_abort(cause);
+               return true;
+       }
+       return false;
+}
+#else
+static inline bool tm_abort_check(struct pt_regs *regs, int reason)
+{
+       return false;
+}
+#endif
+
 static int emulate_instruction(struct pt_regs *regs)
 {
        u32 instword;
@@ -952,6 +994,9 @@ static int emulate_instruction(struct pt_regs *regs)
 
        /* Emulate load/store string insn. */
        if ((instword & PPC_INST_STRING_GEN_MASK) == PPC_INST_STRING) {
+               if (tm_abort_check(regs,
+                                  TM_CAUSE_EMULATE | TM_CAUSE_PERSISTENT))
+                       return -EINVAL;
                PPC_WARN_EMULATED(string, regs);
                return emulate_string_inst(regs, instword);
        }
@@ -1005,6 +1050,7 @@ int is_valid_bugaddr(unsigned long addr)
 
 void __kprobes program_check_exception(struct pt_regs *regs)
 {
+       enum ctx_state prev_state = exception_enter();
        unsigned int reason = get_reason(regs);
        extern int do_mathemu(struct pt_regs *regs);
 
@@ -1014,26 +1060,26 @@ void __kprobes program_check_exception(struct pt_regs *regs)
        if (reason & REASON_FP) {
                /* IEEE FP exception */
                parse_fpe(regs);
-               return;
+               goto bail;
        }
        if (reason & REASON_TRAP) {
                /* Debugger is first in line to stop recursive faults in
                 * rcu_lock, notify_die, or atomic_notifier_call_chain */
                if (debugger_bpt(regs))
-                       return;
+                       goto bail;
 
                /* trap exception */
                if (notify_die(DIE_BPT, "breakpoint", regs, 5, 5, SIGTRAP)
                                == NOTIFY_STOP)
-                       return;
+                       goto bail;
 
                if (!(regs->msr & MSR_PR) &&  /* not user-mode */
                    report_bug(regs->nip, regs) == BUG_TRAP_TYPE_WARN) {
                        regs->nip += 4;
-                       return;
+                       goto bail;
                }
                _exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip);
-               return;
+               goto bail;
        }
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
        if (reason & REASON_TM) {
@@ -1049,7 +1095,7 @@ void __kprobes program_check_exception(struct pt_regs *regs)
                if (!user_mode(regs) &&
                    report_bug(regs->nip, regs) == BUG_TRAP_TYPE_WARN) {
                        regs->nip += 4;
-                       return;
+                       goto bail;
                }
                /* If usermode caused this, it's done something illegal and
                 * gets a SIGILL slap on the wrist.  We call it an illegal
@@ -1059,7 +1105,7 @@ void __kprobes program_check_exception(struct pt_regs *regs)
                 */
                if (user_mode(regs)) {
                        _exception(SIGILL, regs, ILL_ILLOPN, regs->nip);
-                       return;
+                       goto bail;
                } else {
                        printk(KERN_EMERG "Unexpected TM Bad Thing exception "
                               "at %lx (msr 0x%x)\n", regs->nip, reason);
@@ -1083,16 +1129,16 @@ void __kprobes program_check_exception(struct pt_regs *regs)
        switch (do_mathemu(regs)) {
        case 0:
                emulate_single_step(regs);
-               return;
+               goto bail;
        case 1: {
                        int code = 0;
                        code = __parse_fpscr(current->thread.fpscr.val);
                        _exception(SIGFPE, regs, code, regs->nip);
-                       return;
+                       goto bail;
                }
        case -EFAULT:
                _exception(SIGSEGV, regs, SEGV_MAPERR, regs->nip);
-               return;
+               goto bail;
        }
        /* fall through on any other errors */
 #endif /* CONFIG_MATH_EMULATION */
@@ -1103,10 +1149,10 @@ void __kprobes program_check_exception(struct pt_regs *regs)
                case 0:
                        regs->nip += 4;
                        emulate_single_step(regs);
-                       return;
+                       goto bail;
                case -EFAULT:
                        _exception(SIGSEGV, regs, SEGV_MAPERR, regs->nip);
-                       return;
+                       goto bail;
                }
        }
 
@@ -1114,16 +1160,23 @@ void __kprobes program_check_exception(struct pt_regs *regs)
                _exception(SIGILL, regs, ILL_PRVOPC, regs->nip);
        else
                _exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
+
+bail:
+       exception_exit(prev_state);
 }
 
 void alignment_exception(struct pt_regs *regs)
 {
+       enum ctx_state prev_state = exception_enter();
        int sig, code, fixed = 0;
 
        /* We restore the interrupt state now */
        if (!arch_irq_disabled_regs(regs))
                local_irq_enable();
 
+       if (tm_abort_check(regs, TM_CAUSE_ALIGNMENT | TM_CAUSE_PERSISTENT))
+               goto bail;
+
        /* we don't implement logging of alignment exceptions */
        if (!(current->thread.align_ctl & PR_UNALIGN_SIGBUS))
                fixed = fix_alignment(regs);
@@ -1131,7 +1184,7 @@ void alignment_exception(struct pt_regs *regs)
        if (fixed == 1) {
                regs->nip += 4; /* skip over emulated instruction */
                emulate_single_step(regs);
-               return;
+               goto bail;
        }
 
        /* Operand address was bad */
@@ -1146,6 +1199,9 @@ void alignment_exception(struct pt_regs *regs)
                _exception(sig, regs, code, regs->dar);
        else
                bad_page_fault(regs, regs->dar, sig);
+
+bail:
+       exception_exit(prev_state);
 }
 
 void StackOverflow(struct pt_regs *regs)
@@ -1174,23 +1230,32 @@ void trace_syscall(struct pt_regs *regs)
 
 void kernel_fp_unavailable_exception(struct pt_regs *regs)
 {
+       enum ctx_state prev_state = exception_enter();
+
        printk(KERN_EMERG "Unrecoverable FP Unavailable Exception "
                          "%lx at %lx\n", regs->trap, regs->nip);
        die("Unrecoverable FP Unavailable Exception", regs, SIGABRT);
+
+       exception_exit(prev_state);
 }
 
 void altivec_unavailable_exception(struct pt_regs *regs)
 {
+       enum ctx_state prev_state = exception_enter();
+
        if (user_mode(regs)) {
                /* A user program has executed an altivec instruction,
                   but this kernel doesn't support altivec. */
                _exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
-               return;
+               goto bail;
        }
 
        printk(KERN_EMERG "Unrecoverable VMX/Altivec Unavailable Exception "
                        "%lx at %lx\n", regs->trap, regs->nip);
        die("Unrecoverable VMX/Altivec Unavailable Exception", regs, SIGABRT);
+
+bail:
+       exception_exit(prev_state);
 }
 
 void vsx_unavailable_exception(struct pt_regs *regs)
index 13b8670..9d3fdcd 100644 (file)
@@ -64,6 +64,9 @@ void __init udbg_early_init(void)
        udbg_init_usbgecko();
 #elif defined(CONFIG_PPC_EARLY_DEBUG_WSP)
        udbg_init_wsp();
+#elif defined(CONFIG_PPC_EARLY_DEBUG_MEMCONS)
+       /* In memory console */
+       udbg_init_memcons();
 #elif defined(CONFIG_PPC_EARLY_DEBUG_EHV_BC)
        udbg_init_ehv_bc();
 #elif defined(CONFIG_PPC_EARLY_DEBUG_PS3GELIC)
index 5dd3ab4..ed03854 100644 (file)
@@ -441,6 +441,7 @@ int kvmppc_44x_emul_tlbwe(struct kvm_vcpu *vcpu, u8 ra, u8 rs, u8 ws)
        struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu);
        struct kvmppc_44x_tlbe *tlbe;
        unsigned int gtlb_index;
+       int idx;
 
        gtlb_index = kvmppc_get_gpr(vcpu, ra);
        if (gtlb_index >= KVM44x_GUEST_TLB_SIZE) {
@@ -473,6 +474,8 @@ int kvmppc_44x_emul_tlbwe(struct kvm_vcpu *vcpu, u8 ra, u8 rs, u8 ws)
                return EMULATE_FAIL;
        }
 
+       idx = srcu_read_lock(&vcpu->kvm->srcu);
+
        if (tlbe_is_host_safe(vcpu, tlbe)) {
                gva_t eaddr;
                gpa_t gpaddr;
@@ -489,6 +492,8 @@ int kvmppc_44x_emul_tlbwe(struct kvm_vcpu *vcpu, u8 ra, u8 rs, u8 ws)
                kvmppc_mmu_map(vcpu, eaddr, gpaddr, gtlb_index);
        }
 
+       srcu_read_unlock(&vcpu->kvm->srcu, idx);
+
        trace_kvm_gtlb_write(gtlb_index, tlbe->tid, tlbe->word0, tlbe->word1,
                             tlbe->word2);
 
index 9de24f8..550f592 100644 (file)
@@ -562,6 +562,8 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu)
        case H_CPPR:
        case H_EOI:
        case H_IPI:
+       case H_IPOLL:
+       case H_XIRR_X:
                if (kvmppc_xics_enabled(vcpu)) {
                        ret = kvmppc_xics_hcall(vcpu, req);
                        break;
index b24309c..da0e0bc 100644 (file)
@@ -257,6 +257,8 @@ int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd)
        case H_CPPR:
        case H_EOI:
        case H_IPI:
+       case H_IPOLL:
+       case H_XIRR_X:
                if (kvmppc_xics_enabled(vcpu))
                        return kvmppc_h_pr_xics_hcall(vcpu, cmd);
                break;
index f7a1037..94c1dd4 100644 (file)
@@ -650,6 +650,23 @@ static noinline int kvmppc_h_ipi(struct kvm_vcpu *vcpu, unsigned long server,
        return H_SUCCESS;
 }
 
+static int kvmppc_h_ipoll(struct kvm_vcpu *vcpu, unsigned long server)
+{
+       union kvmppc_icp_state state;
+       struct kvmppc_icp *icp;
+
+       icp = vcpu->arch.icp;
+       if (icp->server_num != server) {
+               icp = kvmppc_xics_find_server(vcpu->kvm, server);
+               if (!icp)
+                       return H_PARAMETER;
+       }
+       state = ACCESS_ONCE(icp->state);
+       kvmppc_set_gpr(vcpu, 4, ((u32)state.cppr << 24) | state.xisr);
+       kvmppc_set_gpr(vcpu, 5, state.mfrr);
+       return H_SUCCESS;
+}
+
 static noinline void kvmppc_h_cppr(struct kvm_vcpu *vcpu, unsigned long cppr)
 {
        union kvmppc_icp_state old_state, new_state;
@@ -787,6 +804,18 @@ int kvmppc_xics_hcall(struct kvm_vcpu *vcpu, u32 req)
        if (!xics || !vcpu->arch.icp)
                return H_HARDWARE;
 
+       /* These requests don't have real-mode implementations at present */
+       switch (req) {
+       case H_XIRR_X:
+               res = kvmppc_h_xirr(vcpu);
+               kvmppc_set_gpr(vcpu, 4, res);
+               kvmppc_set_gpr(vcpu, 5, get_tb());
+               return rc;
+       case H_IPOLL:
+               rc = kvmppc_h_ipoll(vcpu, kvmppc_get_gpr(vcpu, 4));
+               return rc;
+       }
+
        /* Check for real mode returning too hard */
        if (xics->real_mode)
                return kvmppc_xics_rm_complete(vcpu, req);
index 1020119..5cd7ad0 100644 (file)
@@ -832,6 +832,18 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
 {
        int r = RESUME_HOST;
        int s;
+       int idx;
+
+#ifdef CONFIG_PPC64
+       WARN_ON(local_paca->irq_happened != 0);
+#endif
+
+       /*
+        * We enter with interrupts disabled in hardware, but
+        * we need to call hard_irq_disable anyway to ensure that
+        * the software state is kept in sync.
+        */
+       hard_irq_disable();
 
        /* update before a new last_exit_type is rewritten */
        kvmppc_update_timing_stats(vcpu);
@@ -1053,6 +1065,8 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
                        break;
                }
 
+               idx = srcu_read_lock(&vcpu->kvm->srcu);
+
                gpaddr = kvmppc_mmu_xlate(vcpu, gtlb_index, eaddr);
                gfn = gpaddr >> PAGE_SHIFT;
 
@@ -1075,6 +1089,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
                        kvmppc_account_exit(vcpu, MMIO_EXITS);
                }
 
+               srcu_read_unlock(&vcpu->kvm->srcu, idx);
                break;
        }
 
@@ -1098,6 +1113,8 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
 
                kvmppc_account_exit(vcpu, ITLB_VIRT_MISS_EXITS);
 
+               idx = srcu_read_lock(&vcpu->kvm->srcu);
+
                gpaddr = kvmppc_mmu_xlate(vcpu, gtlb_index, eaddr);
                gfn = gpaddr >> PAGE_SHIFT;
 
@@ -1114,6 +1131,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
                        kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_MACHINE_CHECK);
                }
 
+               srcu_read_unlock(&vcpu->kvm->srcu, idx);
                break;
        }
 
index c41a5a9..6d6f153 100644 (file)
@@ -396,6 +396,7 @@ int kvmppc_e500_emul_tlbwe(struct kvm_vcpu *vcpu)
        struct kvm_book3e_206_tlb_entry *gtlbe;
        int tlbsel, esel;
        int recal = 0;
+       int idx;
 
        tlbsel = get_tlb_tlbsel(vcpu);
        esel = get_tlb_esel(vcpu, tlbsel);
@@ -430,6 +431,8 @@ int kvmppc_e500_emul_tlbwe(struct kvm_vcpu *vcpu)
                        kvmppc_set_tlb1map_range(vcpu, gtlbe);
        }
 
+       idx = srcu_read_lock(&vcpu->kvm->srcu);
+
        /* Invalidate shadow mappings for the about-to-be-clobbered TLBE. */
        if (tlbe_is_host_safe(vcpu, gtlbe)) {
                u64 eaddr = get_tlb_eaddr(gtlbe);
@@ -444,6 +447,8 @@ int kvmppc_e500_emul_tlbwe(struct kvm_vcpu *vcpu)
                kvmppc_mmu_map(vcpu, eaddr, raddr, index_of(tlbsel, esel));
        }
 
+       srcu_read_unlock(&vcpu->kvm->srcu, idx);
+
        kvmppc_set_exit_type(vcpu, EMULATED_TLBWE_EXITS);
        return EMULATE_DONE;
 }
index 753cc99..19c8379 100644 (file)
@@ -177,8 +177,6 @@ int kvmppc_core_check_processor_compat(void)
                r = 0;
        else if (strcmp(cur_cpu_spec->cpu_name, "e5500") == 0)
                r = 0;
-       else if (strcmp(cur_cpu_spec->cpu_name, "e6500") == 0)
-               r = 0;
        else
                r = -ENOTSUPP;
 
index 0ef75bf..395c594 100644 (file)
@@ -28,13 +28,14 @@ _GLOBAL(copypage_power7)
         * aligned we don't need to clear the bottom 7 bits of either
         * address.
         */
-       ori     r9,r3,1         /* stream=1 */
+       ori     r9,r3,1         /* stream=1 => to */
 
 #ifdef CONFIG_PPC_64K_PAGES
-       lis     r7,0x0E01       /* depth=7, units=512 */
+       lis     r7,0x0E01       /* depth=7
+                                * units/cachelines=512 */
 #else
        lis     r7,0x0E00       /* depth=7 */
-       ori     r7,r7,0x1000    /* units=32 */
+       ori     r7,r7,0x1000    /* units/cachelines=32 */
 #endif
        ori     r10,r7,1        /* stream=1 */
 
@@ -43,12 +44,14 @@ _GLOBAL(copypage_power7)
 
 .machine push
 .machine "power4"
-       dcbt    r0,r4,0b01000
-       dcbt    r0,r7,0b01010
-       dcbtst  r0,r9,0b01000
-       dcbtst  r0,r10,0b01010
+       /* setup read stream 0  */
+       dcbt    r0,r4,0b01000   /* addr from */
+       dcbt    r0,r7,0b01010   /* length and depth from */
+       /* setup write stream 1 */
+       dcbtst  r0,r9,0b01000   /* addr to */
+       dcbtst  r0,r10,0b01010  /* length and depth to */
        eieio
-       dcbt    r0,r8,0b01010   /* GO */
+       dcbt    r0,r8,0b01010   /* all streams GO */
 .machine pop
 
 #ifdef CONFIG_ALTIVEC
index 0d24ff1..d1f1179 100644 (file)
@@ -318,12 +318,14 @@ err1;     stb     r0,0(r3)
 
 .machine push
 .machine "power4"
-       dcbt    r0,r6,0b01000
-       dcbt    r0,r7,0b01010
-       dcbtst  r0,r9,0b01000
-       dcbtst  r0,r10,0b01010
+       /* setup read stream 0 */
+       dcbt    r0,r6,0b01000   /* addr from */
+       dcbt    r0,r7,0b01010   /* length and depth from */
+       /* setup write stream 1 */
+       dcbtst  r0,r9,0b01000   /* addr to */
+       dcbtst  r0,r10,0b01010  /* length and depth to */
        eieio
-       dcbt    r0,r8,0b01010   /* GO */
+       dcbt    r0,r8,0b01010   /* all streams GO */
 .machine pop
 
        beq     cr1,.Lunwind_stack_nonvmx_copy
index 229951f..8726779 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/perf_event.h>
 #include <linux/magic.h>
 #include <linux/ratelimit.h>
+#include <linux/context_tracking.h>
 
 #include <asm/firmware.h>
 #include <asm/page.h>
@@ -196,6 +197,7 @@ static int mm_fault_error(struct pt_regs *regs, unsigned long addr, int fault)
 int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address,
                            unsigned long error_code)
 {
+       enum ctx_state prev_state = exception_enter();
        struct vm_area_struct * vma;
        struct mm_struct *mm = current->mm;
        unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
@@ -204,6 +206,7 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address,
        int trap = TRAP(regs);
        int is_exec = trap == 0x400;
        int fault;
+       int rc = 0;
 
 #if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE))
        /*
@@ -230,28 +233,30 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address,
         * look at it
         */
        if (error_code & ICSWX_DSI_UCT) {
-               int rc = acop_handle_fault(regs, address, error_code);
+               rc = acop_handle_fault(regs, address, error_code);
                if (rc)
-                       return rc;
+                       goto bail;
        }
 #endif /* CONFIG_PPC_ICSWX */
 
        if (notify_page_fault(regs))
-               return 0;
+               goto bail;
 
        if (unlikely(debugger_fault_handler(regs)))
-               return 0;
+               goto bail;
 
        /* On a kernel SLB miss we can only check for a valid exception entry */
-       if (!user_mode(regs) && (address >= TASK_SIZE))
-               return SIGSEGV;
+       if (!user_mode(regs) && (address >= TASK_SIZE)) {
+               rc = SIGSEGV;
+               goto bail;
+       }
 
 #if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE) || \
                             defined(CONFIG_PPC_BOOK3S_64))
        if (error_code & DSISR_DABRMATCH) {
                /* breakpoint match */
                do_break(regs, address, error_code);
-               return 0;
+               goto bail;
        }
 #endif
 
@@ -260,8 +265,10 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address,
                local_irq_enable();
 
        if (in_atomic() || mm == NULL) {
-               if (!user_mode(regs))
-                       return SIGSEGV;
+               if (!user_mode(regs)) {
+                       rc = SIGSEGV;
+                       goto bail;
+               }
                /* in_atomic() in user mode is really bad,
                   as is current->mm == NULL. */
                printk(KERN_EMERG "Page fault in user mode with "
@@ -417,9 +424,11 @@ good_area:
         */
        fault = handle_mm_fault(mm, vma, address, flags);
        if (unlikely(fault & (VM_FAULT_RETRY|VM_FAULT_ERROR))) {
-               int rc = mm_fault_error(regs, address, fault);
+               rc = mm_fault_error(regs, address, fault);
                if (rc >= MM_FAULT_RETURN)
-                       return rc;
+                       goto bail;
+               else
+                       rc = 0;
        }
 
        /*
@@ -454,7 +463,7 @@ good_area:
        }
 
        up_read(&mm->mmap_sem);
-       return 0;
+       goto bail;
 
 bad_area:
        up_read(&mm->mmap_sem);
@@ -463,7 +472,7 @@ bad_area_nosemaphore:
        /* User mode accesses cause a SIGSEGV */
        if (user_mode(regs)) {
                _exception(SIGSEGV, regs, code, address);
-               return 0;
+               goto bail;
        }
 
        if (is_exec && (error_code & DSISR_PROTFAULT))
@@ -471,7 +480,11 @@ bad_area_nosemaphore:
                                   " page (%lx) - exploit attempt? (uid: %d)\n",
                                   address, from_kuid(&init_user_ns, current_uid()));
 
-       return SIGSEGV;
+       rc = SIGSEGV;
+
+bail:
+       exception_exit(prev_state);
+       return rc;
 
 }
 
index 6a2aead..4c122c3 100644 (file)
@@ -336,11 +336,18 @@ static long native_hpte_updatepp(unsigned long slot, unsigned long newpp,
 
        hpte_v = hptep->v;
        actual_psize = hpte_actual_psize(hptep, psize);
+       /*
+        * We need to invalidate the TLB always because hpte_remove doesn't do
+        * a tlb invalidate. If a hash bucket gets full, we "evict" a more/less
+        * random entry from it. When we do that we don't invalidate the TLB
+        * (hpte_remove) because we assume the old translation is still
+        * technically "valid".
+        */
        if (actual_psize < 0) {
-               native_unlock_hpte(hptep);
-               return -1;
+               actual_psize = psize;
+               ret = -1;
+               goto err_out;
        }
-       /* Even if we miss, we need to invalidate the TLB */
        if (!HPTE_V_COMPARE(hpte_v, want_v)) {
                DBG_LOW(" -> miss\n");
                ret = -1;
@@ -350,6 +357,7 @@ static long native_hpte_updatepp(unsigned long slot, unsigned long newpp,
                hptep->r = (hptep->r & ~(HPTE_R_PP | HPTE_R_N)) |
                        (newpp & (HPTE_R_PP | HPTE_R_N | HPTE_R_C));
        }
+err_out:
        native_unlock_hpte(hptep);
 
        /* Ensure it is out of the tlb too. */
@@ -409,7 +417,7 @@ static void native_hpte_updateboltedpp(unsigned long newpp, unsigned long ea,
        hptep = htab_address + slot;
        actual_psize = hpte_actual_psize(hptep, psize);
        if (actual_psize < 0)
-               return;
+               actual_psize = psize;
 
        /* Update the HPTE */
        hptep->r = (hptep->r & ~(HPTE_R_PP | HPTE_R_N)) |
@@ -437,21 +445,27 @@ static void native_hpte_invalidate(unsigned long slot, unsigned long vpn,
        hpte_v = hptep->v;
 
        actual_psize = hpte_actual_psize(hptep, psize);
+       /*
+        * We need to invalidate the TLB always because hpte_remove doesn't do
+        * a tlb invalidate. If a hash bucket gets full, we "evict" a more/less
+        * random entry from it. When we do that we don't invalidate the TLB
+        * (hpte_remove) because we assume the old translation is still
+        * technically "valid".
+        */
        if (actual_psize < 0) {
+               actual_psize = psize;
                native_unlock_hpte(hptep);
-               local_irq_restore(flags);
-               return;
+               goto err_out;
        }
-       /* Even if we miss, we need to invalidate the TLB */
        if (!HPTE_V_COMPARE(hpte_v, want_v))
                native_unlock_hpte(hptep);
        else
                /* Invalidate the hpte. NOTE: this also unlocks it */
                hptep->v = 0;
 
+err_out:
        /* Invalidate the TLB */
        tlbie(vpn, psize, actual_psize, ssize, local);
-
        local_irq_restore(flags);
 }
 
index 88ac0ee..e303a6d 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/init.h>
 #include <linux/signal.h>
 #include <linux/memblock.h>
+#include <linux/context_tracking.h>
 
 #include <asm/processor.h>
 #include <asm/pgtable.h>
@@ -954,6 +955,7 @@ void hash_failure_debug(unsigned long ea, unsigned long access,
  */
 int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
 {
+       enum ctx_state prev_state = exception_enter();
        pgd_t *pgdir;
        unsigned long vsid;
        struct mm_struct *mm;
@@ -973,7 +975,8 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
                mm = current->mm;
                if (! mm) {
                        DBG_LOW(" user region with no mm !\n");
-                       return 1;
+                       rc = 1;
+                       goto bail;
                }
                psize = get_slice_psize(mm, ea);
                ssize = user_segment_size(ea);
@@ -992,19 +995,23 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
                /* Not a valid range
                 * Send the problem up to do_page_fault 
                 */
-               return 1;
+               rc = 1;
+               goto bail;
        }
        DBG_LOW(" mm=%p, mm->pgdir=%p, vsid=%016lx\n", mm, mm->pgd, vsid);
 
        /* Bad address. */
        if (!vsid) {
                DBG_LOW("Bad address!\n");
-               return 1;
+               rc = 1;
+               goto bail;
        }
        /* Get pgdir */
        pgdir = mm->pgd;
-       if (pgdir == NULL)
-               return 1;
+       if (pgdir == NULL) {
+               rc = 1;
+               goto bail;
+       }
 
        /* Check CPU locality */
        tmp = cpumask_of(smp_processor_id());
@@ -1027,7 +1034,8 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
        ptep = find_linux_pte_or_hugepte(pgdir, ea, &hugeshift);
        if (ptep == NULL || !pte_present(*ptep)) {
                DBG_LOW(" no PTE !\n");
-               return 1;
+               rc = 1;
+               goto bail;
        }
 
        /* Add _PAGE_PRESENT to the required access perm */
@@ -1038,13 +1046,16 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
         */
        if (access & ~pte_val(*ptep)) {
                DBG_LOW(" no access !\n");
-               return 1;
+               rc = 1;
+               goto bail;
        }
 
 #ifdef CONFIG_HUGETLB_PAGE
-       if (hugeshift)
-               return __hash_page_huge(ea, access, vsid, ptep, trap, local,
+       if (hugeshift) {
+               rc = __hash_page_huge(ea, access, vsid, ptep, trap, local,
                                        ssize, hugeshift, psize);
+               goto bail;
+       }
 #endif /* CONFIG_HUGETLB_PAGE */
 
 #ifndef CONFIG_PPC_64K_PAGES
@@ -1124,6 +1135,9 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
                pte_val(*(ptep + PTRS_PER_PTE)));
 #endif
        DBG_LOW(" -> rc=%d\n", rc);
+
+bail:
+       exception_exit(prev_state);
        return rc;
 }
 EXPORT_SYMBOL_GPL(hash_page);
@@ -1259,6 +1273,8 @@ void flush_hash_range(unsigned long number, int local)
  */
 void low_hash_fault(struct pt_regs *regs, unsigned long address, int rc)
 {
+       enum ctx_state prev_state = exception_enter();
+
        if (user_mode(regs)) {
 #ifdef CONFIG_PPC_SUBPAGE_PROT
                if (rc == -2)
@@ -1268,6 +1284,8 @@ void low_hash_fault(struct pt_regs *regs, unsigned long address, int rc)
                        _exception(SIGBUS, regs, BUS_ADRERR, address);
        } else
                bad_page_fault(regs, address, SIGBUS);
+
+       exception_exit(prev_state);
 }
 
 long hpte_insert_repeating(unsigned long hash, unsigned long vpn,
index c2787bf..a90b9c4 100644 (file)
@@ -215,7 +215,8 @@ static void __meminit vmemmap_create_mapping(unsigned long start,
                                             unsigned long phys)
 {
        int  mapped = htab_bolt_mapping(start, start + page_size, phys,
-                                       PAGE_KERNEL, mmu_vmemmap_psize,
+                                       pgprot_val(PAGE_KERNEL),
+                                       mmu_vmemmap_psize,
                                        mmu_kernel_ssize);
        BUG_ON(mapped < 0);
 }
index c627843..29c6482 100644 (file)
 #include <linux/perf_event.h>
 #include <linux/percpu.h>
 #include <linux/hardirq.h>
+#include <linux/uaccess.h>
 #include <asm/reg.h>
 #include <asm/pmc.h>
 #include <asm/machdep.h>
 #include <asm/firmware.h>
 #include <asm/ptrace.h>
+#include <asm/code-patching.h>
 
 #define BHRB_MAX_ENTRIES       32
 #define BHRB_TARGET            0x0000000000000002
@@ -100,11 +102,15 @@ static inline int siar_valid(struct pt_regs *regs)
        return 1;
 }
 
+static inline void power_pmu_bhrb_enable(struct perf_event *event) {}
+static inline void power_pmu_bhrb_disable(struct perf_event *event) {}
+void power_pmu_flush_branch_stack(void) {}
+static inline void power_pmu_bhrb_read(struct cpu_hw_events *cpuhw) {}
 #endif /* CONFIG_PPC32 */
 
 static bool regs_use_siar(struct pt_regs *regs)
 {
-       return !!(regs->result & 1);
+       return !!regs->result;
 }
 
 /*
@@ -130,22 +136,30 @@ static inline unsigned long perf_ip_adjust(struct pt_regs *regs)
  * If we're not doing instruction sampling, give them the SDAR
  * (sampled data address).  If we are doing instruction sampling, then
  * only give them the SDAR if it corresponds to the instruction
- * pointed to by SIAR; this is indicated by the [POWER6_]MMCRA_SDSYNC or
- * the [POWER7P_]MMCRA_SDAR_VALID bit in MMCRA.
+ * pointed to by SIAR; this is indicated by the [POWER6_]MMCRA_SDSYNC, the
+ * [POWER7P_]MMCRA_SDAR_VALID bit in MMCRA, or the SDAR_VALID bit in SIER.
  */
 static inline void perf_get_data_addr(struct pt_regs *regs, u64 *addrp)
 {
        unsigned long mmcra = regs->dsisr;
-       unsigned long sdsync;
+       bool sdar_valid;
 
-       if (ppmu->flags & PPMU_SIAR_VALID)
-               sdsync = POWER7P_MMCRA_SDAR_VALID;
-       else if (ppmu->flags & PPMU_ALT_SIPR)
-               sdsync = POWER6_MMCRA_SDSYNC;
-       else
-               sdsync = MMCRA_SDSYNC;
+       if (ppmu->flags & PPMU_HAS_SIER)
+               sdar_valid = regs->dar & SIER_SDAR_VALID;
+       else {
+               unsigned long sdsync;
+
+               if (ppmu->flags & PPMU_SIAR_VALID)
+                       sdsync = POWER7P_MMCRA_SDAR_VALID;
+               else if (ppmu->flags & PPMU_ALT_SIPR)
+                       sdsync = POWER6_MMCRA_SDSYNC;
+               else
+                       sdsync = MMCRA_SDSYNC;
 
-       if (!(mmcra & MMCRA_SAMPLE_ENABLE) || (mmcra & sdsync))
+               sdar_valid = mmcra & sdsync;
+       }
+
+       if (!(mmcra & MMCRA_SAMPLE_ENABLE) || sdar_valid)
                *addrp = mfspr(SPRN_SDAR);
 }
 
@@ -175,11 +189,6 @@ static bool regs_sipr(struct pt_regs *regs)
        return !!(regs->dsisr & sipr);
 }
 
-static bool regs_no_sipr(struct pt_regs *regs)
-{
-       return !!(regs->result & 2);
-}
-
 static inline u32 perf_flags_from_msr(struct pt_regs *regs)
 {
        if (regs->msr & MSR_PR)
@@ -202,7 +211,7 @@ static inline u32 perf_get_misc_flags(struct pt_regs *regs)
         * SIAR which should give slightly more reliable
         * results
         */
-       if (regs_no_sipr(regs)) {
+       if (ppmu->flags & PPMU_NO_SIPR) {
                unsigned long siar = mfspr(SPRN_SIAR);
                if (siar >= PAGE_OFFSET)
                        return PERF_RECORD_MISC_KERNEL;
@@ -233,22 +242,9 @@ static inline void perf_read_regs(struct pt_regs *regs)
        int use_siar;
 
        regs->dsisr = mmcra;
-       regs->result = 0;
-
-       if (ppmu->flags & PPMU_NO_SIPR)
-               regs->result |= 2;
-
-       /*
-        * On power8 if we're in random sampling mode, the SIER is updated.
-        * If we're in continuous sampling mode, we don't have SIPR.
-        */
-       if (ppmu->flags & PPMU_HAS_SIER) {
-               if (marked)
-                       regs->dar = mfspr(SPRN_SIER);
-               else
-                       regs->result |= 2;
-       }
 
+       if (ppmu->flags & PPMU_HAS_SIER)
+               regs->dar = mfspr(SPRN_SIER);
 
        /*
         * If this isn't a PMU exception (eg a software event) the SIAR is
@@ -273,12 +269,12 @@ static inline void perf_read_regs(struct pt_regs *regs)
                use_siar = 1;
        else if ((ppmu->flags & PPMU_NO_CONT_SAMPLING))
                use_siar = 0;
-       else if (!regs_no_sipr(regs) && regs_sipr(regs))
+       else if (!(ppmu->flags & PPMU_NO_SIPR) && regs_sipr(regs))
                use_siar = 0;
        else
                use_siar = 1;
 
-       regs->result |= use_siar;
+       regs->result = use_siar;
 }
 
 /*
@@ -302,12 +298,170 @@ static inline int siar_valid(struct pt_regs *regs)
        unsigned long mmcra = regs->dsisr;
        int marked = mmcra & MMCRA_SAMPLE_ENABLE;
 
-       if ((ppmu->flags & PPMU_SIAR_VALID) && marked)
-               return mmcra & POWER7P_MMCRA_SIAR_VALID;
+       if (marked) {
+               if (ppmu->flags & PPMU_HAS_SIER)
+                       return regs->dar & SIER_SIAR_VALID;
+
+               if (ppmu->flags & PPMU_SIAR_VALID)
+                       return mmcra & POWER7P_MMCRA_SIAR_VALID;
+       }
 
        return 1;
 }
 
+
+/* Reset all possible BHRB entries */
+static void power_pmu_bhrb_reset(void)
+{
+       asm volatile(PPC_CLRBHRB);
+}
+
+static void power_pmu_bhrb_enable(struct perf_event *event)
+{
+       struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events);
+
+       if (!ppmu->bhrb_nr)
+               return;
+
+       /* Clear BHRB if we changed task context to avoid data leaks */
+       if (event->ctx->task && cpuhw->bhrb_context != event->ctx) {
+               power_pmu_bhrb_reset();
+               cpuhw->bhrb_context = event->ctx;
+       }
+       cpuhw->bhrb_users++;
+}
+
+static void power_pmu_bhrb_disable(struct perf_event *event)
+{
+       struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events);
+
+       if (!ppmu->bhrb_nr)
+               return;
+
+       cpuhw->bhrb_users--;
+       WARN_ON_ONCE(cpuhw->bhrb_users < 0);
+
+       if (!cpuhw->disabled && !cpuhw->bhrb_users) {
+               /* BHRB cannot be turned off when other
+                * events are active on the PMU.
+                */
+
+               /* avoid stale pointer */
+               cpuhw->bhrb_context = NULL;
+       }
+}
+
+/* Called from ctxsw to prevent one process's branch entries to
+ * mingle with the other process's entries during context switch.
+ */
+void power_pmu_flush_branch_stack(void)
+{
+       if (ppmu->bhrb_nr)
+               power_pmu_bhrb_reset();
+}
+/* Calculate the to address for a branch */
+static __u64 power_pmu_bhrb_to(u64 addr)
+{
+       unsigned int instr;
+       int ret;
+       __u64 target;
+
+       if (is_kernel_addr(addr))
+               return branch_target((unsigned int *)addr);
+
+       /* Userspace: need copy instruction here then translate it */
+       pagefault_disable();
+       ret = __get_user_inatomic(instr, (unsigned int __user *)addr);
+       if (ret) {
+               pagefault_enable();
+               return 0;
+       }
+       pagefault_enable();
+
+       target = branch_target(&instr);
+       if ((!target) || (instr & BRANCH_ABSOLUTE))
+               return target;
+
+       /* Translate relative branch target from kernel to user address */
+       return target - (unsigned long)&instr + addr;
+}
+
+/* Processing BHRB entries */
+void power_pmu_bhrb_read(struct cpu_hw_events *cpuhw)
+{
+       u64 val;
+       u64 addr;
+       int r_index, u_index, pred;
+
+       r_index = 0;
+       u_index = 0;
+       while (r_index < ppmu->bhrb_nr) {
+               /* Assembly read function */
+               val = read_bhrb(r_index++);
+               if (!val)
+                       /* Terminal marker: End of valid BHRB entries */
+                       break;
+               else {
+                       addr = val & BHRB_EA;
+                       pred = val & BHRB_PREDICTION;
+
+                       if (!addr)
+                               /* invalid entry */
+                               continue;
+
+                       /* Branches are read most recent first (ie. mfbhrb 0 is
+                        * the most recent branch).
+                        * There are two types of valid entries:
+                        * 1) a target entry which is the to address of a
+                        *    computed goto like a blr,bctr,btar.  The next
+                        *    entry read from the bhrb will be branch
+                        *    corresponding to this target (ie. the actual
+                        *    blr/bctr/btar instruction).
+                        * 2) a from address which is an actual branch.  If a
+                        *    target entry proceeds this, then this is the
+                        *    matching branch for that target.  If this is not
+                        *    following a target entry, then this is a branch
+                        *    where the target is given as an immediate field
+                        *    in the instruction (ie. an i or b form branch).
+                        *    In this case we need to read the instruction from
+                        *    memory to determine the target/to address.
+                        */
+
+                       if (val & BHRB_TARGET) {
+                               /* Target branches use two entries
+                                * (ie. computed gotos/XL form)
+                                */
+                               cpuhw->bhrb_entries[u_index].to = addr;
+                               cpuhw->bhrb_entries[u_index].mispred = pred;
+                               cpuhw->bhrb_entries[u_index].predicted = ~pred;
+
+                               /* Get from address in next entry */
+                               val = read_bhrb(r_index++);
+                               addr = val & BHRB_EA;
+                               if (val & BHRB_TARGET) {
+                                       /* Shouldn't have two targets in a
+                                          row.. Reset index and try again */
+                                       r_index--;
+                                       addr = 0;
+                               }
+                               cpuhw->bhrb_entries[u_index].from = addr;
+                       } else {
+                               /* Branches to immediate field 
+                                  (ie I or B form) */
+                               cpuhw->bhrb_entries[u_index].from = addr;
+                               cpuhw->bhrb_entries[u_index].to =
+                                       power_pmu_bhrb_to(addr);
+                               cpuhw->bhrb_entries[u_index].mispred = pred;
+                               cpuhw->bhrb_entries[u_index].predicted = ~pred;
+                       }
+                       u_index++;
+
+               }
+       }
+       cpuhw->bhrb_stack.nr = u_index;
+       return;
+}
+
 #endif /* CONFIG_PPC64 */
 
 static void perf_event_interrupt(struct pt_regs *regs);
@@ -904,47 +1058,6 @@ static int collect_events(struct perf_event *group, int max_count,
        return n;
 }
 
-/* Reset all possible BHRB entries */
-static void power_pmu_bhrb_reset(void)
-{
-       asm volatile(PPC_CLRBHRB);
-}
-
-void power_pmu_bhrb_enable(struct perf_event *event)
-{
-       struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events);
-
-       if (!ppmu->bhrb_nr)
-               return;
-
-       /* Clear BHRB if we changed task context to avoid data leaks */
-       if (event->ctx->task && cpuhw->bhrb_context != event->ctx) {
-               power_pmu_bhrb_reset();
-               cpuhw->bhrb_context = event->ctx;
-       }
-       cpuhw->bhrb_users++;
-}
-
-void power_pmu_bhrb_disable(struct perf_event *event)
-{
-       struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events);
-
-       if (!ppmu->bhrb_nr)
-               return;
-
-       cpuhw->bhrb_users--;
-       WARN_ON_ONCE(cpuhw->bhrb_users < 0);
-
-       if (!cpuhw->disabled && !cpuhw->bhrb_users) {
-               /* BHRB cannot be turned off when other
-                * events are active on the PMU.
-                */
-
-               /* avoid stale pointer */
-               cpuhw->bhrb_context = NULL;
-       }
-}
-
 /*
  * Add a event to the PMU.
  * If all events are not already frozen, then we disable and
@@ -1180,15 +1293,6 @@ int power_pmu_commit_txn(struct pmu *pmu)
        return 0;
 }
 
-/* Called from ctxsw to prevent one process's branch entries to
- * mingle with the other process's entries during context switch.
- */
-void power_pmu_flush_branch_stack(void)
-{
-       if (ppmu->bhrb_nr)
-               power_pmu_bhrb_reset();
-}
-
 /*
  * Return 1 if we might be able to put event on a limited PMC,
  * or 0 if not.
@@ -1458,77 +1562,6 @@ struct pmu power_pmu = {
        .flush_branch_stack = power_pmu_flush_branch_stack,
 };
 
-/* Processing BHRB entries */
-void power_pmu_bhrb_read(struct cpu_hw_events *cpuhw)
-{
-       u64 val;
-       u64 addr;
-       int r_index, u_index, target, pred;
-
-       r_index = 0;
-       u_index = 0;
-       while (r_index < ppmu->bhrb_nr) {
-               /* Assembly read function */
-               val = read_bhrb(r_index);
-
-               /* Terminal marker: End of valid BHRB entries */
-               if (val == 0) {
-                       break;
-               } else {
-                       /* BHRB field break up */
-                       addr = val & BHRB_EA;
-                       pred = val & BHRB_PREDICTION;
-                       target = val & BHRB_TARGET;
-
-                       /* Probable Missed entry: Not applicable for POWER8 */
-                       if ((addr == 0) && (target == 0) && (pred == 1)) {
-                               r_index++;
-                               continue;
-                       }
-
-                       /* Real Missed entry: Power8 based missed entry */
-                       if ((addr == 0) && (target == 1) && (pred == 1)) {
-                               r_index++;
-                               continue;
-                       }
-
-                       /* Reserved condition: Not a valid entry  */
-                       if ((addr == 0) && (target == 1) && (pred == 0)) {
-                               r_index++;
-                               continue;
-                       }
-
-                       /* Is a target address */
-                       if (val & BHRB_TARGET) {
-                               /* First address cannot be a target address */
-                               if (r_index == 0) {
-                                       r_index++;
-                                       continue;
-                               }
-
-                               /* Update target address for the previous entry */
-                               cpuhw->bhrb_entries[u_index - 1].to = addr;
-                               cpuhw->bhrb_entries[u_index - 1].mispred = pred;
-                               cpuhw->bhrb_entries[u_index - 1].predicted = ~pred;
-
-                               /* Dont increment u_index */
-                               r_index++;
-                       } else {
-                               /* Update address, flags for current entry */
-                               cpuhw->bhrb_entries[u_index].from = addr;
-                               cpuhw->bhrb_entries[u_index].mispred = pred;
-                               cpuhw->bhrb_entries[u_index].predicted = ~pred;
-
-                               /* Successfully popullated one entry */
-                               u_index++;
-                               r_index++;
-                       }
-               }
-       }
-       cpuhw->bhrb_stack.nr = u_index;
-       return;
-}
-
 /*
  * A counter has overflowed; update its count and record
  * things if requested.  Note that interrupts are hard-disabled
@@ -1725,7 +1758,7 @@ static void perf_event_interrupt(struct pt_regs *regs)
                        }
                }
        }
-       if ((!found) && printk_ratelimit())
+       if (!found && !nmi && printk_ratelimit())
                printk(KERN_WARNING "Can't find PMC that caused IRQ\n");
 
        /*
index a881232..b62aab3 100644 (file)
@@ -128,7 +128,7 @@ config PPC_RTAS_DAEMON
 
 config RTAS_PROC
        bool "Proc interface to RTAS"
-       depends on PPC_RTAS
+       depends on PPC_RTAS && PROC_FS
        default y
 
 config RTAS_FLASH
index d3e840d..c24684c 100644 (file)
@@ -6,6 +6,7 @@ config PPC_POWERNV
        select PPC_ICP_NATIVE
        select PPC_P7_NAP
        select PPC_PCI_CHOICE if EMBEDDED
+       select EPAPR_BOOT
        default y
 
 config POWERNV_MSI
index ade4463..628c564 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/of.h>
 #include <linux/of_platform.h>
 #include <linux/interrupt.h>
+#include <linux/slab.h>
 #include <asm/opal.h>
 #include <asm/firmware.h>
 
@@ -28,6 +29,8 @@ struct opal {
 static struct device_node *opal_node;
 static DEFINE_SPINLOCK(opal_write_lock);
 extern u64 opal_mc_secondary_handler[];
+static unsigned int *opal_irqs;
+static unsigned int opal_irq_count;
 
 int __init early_init_dt_scan_opal(unsigned long node,
                                   const char *uname, int depth, void *data)
@@ -53,7 +56,11 @@ int __init early_init_dt_scan_opal(unsigned long node,
                 opal.entry, entryp, entrysz);
 
        powerpc_firmware_features |= FW_FEATURE_OPAL;
-       if (of_flat_dt_is_compatible(node, "ibm,opal-v2")) {
+       if (of_flat_dt_is_compatible(node, "ibm,opal-v3")) {
+               powerpc_firmware_features |= FW_FEATURE_OPALv2;
+               powerpc_firmware_features |= FW_FEATURE_OPALv3;
+               printk("OPAL V3 detected !\n");
+       } else if (of_flat_dt_is_compatible(node, "ibm,opal-v2")) {
                powerpc_firmware_features |= FW_FEATURE_OPALv2;
                printk("OPAL V2 detected !\n");
        } else {
@@ -144,6 +151,13 @@ int opal_put_chars(uint32_t vtermno, const char *data, int total_len)
                                rc == OPAL_BUSY_EVENT || rc == OPAL_SUCCESS)) {
                len = total_len;
                rc = opal_console_write(vtermno, &len, data);
+
+               /* Closed or other error drop */
+               if (rc != OPAL_SUCCESS && rc != OPAL_BUSY &&
+                   rc != OPAL_BUSY_EVENT) {
+                       written = total_len;
+                       break;
+               }
                if (rc == OPAL_SUCCESS) {
                        total_len -= len;
                        data += len;
@@ -316,6 +330,8 @@ static int __init opal_init(void)
        irqs = of_get_property(opal_node, "opal-interrupts", &irqlen);
        pr_debug("opal: Found %d interrupts reserved for OPAL\n",
                 irqs ? (irqlen / 4) : 0);
+       opal_irq_count = irqlen / 4;
+       opal_irqs = kzalloc(opal_irq_count * sizeof(unsigned int), GFP_KERNEL);
        for (i = 0; irqs && i < (irqlen / 4); i++, irqs++) {
                unsigned int hwirq = be32_to_cpup(irqs);
                unsigned int irq = irq_create_mapping(NULL, hwirq);
@@ -327,7 +343,19 @@ static int __init opal_init(void)
                if (rc)
                        pr_warning("opal: Error %d requesting irq %d"
                                   " (0x%x)\n", rc, irq, hwirq);
+               opal_irqs[i] = irq;
        }
        return 0;
 }
 subsys_initcall(opal_init);
+
+void opal_shutdown(void)
+{
+       unsigned int i;
+
+       for (i = 0; i < opal_irq_count; i++) {
+               if (opal_irqs[i])
+                       free_irq(opal_irqs[i], 0);
+               opal_irqs[i] = 0;
+       }
+}
index 1da578b..9c9d15e 100644 (file)
@@ -68,16 +68,6 @@ define_pe_printk_level(pe_err, KERN_ERR);
 define_pe_printk_level(pe_warn, KERN_WARNING);
 define_pe_printk_level(pe_info, KERN_INFO);
 
-static struct pci_dn *pnv_ioda_get_pdn(struct pci_dev *dev)
-{
-       struct device_node *np;
-
-       np = pci_device_to_OF_node(dev);
-       if (!np)
-               return NULL;
-       return PCI_DN(np);
-}
-
 static int pnv_ioda_alloc_pe(struct pnv_phb *phb)
 {
        unsigned long pe;
@@ -110,7 +100,7 @@ static struct pnv_ioda_pe *pnv_ioda_get_pe(struct pci_dev *dev)
 {
        struct pci_controller *hose = pci_bus_to_host(dev->bus);
        struct pnv_phb *phb = hose->private_data;
-       struct pci_dn *pdn = pnv_ioda_get_pdn(dev);
+       struct pci_dn *pdn = pci_get_pdn(dev);
 
        if (!pdn)
                return NULL;
@@ -173,7 +163,7 @@ static int pnv_ioda_configure_pe(struct pnv_phb *phb, struct pnv_ioda_pe *pe)
 
        /* Add to all parents PELT-V */
        while (parent) {
-               struct pci_dn *pdn = pnv_ioda_get_pdn(parent);
+               struct pci_dn *pdn = pci_get_pdn(parent);
                if (pdn && pdn->pe_number != IODA_INVALID_PE) {
                        rc = opal_pci_set_peltv(phb->opal_id, pdn->pe_number,
                                                pe->pe_number, OPAL_ADD_PE_TO_DOMAIN);
@@ -252,7 +242,7 @@ static struct pnv_ioda_pe *pnv_ioda_setup_dev_PE(struct pci_dev *dev)
 {
        struct pci_controller *hose = pci_bus_to_host(dev->bus);
        struct pnv_phb *phb = hose->private_data;
-       struct pci_dn *pdn = pnv_ioda_get_pdn(dev);
+       struct pci_dn *pdn = pci_get_pdn(dev);
        struct pnv_ioda_pe *pe;
        int pe_num;
 
@@ -323,7 +313,7 @@ static void pnv_ioda_setup_same_PE(struct pci_bus *bus, struct pnv_ioda_pe *pe)
        struct pci_dev *dev;
 
        list_for_each_entry(dev, &bus->devices, bus_list) {
-               struct pci_dn *pdn = pnv_ioda_get_pdn(dev);
+               struct pci_dn *pdn = pci_get_pdn(dev);
 
                if (pdn == NULL) {
                        pr_warn("%s: No device node associated with device !\n",
@@ -436,7 +426,7 @@ static void pnv_pci_ioda_setup_PEs(void)
 
 static void pnv_pci_ioda_dma_dev_setup(struct pnv_phb *phb, struct pci_dev *pdev)
 {
-       struct pci_dn *pdn = pnv_ioda_get_pdn(pdev);
+       struct pci_dn *pdn = pci_get_pdn(pdev);
        struct pnv_ioda_pe *pe;
 
        /*
@@ -768,6 +758,7 @@ static int pnv_pci_ioda_msi_setup(struct pnv_phb *phb, struct pci_dev *dev,
                                  unsigned int is_64, struct msi_msg *msg)
 {
        struct pnv_ioda_pe *pe = pnv_ioda_get_pe(dev);
+       struct pci_dn *pdn = pci_get_pdn(dev);
        struct irq_data *idata;
        struct irq_chip *ichip;
        unsigned int xive_num = hwirq - phb->msi_base;
@@ -783,6 +774,10 @@ static int pnv_pci_ioda_msi_setup(struct pnv_phb *phb, struct pci_dev *dev,
        if (pe->mve_number < 0)
                return -ENXIO;
 
+       /* Force 32-bit MSI on some broken devices */
+       if (pdn && pdn->force_32bit_msi)
+               is_64 = 0;
+
        /* Assign XIVE to PE */
        rc = opal_pci_set_xive_pe(phb->opal_id, pe->pe_number, xive_num);
        if (rc) {
@@ -1035,7 +1030,7 @@ static int pnv_pci_enable_device_hook(struct pci_dev *dev)
        if (!phb->initialized)
                return 0;
 
-       pdn = pnv_ioda_get_pdn(dev);
+       pdn = pci_get_pdn(dev);
        if (!pdn || pdn->pe_number == IODA_INVALID_PE)
                return -EINVAL;
 
@@ -1048,6 +1043,12 @@ static u32 pnv_ioda_bdfn_to_pe(struct pnv_phb *phb, struct pci_bus *bus,
        return phb->ioda.pe_rmap[(bus->number << 8) | devfn];
 }
 
+static void pnv_pci_ioda_shutdown(struct pnv_phb *phb)
+{
+       opal_pci_reset(phb->opal_id, OPAL_PCI_IODA_TABLE_RESET,
+                      OPAL_ASSERT_RESET);
+}
+
 void __init pnv_pci_init_ioda_phb(struct device_node *np, int ioda_type)
 {
        struct pci_controller *hose;
@@ -1178,6 +1179,9 @@ void __init pnv_pci_init_ioda_phb(struct device_node *np, int ioda_type)
        /* Setup TCEs */
        phb->dma_dev_setup = pnv_pci_ioda_dma_dev_setup;
 
+       /* Setup shutdown function for kexec */
+       phb->shutdown = pnv_pci_ioda_shutdown;
+
        /* Setup MSI support */
        pnv_pci_init_ioda_msis(phb);
 
index 55dfca8..277343c 100644 (file)
@@ -47,6 +47,10 @@ static int pnv_msi_check_device(struct pci_dev* pdev, int nvec, int type)
 {
        struct pci_controller *hose = pci_bus_to_host(pdev->bus);
        struct pnv_phb *phb = hose->private_data;
+       struct pci_dn *pdn = pci_get_pdn(pdev);
+
+       if (pdn && pdn->force_32bit_msi && !phb->msi32_support)
+               return -ENODEV;
 
        return (phb && phb->msi_bmp.bitmap) ? 0 : -ENODEV;
 }
@@ -367,7 +371,7 @@ static void pnv_tce_free(struct iommu_table *tbl, long index, long npages)
        while (npages--)
                *(tcep++) = 0;
 
-       if (tbl->it_type & TCE_PCI_SWINV_CREATE)
+       if (tbl->it_type & TCE_PCI_SWINV_FREE)
                pnv_pci_ioda_tce_invalidate(tbl, tces, tcep - 1);
 }
 
@@ -450,6 +454,18 @@ static void pnv_pci_dma_dev_setup(struct pci_dev *pdev)
                pnv_pci_dma_fallback_setup(hose, pdev);
 }
 
+void pnv_pci_shutdown(void)
+{
+       struct pci_controller *hose;
+
+       list_for_each_entry(hose, &hose_list, list_node) {
+               struct pnv_phb *phb = hose->private_data;
+
+               if (phb && phb->shutdown)
+                       phb->shutdown(phb);
+       }
+}
+
 /* Fixup wrong class code in p7ioc and p8 root complex */
 static void pnv_p7ioc_rc_quirk(struct pci_dev *dev)
 {
index 48dc4bb..25d76c4 100644 (file)
@@ -86,6 +86,7 @@ struct pnv_phb {
        void (*dma_dev_setup)(struct pnv_phb *phb, struct pci_dev *pdev);
        void (*fixup_phb)(struct pci_controller *hose);
        u32 (*bdfn_to_pe)(struct pnv_phb *phb, struct pci_bus *bus, u32 devfn);
+       void (*shutdown)(struct pnv_phb *phb);
 
        union {
                struct {
@@ -158,4 +159,5 @@ extern void pnv_pci_init_ioda_hub(struct device_node *np);
 extern void pnv_pci_init_ioda2_phb(struct device_node *np);
 extern void pnv_pci_ioda_tce_invalidate(struct iommu_table *tbl,
                                        u64 *startp, u64 *endp);
+
 #endif /* __POWERNV_PCI_H */
index 8a9df7f..a1c6f83 100644 (file)
@@ -9,8 +9,10 @@ static inline void pnv_smp_init(void) { }
 
 #ifdef CONFIG_PCI
 extern void pnv_pci_init(void);
+extern void pnv_pci_shutdown(void);
 #else
 static inline void pnv_pci_init(void) { }
+static inline void pnv_pci_shutdown(void) { }
 #endif
 
 #endif /* _POWERNV_H */
index db1ad1c..d4459bf 100644 (file)
@@ -78,7 +78,9 @@ static void pnv_show_cpuinfo(struct seq_file *m)
        if (root)
                model = of_get_property(root, "model", NULL);
        seq_printf(m, "machine\t\t: PowerNV %s\n", model);
-       if (firmware_has_feature(FW_FEATURE_OPALv2))
+       if (firmware_has_feature(FW_FEATURE_OPALv3))
+               seq_printf(m, "firmware\t: OPAL v3\n");
+       else if (firmware_has_feature(FW_FEATURE_OPALv2))
                seq_printf(m, "firmware\t: OPAL v2\n");
        else if (firmware_has_feature(FW_FEATURE_OPAL))
                seq_printf(m, "firmware\t: OPAL v1\n");
@@ -126,6 +128,17 @@ static void pnv_progress(char *s, unsigned short hex)
 {
 }
 
+static void pnv_shutdown(void)
+{
+       /* Let the PCI code clear up IODA tables */
+       pnv_pci_shutdown();
+
+       /* And unregister all OPAL interrupts so they don't fire
+        * up while we kexec
+        */
+       opal_shutdown();
+}
+
 #ifdef CONFIG_KEXEC
 static void pnv_kexec_cpu_down(int crash_shutdown, int secondary)
 {
@@ -187,6 +200,7 @@ define_machine(powernv) {
        .init_IRQ               = pnv_init_IRQ,
        .show_cpuinfo           = pnv_show_cpuinfo,
        .progress               = pnv_progress,
+       .machine_shutdown       = pnv_shutdown,
        .power_save             = power7_idle,
        .calibrate_decr         = generic_calibrate_decr,
 #ifdef CONFIG_KEXEC
index 6a3ecca..88c9459 100644 (file)
@@ -71,18 +71,68 @@ int pnv_smp_kick_cpu(int nr)
 
        BUG_ON(nr < 0 || nr >= NR_CPUS);
 
-       /* On OPAL v2 the CPU are still spinning inside OPAL itself,
-        * get them back now
+       /*
+        * If we already started or OPALv2 is not supported, we just
+        * kick the CPU via the PACA
         */
-       if (!paca[nr].cpu_start && firmware_has_feature(FW_FEATURE_OPALv2)) {
-               pr_devel("OPAL: Starting CPU %d (HW 0x%x)...\n", nr, pcpu);
-               rc = opal_start_cpu(pcpu, start_here);
+       if (paca[nr].cpu_start || !firmware_has_feature(FW_FEATURE_OPALv2))
+               goto kick;
+
+       /*
+        * At this point, the CPU can either be spinning on the way in
+        * from kexec or be inside OPAL waiting to be started for the
+        * first time. OPAL v3 allows us to query OPAL to know if it
+        * has the CPUs, so we do that
+        */
+       if (firmware_has_feature(FW_FEATURE_OPALv3)) {
+               uint8_t status;
+
+               rc = opal_query_cpu_status(pcpu, &status);
                if (rc != OPAL_SUCCESS) {
-                       pr_warn("OPAL Error %ld starting CPU %d\n",
+                       pr_warn("OPAL Error %ld querying CPU %d state\n",
                                rc, nr);
                        return -ENODEV;
                }
+
+               /*
+                * Already started, just kick it, probably coming from
+                * kexec and spinning
+                */
+               if (status == OPAL_THREAD_STARTED)
+                       goto kick;
+
+               /*
+                * Available/inactive, let's kick it
+                */
+               if (status == OPAL_THREAD_INACTIVE) {
+                       pr_devel("OPAL: Starting CPU %d (HW 0x%x)...\n",
+                                nr, pcpu);
+                       rc = opal_start_cpu(pcpu, start_here);
+                       if (rc != OPAL_SUCCESS) {
+                               pr_warn("OPAL Error %ld starting CPU %d\n",
+                                       rc, nr);
+                               return -ENODEV;
+                       }
+               } else {
+                       /*
+                        * An unavailable CPU (or any other unknown status)
+                        * shouldn't be started. It should also
+                        * not be in the possible map but currently it can
+                        * happen
+                        */
+                       pr_devel("OPAL: CPU %d (HW 0x%x) is unavailable"
+                                " (status %d)...\n", nr, pcpu, status);
+                       return -ENODEV;
+               }
+       } else {
+               /*
+                * On OPAL v2, we just kick it and hope for the best,
+                * we must not test the error from opal_start_cpu() or
+                * we would fail to get CPUs from kexec.
+                */
+               opal_start_cpu(pcpu, start_here);
        }
+ kick:
        return smp_generic_kick_cpu(nr);
 }
 
index 9a0941b..4459eff 100644 (file)
@@ -18,6 +18,9 @@ config PPC_PSERIES
        select PPC_PCI_CHOICE if EXPERT
        select ZLIB_DEFLATE
        select PPC_DOORBELL
+       select HAVE_CONTEXT_TRACKING
+       select HOTPLUG if SMP
+       select HOTPLUG_CPU if SMP
        default y
 
 config PPC_SPLPAR
index 19506f9..b456b15 100644 (file)
@@ -83,7 +83,11 @@ static int pseries_eeh_init(void)
        ibm_configure_pe                = rtas_token("ibm,configure-pe");
        ibm_configure_bridge            = rtas_token("ibm,configure-bridge");
 
-       /* necessary sanity check */
+       /*
+        * Necessary sanity check. We needn't check "get-config-addr-info"
+        * and its variant since the old firmware probably support address
+        * of domain/bus/slot/function for EEH RTAS operations.
+        */
        if (ibm_set_eeh_option == RTAS_UNKNOWN_SERVICE) {
                pr_warning("%s: RTAS service <ibm,set-eeh-option> invalid\n",
                        __func__);
@@ -102,12 +106,6 @@ static int pseries_eeh_init(void)
                pr_warning("%s: RTAS service <ibm,slot-error-detail> invalid\n",
                        __func__);
                return -EINVAL;
-       } else if (ibm_get_config_addr_info2 == RTAS_UNKNOWN_SERVICE &&
-                  ibm_get_config_addr_info == RTAS_UNKNOWN_SERVICE) {
-               pr_warning("%s: RTAS service <ibm,get-config-addr-info2> and "
-                       "<ibm,get-config-addr-info> invalid\n",
-                       __func__);
-               return -EINVAL;
        } else if (ibm_configure_pe == RTAS_UNKNOWN_SERVICE &&
                   ibm_configure_bridge == RTAS_UNKNOWN_SERVICE) {
                pr_warning("%s: RTAS service <ibm,configure-pe> and "
index 420524e..6d2f0ab 100644 (file)
@@ -26,26 +26,6 @@ static int query_token, change_token;
 #define RTAS_CHANGE_MSIX_FN    4
 #define RTAS_CHANGE_32MSI_FN   5
 
-static struct pci_dn *get_pdn(struct pci_dev *pdev)
-{
-       struct device_node *dn;
-       struct pci_dn *pdn;
-
-       dn = pci_device_to_OF_node(pdev);
-       if (!dn) {
-               dev_dbg(&pdev->dev, "rtas_msi: No OF device node\n");
-               return NULL;
-       }
-
-       pdn = PCI_DN(dn);
-       if (!pdn) {
-               dev_dbg(&pdev->dev, "rtas_msi: No PCI DN\n");
-               return NULL;
-       }
-
-       return pdn;
-}
-
 /* RTAS Helpers */
 
 static int rtas_change_msi(struct pci_dn *pdn, u32 func, u32 num_irqs)
@@ -91,7 +71,7 @@ static void rtas_disable_msi(struct pci_dev *pdev)
 {
        struct pci_dn *pdn;
 
-       pdn = get_pdn(pdev);
+       pdn = pci_get_pdn(pdev);
        if (!pdn)
                return;
 
@@ -152,7 +132,7 @@ static int check_req(struct pci_dev *pdev, int nvec, char *prop_name)
        struct pci_dn *pdn;
        const u32 *req_msi;
 
-       pdn = get_pdn(pdev);
+       pdn = pci_get_pdn(pdev);
        if (!pdn)
                return -ENODEV;
 
@@ -394,6 +374,23 @@ static int check_msix_entries(struct pci_dev *pdev)
        return 0;
 }
 
+static void rtas_hack_32bit_msi_gen2(struct pci_dev *pdev)
+{
+       u32 addr_hi, addr_lo;
+
+       /*
+        * We should only get in here for IODA1 configs. This is based on the
+        * fact that we using RTAS for MSIs, we don't have the 32 bit MSI RTAS
+        * support, and we are in a PCIe Gen2 slot.
+        */
+       dev_info(&pdev->dev,
+                "rtas_msi: No 32 bit MSI firmware support, forcing 32 bit MSI\n");
+       pci_read_config_dword(pdev, pdev->msi_cap + PCI_MSI_ADDRESS_HI, &addr_hi);
+       addr_lo = 0xffff0000 | ((addr_hi >> (48 - 32)) << 4);
+       pci_write_config_dword(pdev, pdev->msi_cap + PCI_MSI_ADDRESS_LO, addr_lo);
+       pci_write_config_dword(pdev, pdev->msi_cap + PCI_MSI_ADDRESS_HI, 0);
+}
+
 static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec_in, int type)
 {
        struct pci_dn *pdn;
@@ -401,8 +398,9 @@ static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec_in, int type)
        struct msi_desc *entry;
        struct msi_msg msg;
        int nvec = nvec_in;
+       int use_32bit_msi_hack = 0;
 
-       pdn = get_pdn(pdev);
+       pdn = pci_get_pdn(pdev);
        if (!pdn)
                return -ENODEV;
 
@@ -428,15 +426,31 @@ static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec_in, int type)
         */
 again:
        if (type == PCI_CAP_ID_MSI) {
-               if (pdn->force_32bit_msi)
+               if (pdn->force_32bit_msi) {
                        rc = rtas_change_msi(pdn, RTAS_CHANGE_32MSI_FN, nvec);
-               else
+                       if (rc < 0) {
+                               /*
+                                * We only want to run the 32 bit MSI hack below if
+                                * the max bus speed is Gen2 speed
+                                */
+                               if (pdev->bus->max_bus_speed != PCIE_SPEED_5_0GT)
+                                       return rc;
+
+                               use_32bit_msi_hack = 1;
+                       }
+               } else
+                       rc = -1;
+
+               if (rc < 0)
                        rc = rtas_change_msi(pdn, RTAS_CHANGE_MSI_FN, nvec);
 
-               if (rc < 0 && !pdn->force_32bit_msi) {
+               if (rc < 0) {
                        pr_debug("rtas_msi: trying the old firmware call.\n");
                        rc = rtas_change_msi(pdn, RTAS_CHANGE_FN, nvec);
                }
+
+               if (use_32bit_msi_hack && rc > 0)
+                       rtas_hack_32bit_msi_gen2(pdev);
        } else
                rc = rtas_change_msi(pdn, RTAS_CHANGE_MSIX_FN, nvec);
 
@@ -518,12 +532,3 @@ static int rtas_msi_init(void)
 }
 arch_initcall(rtas_msi_init);
 
-static void quirk_radeon(struct pci_dev *dev)
-{
-       struct pci_dn *pdn = get_pdn(dev);
-
-       if (pdn)
-               pdn->force_32bit_msi = 1;
-}
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x68f2, quirk_radeon);
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0xaa68, quirk_radeon);
index 47226e0..5f997e7 100644 (file)
@@ -16,6 +16,7 @@
   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
   */
 
+#include <linux/cpu.h>
 #include <linux/delay.h>
 #include <linux/suspend.h>
 #include <linux/stat.h>
@@ -126,11 +127,15 @@ static ssize_t store_hibernate(struct device *dev,
                               struct device_attribute *attr,
                               const char *buf, size_t count)
 {
+       cpumask_var_t offline_mask;
        int rc;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
+       if (!alloc_cpumask_var(&offline_mask, GFP_TEMPORARY))
+               return -ENOMEM;
+
        stream_id = simple_strtoul(buf, NULL, 16);
 
        do {
@@ -140,15 +145,32 @@ static ssize_t store_hibernate(struct device *dev,
        } while (rc == -EAGAIN);
 
        if (!rc) {
+               /* All present CPUs must be online */
+               cpumask_andnot(offline_mask, cpu_present_mask,
+                               cpu_online_mask);
+               rc = rtas_online_cpus_mask(offline_mask);
+               if (rc) {
+                       pr_err("%s: Could not bring present CPUs online.\n",
+                                       __func__);
+                       goto out;
+               }
+
                stop_topology_update();
                rc = pm_suspend(PM_SUSPEND_MEM);
                start_topology_update();
+
+               /* Take down CPUs not online prior to suspend */
+               if (!rtas_offline_cpus_mask(offline_mask))
+                       pr_warn("%s: Could not restore CPUs to offline "
+                                       "state.\n", __func__);
        }
 
        stream_id = 0;
 
        if (!rc)
                rc = count;
+out:
+       free_cpumask_var(offline_mask);
        return rc;
 }
 
index 97fe82e..2d3b1dd 100644 (file)
@@ -361,7 +361,7 @@ static int wsp_chip_set_affinity(struct irq_data *d,
        xive = xive_set_server(xive, get_irq_server(ics, hw_irq));
        wsp_ics_set_xive(ics, hw_irq, xive);
 
-       return 0;
+       return IRQ_SET_MASK_OK;
 }
 
 static struct irq_chip wsp_irq_chip = {
index b0a518e..99464a7 100644 (file)
@@ -64,6 +64,8 @@ endif
 
 obj-$(CONFIG_PPC_SCOM)         += scom.o
 
+obj-$(CONFIG_PPC_EARLY_DEBUG_MEMCONS)  += udbg_memcons.o
+
 subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
 
 obj-$(CONFIG_PPC_XICS)         += xics/
index 6e0e100..9cd0e60 100644 (file)
@@ -81,7 +81,7 @@ int ehv_pic_set_affinity(struct irq_data *d, const struct cpumask *dest,
        ev_int_set_config(src, config, prio, cpuid);
        spin_unlock_irqrestore(&ehv_pic_lock, flags);
 
-       return 0;
+       return IRQ_SET_MASK_OK;
 }
 
 static unsigned int ehv_pic_type_to_vecpri(unsigned int type)
index ee21b5e..3cc2f91 100644 (file)
@@ -54,7 +54,7 @@ static DEFINE_RAW_SPINLOCK(mpic_lock);
 
 #ifdef CONFIG_PPC32    /* XXX for now */
 #ifdef CONFIG_IRQ_ALL_CPUS
-#define distribute_irqs        (!(mpic->flags & MPIC_SINGLE_DEST_CPU))
+#define distribute_irqs        (1)
 #else
 #define distribute_irqs        (0)
 #endif
@@ -836,7 +836,7 @@ int mpic_set_affinity(struct irq_data *d, const struct cpumask *cpumask,
                               mpic_physmask(mask));
        }
 
-       return 0;
+       return IRQ_SET_MASK_OK;
 }
 
 static unsigned int mpic_type_to_vecpri(struct mpic *mpic, unsigned int type)
@@ -1703,7 +1703,7 @@ void mpic_setup_this_cpu(void)
         * it differently, then we should make sure we also change the default
         * values of irq_desc[].affinity in irq.c.
         */
-       if (distribute_irqs) {
+       if (distribute_irqs && !(mpic->flags & MPIC_SINGLE_DEST_CPU)) {
                for (i = 0; i < mpic->num_sources ; i++)
                        mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION),
                                mpic_irq_read(i, MPIC_INFO(IRQ_DESTINATION)) | msk);
diff --git a/arch/powerpc/sysdev/udbg_memcons.c b/arch/powerpc/sysdev/udbg_memcons.c
new file mode 100644 (file)
index 0000000..ce5a7b4
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * A udbg backend which logs messages and reads input from in memory
+ * buffers.
+ *
+ * The console output can be read from memcons_output which is a
+ * circular buffer whose next write position is stored in memcons.output_pos.
+ *
+ * Input may be passed by writing into the memcons_input buffer when it is
+ * empty. The input buffer is empty when both input_pos == input_start and
+ * *input_start == '\0'.
+ *
+ * Copyright (C) 2003-2005 Anton Blanchard and Milton Miller, IBM Corp
+ * Copyright (C) 2013 Alistair Popple, IBM Corp
+ *
+ *      This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License
+ *      as published by the Free Software Foundation; either version
+ *      2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <asm/barrier.h>
+#include <asm/page.h>
+#include <asm/processor.h>
+#include <asm/udbg.h>
+
+struct memcons {
+       char *output_start;
+       char *output_pos;
+       char *output_end;
+       char *input_start;
+       char *input_pos;
+       char *input_end;
+};
+
+static char memcons_output[CONFIG_PPC_MEMCONS_OUTPUT_SIZE];
+static char memcons_input[CONFIG_PPC_MEMCONS_INPUT_SIZE];
+
+struct memcons memcons = {
+       .output_start = memcons_output,
+       .output_pos = memcons_output,
+       .output_end = &memcons_output[CONFIG_PPC_MEMCONS_OUTPUT_SIZE],
+       .input_start = memcons_input,
+       .input_pos = memcons_input,
+       .input_end = &memcons_input[CONFIG_PPC_MEMCONS_INPUT_SIZE],
+};
+
+void memcons_putc(char c)
+{
+       char *new_output_pos;
+
+       *memcons.output_pos = c;
+       wmb();
+       new_output_pos = memcons.output_pos + 1;
+       if (new_output_pos >= memcons.output_end)
+               new_output_pos = memcons.output_start;
+
+       memcons.output_pos = new_output_pos;
+}
+
+int memcons_getc_poll(void)
+{
+       char c;
+       char *new_input_pos;
+
+       if (*memcons.input_pos) {
+               c = *memcons.input_pos;
+
+               new_input_pos = memcons.input_pos + 1;
+               if (new_input_pos >= memcons.input_end)
+                       new_input_pos = memcons.input_start;
+               else if (*new_input_pos == '\0')
+                       new_input_pos = memcons.input_start;
+
+               *memcons.input_pos = '\0';
+               wmb();
+               memcons.input_pos = new_input_pos;
+               return c;
+       }
+
+       return -1;
+}
+
+int memcons_getc(void)
+{
+       int c;
+
+       while (1) {
+               c = memcons_getc_poll();
+               if (c == -1)
+                       cpu_relax();
+               else
+                       break;
+       }
+
+       return c;
+}
+
+void udbg_init_memcons(void)
+{
+       udbg_putc = memcons_putc;
+       udbg_getc = memcons_getc;
+       udbg_getc_poll = memcons_getc_poll;
+}
index f7e8609..39d7221 100644 (file)
@@ -148,7 +148,7 @@ static int ics_opal_set_affinity(struct irq_data *d,
                       __func__, d->irq, hw_irq, server, rc);
                return -1;
        }
-       return 0;
+       return IRQ_SET_MASK_OK;
 }
 
 static struct irq_chip ics_opal_irq_chip = {
index 2c9789d..da183c5 100644 (file)
@@ -98,7 +98,6 @@ config S390
        select CLONE_BACKWARDS2
        select GENERIC_CLOCKEVENTS
        select GENERIC_CPU_DEVICES if !SMP
-       select GENERIC_KERNEL_THREAD
        select GENERIC_SMP_IDLE_THREAD
        select GENERIC_TIME_VSYSCALL_OLD
        select HAVE_ALIGNED_STRUCT_PAGE if SLUB
index bae0f40..87a2209 100644 (file)
@@ -212,7 +212,9 @@ appldata_timer_handler(ctl_table *ctl, int write,
                return 0;
        }
        if (!write) {
-               len = sprintf(buf, appldata_timer_active ? "1\n" : "0\n");
+               strncpy(buf, appldata_timer_active ? "1\n" : "0\n",
+                       ARRAY_SIZE(buf));
+               len = strnlen(buf, ARRAY_SIZE(buf));
                if (len > *lenp)
                        len = *lenp;
                if (copy_to_user(buffer, buf, len))
@@ -317,7 +319,8 @@ appldata_generic_handler(ctl_table *ctl, int write,
                return 0;
        }
        if (!write) {
-               len = sprintf(buf, ops->active ? "1\n" : "0\n");
+               strncpy(buf, ops->active ? "1\n" : "0\n", ARRAY_SIZE(buf));
+               len = strnlen(buf, ARRAY_SIZE(buf));
                if (len > *lenp)
                        len = *lenp;
                if (copy_to_user(buffer, buf, len)) {
index 9411db6..886ac7d 100644 (file)
@@ -71,8 +71,8 @@ static inline void dma_free_coherent(struct device *dev, size_t size,
 {
        struct dma_map_ops *dma_ops = get_dma_ops(dev);
 
-       dma_ops->free(dev, size, cpu_addr, dma_handle, NULL);
        debug_dma_free_coherent(dev, size, cpu_addr, dma_handle);
+       dma_ops->free(dev, size, cpu_addr, dma_handle, NULL);
 }
 
 #endif /* _ASM_S390_DMA_MAPPING_H */
index b7931fa..bf246da 100644 (file)
@@ -9,11 +9,6 @@ struct dyn_arch_ftrace { };
 
 #define MCOUNT_ADDR ((long)_mcount)
 
-#ifdef CONFIG_64BIT
-#define MCOUNT_INSN_SIZE  12
-#else
-#define MCOUNT_INSN_SIZE  20
-#endif
 
 static inline unsigned long ftrace_call_adjust(unsigned long addr)
 {
@@ -21,4 +16,11 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
 }
 
 #endif /* __ASSEMBLY__ */
+
+#ifdef CONFIG_64BIT
+#define MCOUNT_INSN_SIZE  12
+#else
+#define MCOUNT_INSN_SIZE  22
+#endif
+
 #endif /* _ASM_S390_FTRACE_H */
index 379d96e..fd9be01 100644 (file)
@@ -36,6 +36,7 @@ static inline void * phys_to_virt(unsigned long address)
 }
 
 void *xlate_dev_mem_ptr(unsigned long phys);
+#define xlate_dev_mem_ptr xlate_dev_mem_ptr
 void unxlate_dev_mem_ptr(unsigned long phys, void *addr);
 
 /*
index 75ce9b0..5d64fb7 100644 (file)
@@ -32,7 +32,7 @@
 
 void storage_key_init_range(unsigned long start, unsigned long end);
 
-static unsigned long pfmf(unsigned long function, unsigned long address)
+static inline unsigned long pfmf(unsigned long function, unsigned long address)
 {
        asm volatile(
                "       .insn   rre,0xb9af0000,%[function],%[address]"
@@ -44,17 +44,13 @@ static unsigned long pfmf(unsigned long function, unsigned long address)
 
 static inline void clear_page(void *page)
 {
-       if (MACHINE_HAS_PFMF) {
-               pfmf(0x10000, (unsigned long)page);
-       } else {
-               register unsigned long reg1 asm ("1") = 0;
-               register void *reg2 asm ("2") = page;
-               register unsigned long reg3 asm ("3") = 4096;
-               asm volatile(
-                       "       mvcl    2,0"
-                       : "+d" (reg2), "+d" (reg3) : "d" (reg1)
-                       : "memory", "cc");
-       }
+       register unsigned long reg1 asm ("1") = 0;
+       register void *reg2 asm ("2") = page;
+       register unsigned long reg3 asm ("3") = 4096;
+       asm volatile(
+               "       mvcl    2,0"
+               : "+d" (reg2), "+d" (reg3) : "d" (reg1)
+               : "memory", "cc");
 }
 
 static inline void copy_page(void *to, void *from)
index 4105b82..ac01463 100644 (file)
@@ -306,7 +306,7 @@ extern unsigned long MODULES_END;
 #define RCP_HC_BIT     0x00200000UL
 #define RCP_GR_BIT     0x00040000UL
 #define RCP_GC_BIT     0x00020000UL
-#define RCP_IN_BIT     0x00008000UL    /* IPTE notify bit */
+#define RCP_IN_BIT     0x00002000UL    /* IPTE notify bit */
 
 /* User dirty / referenced bit for KVM's migration feature */
 #define KVM_UR_BIT     0x00008000UL
@@ -374,7 +374,7 @@ extern unsigned long MODULES_END;
 #define RCP_HC_BIT     0x0020000000000000UL
 #define RCP_GR_BIT     0x0004000000000000UL
 #define RCP_GC_BIT     0x0002000000000000UL
-#define RCP_IN_BIT     0x0000800000000000UL    /* IPTE notify bit */
+#define RCP_IN_BIT     0x0000200000000000UL    /* IPTE notify bit */
 
 /* User dirty / referenced bit for KVM's migration feature */
 #define KVM_UR_BIT     0x0000800000000000UL
@@ -646,7 +646,7 @@ static inline pgste_t pgste_update_all(pte_t *ptep, pgste_t pgste)
        unsigned long address, bits;
        unsigned char skey;
 
-       if (!pte_present(*ptep))
+       if (pte_val(*ptep) & _PAGE_INVALID)
                return pgste;
        address = pte_val(*ptep) & PAGE_MASK;
        skey = page_get_storage_key(address);
@@ -680,7 +680,7 @@ static inline pgste_t pgste_update_young(pte_t *ptep, pgste_t pgste)
 #ifdef CONFIG_PGSTE
        int young;
 
-       if (!pte_present(*ptep))
+       if (pte_val(*ptep) & _PAGE_INVALID)
                return pgste;
        /* Get referenced bit from storage key */
        young = page_reset_referenced(pte_val(*ptep) & PAGE_MASK);
@@ -706,7 +706,7 @@ static inline void pgste_set_key(pte_t *ptep, pgste_t pgste, pte_t entry)
        unsigned long address;
        unsigned long okey, nkey;
 
-       if (!pte_present(entry))
+       if (pte_val(entry) & _PAGE_INVALID)
                return;
        address = pte_val(entry) & PAGE_MASK;
        okey = nkey = page_get_storage_key(address);
@@ -1098,6 +1098,9 @@ static inline pte_t ptep_modify_prot_start(struct mm_struct *mm,
        pte = *ptep;
        if (!mm_exclusive(mm))
                __ptep_ipte(address, ptep);
+
+       if (mm_has_pgste(mm))
+               pgste = pgste_update_all(&pte, pgste);
        return pte;
 }
 
@@ -1105,9 +1108,13 @@ static inline void ptep_modify_prot_commit(struct mm_struct *mm,
                                           unsigned long address,
                                           pte_t *ptep, pte_t pte)
 {
+       pgste_t pgste;
+
        if (mm_has_pgste(mm)) {
+               pgste = *(pgste_t *)(ptep + PTRS_PER_PTE);
+               pgste_set_key(ptep, pgste, pte);
                pgste_set_pte(ptep, pte);
-               pgste_set_unlock(ptep, *(pgste_t *)(ptep + PTRS_PER_PTE));
+               pgste_set_unlock(ptep, pgste);
        } else
                *ptep = pte;
 }
index 2d72d9e..9cb1b97 100644 (file)
@@ -793,10 +793,6 @@ ENTRY(sys32_stime_wrapper)
        llgtr   %r2,%r2                 # long *
        jg      compat_sys_stime        # branch to system call
 
-ENTRY(sys32_sysctl_wrapper)
-       llgtr   %r2,%r2                 # struct compat_sysctl_args *
-       jg      compat_sys_sysctl
-
 ENTRY(sys32_fstat64_wrapper)
        llgfr   %r2,%r2                 # unsigned long
        llgtr   %r3,%r3                 # struct stat64 *
@@ -1349,15 +1345,6 @@ ENTRY(sys_fanotify_init_wrapper)
        llgfr   %r3,%r3                 # unsigned int
        jg      sys_fanotify_init       # branch to system call
 
-ENTRY(sys_fanotify_mark_wrapper)
-       lgfr    %r2,%r2                 # int
-       llgfr   %r3,%r3                 # unsigned int
-       sllg    %r4,%r4,32              # get high word of 64bit mask
-       lr      %r4,%r5                 # get low word of 64bit mask
-       llgfr   %r5,%r6                 # unsigned int
-       llgt    %r6,164(%r15)           # char *
-       jg      sys_fanotify_mark       # branch to system call
-
 ENTRY(sys_prlimit64_wrapper)
        lgfr    %r2,%r2                 # pid_t
        llgfr   %r3,%r3                 # unsigned int
index 7f4a4a8..be87d3e 100644 (file)
@@ -1862,6 +1862,8 @@ void print_fn_code(unsigned char *code, unsigned long len)
        while (len) {
                ptr = buffer;
                opsize = insn_length(*code);
+               if (opsize > len)
+                       break;
                ptr += sprintf(ptr, "%p: ", code);
                for (i = 0; i < opsize; i++)
                        ptr += sprintf(ptr, "%02x", code[i]);
index 78bdf0e..e3043ae 100644 (file)
 #include <trace/syscall.h>
 #include <asm/asm-offsets.h>
 
-#ifdef CONFIG_64BIT
-#define MCOUNT_OFFSET_RET 12
-#else
-#define MCOUNT_OFFSET_RET 22
-#endif
-
 #ifdef CONFIG_DYNAMIC_FTRACE
 
 void ftrace_disable_code(void);
@@ -155,9 +149,10 @@ unsigned long __kprobes prepare_ftrace_return(unsigned long parent,
 
        if (unlikely(atomic_read(&current->tracing_graph_pause)))
                goto out;
+       ip = (ip & PSW_ADDR_INSN) - MCOUNT_INSN_SIZE;
        if (ftrace_push_return_trace(parent, ip, &trace.depth, 0) == -EBUSY)
                goto out;
-       trace.func = (ip & PSW_ADDR_INSN) - MCOUNT_OFFSET_RET;
+       trace.func = ip;
        /* Only trace if the calling function expects to. */
        if (!ftrace_graph_entry(&trace)) {
                current->curr_ret_stack--;
index 4567ce2..08dcf21 100644 (file)
@@ -7,6 +7,7 @@
 
 #include <linux/linkage.h>
 #include <asm/asm-offsets.h>
+#include <asm/ftrace.h>
 
        .section .kprobes.text, "ax"
 
@@ -33,6 +34,7 @@ ENTRY(ftrace_caller)
        la      %r2,0(%r14)
        st      %r0,__SF_BACKCHAIN(%r15)
        la      %r3,0(%r3)
+       ahi     %r2,-MCOUNT_INSN_SIZE
        l       %r14,0b-0b(%r1)
        l       %r14,0(%r14)
        basr    %r14,%r14
index 1133219..1c52eae 100644 (file)
@@ -7,6 +7,7 @@
 
 #include <linux/linkage.h>
 #include <asm/asm-offsets.h>
+#include <asm/ftrace.h>
 
        .section .kprobes.text, "ax"
 
@@ -29,6 +30,7 @@ ENTRY(ftrace_caller)
        stg     %r1,__SF_BACKCHAIN(%r15)
        lgr     %r2,%r14
        lg      %r3,168(%r15)
+       aghi    %r2,-MCOUNT_INSN_SIZE
        larl    %r14,ftrace_trace_function
        lg      %r14,0(%r14)
        basr    %r14,%r14
index 8074cb4..4f977d0 100644 (file)
@@ -428,34 +428,27 @@ void smp_stop_cpu(void)
  * This is the main routine where commands issued by other
  * cpus are handled.
  */
-static void do_ext_call_interrupt(struct ext_code ext_code,
-                                 unsigned int param32, unsigned long param64)
+static void smp_handle_ext_call(void)
 {
        unsigned long bits;
-       int cpu;
-
-       cpu = smp_processor_id();
-       if (ext_code.code == 0x1202)
-               inc_irq_stat(IRQEXT_EXC);
-       else
-               inc_irq_stat(IRQEXT_EMS);
-       /*
-        * handle bit signal external calls
-        */
-       bits = xchg(&pcpu_devices[cpu].ec_mask, 0);
 
+       /* handle bit signal external calls */
+       bits = xchg(&pcpu_devices[smp_processor_id()].ec_mask, 0);
        if (test_bit(ec_stop_cpu, &bits))
                smp_stop_cpu();
-
        if (test_bit(ec_schedule, &bits))
                scheduler_ipi();
-
        if (test_bit(ec_call_function, &bits))
                generic_smp_call_function_interrupt();
-
        if (test_bit(ec_call_function_single, &bits))
                generic_smp_call_function_single_interrupt();
+}
 
+static void do_ext_call_interrupt(struct ext_code ext_code,
+                                 unsigned int param32, unsigned long param64)
+{
+       inc_irq_stat(ext_code.code == 0x1202 ? IRQEXT_EXC : IRQEXT_EMS);
+       smp_handle_ext_call();
 }
 
 void arch_send_call_function_ipi_mask(const struct cpumask *mask)
@@ -645,7 +638,7 @@ static int __cpuinit __smp_rescan_cpus(struct sclp_cpu_info *info,
                        continue;
                pcpu = pcpu_devices + cpu;
                pcpu->address = info->cpu[i].address;
-               pcpu->state = (cpu >= info->configured) ?
+               pcpu->state = (i >= info->configured) ?
                        CPU_STATE_STANDBY : CPU_STATE_CONFIGURED;
                smp_cpu_set_polarization(cpu, POLARIZATION_UNKNOWN);
                set_cpu_present(cpu, true);
@@ -760,6 +753,8 @@ int __cpu_disable(void)
 {
        unsigned long cregs[16];
 
+       /* Handle possible pending IPIs */
+       smp_handle_ext_call();
        set_cpu_online(smp_processor_id(), false);
        /* Disable pseudo page faults on this cpu. */
        pfault_fini();
index 9f214e9..913410b 100644 (file)
@@ -157,7 +157,7 @@ SYSCALL(sys_readv,sys_readv,compat_sys_readv_wrapper)               /* 145 */
 SYSCALL(sys_writev,sys_writev,compat_sys_writev_wrapper)
 SYSCALL(sys_getsid,sys_getsid,sys32_getsid_wrapper)
 SYSCALL(sys_fdatasync,sys_fdatasync,sys32_fdatasync_wrapper)
-SYSCALL(sys_sysctl,sys_sysctl,sys32_sysctl_wrapper)
+SYSCALL(sys_sysctl,sys_sysctl,compat_sys_sysctl)
 SYSCALL(sys_mlock,sys_mlock,sys32_mlock_wrapper)               /* 150 */
 SYSCALL(sys_munlock,sys_munlock,sys32_munlock_wrapper)
 SYSCALL(sys_mlockall,sys_mlockall,sys32_mlockall_wrapper)
@@ -341,7 +341,7 @@ SYSCALL(sys_pwritev,sys_pwritev,compat_sys_pwritev)
 SYSCALL(sys_rt_tgsigqueueinfo,sys_rt_tgsigqueueinfo,compat_sys_rt_tgsigqueueinfo) /* 330 */
 SYSCALL(sys_perf_event_open,sys_perf_event_open,sys_perf_event_open_wrapper)
 SYSCALL(sys_fanotify_init,sys_fanotify_init,sys_fanotify_init_wrapper)
-SYSCALL(sys_fanotify_mark,sys_fanotify_mark,sys_fanotify_mark_wrapper)
+SYSCALL(sys_fanotify_mark,sys_fanotify_mark,compat_sys_fanotify_mark)
 SYSCALL(sys_prlimit64,sys_prlimit64,sys_prlimit64_wrapper)
 SYSCALL(sys_name_to_handle_at,sys_name_to_handle_at,sys_name_to_handle_at_wrapper) /* 335 */
 SYSCALL(sys_open_by_handle_at,sys_open_by_handle_at,compat_sys_open_by_handle_at)
index 7805ddc..a938b54 100644 (file)
@@ -492,7 +492,7 @@ static int gmap_connect_pgtable(unsigned long address, unsigned long segment,
        mp = (struct gmap_pgtable *) page->index;
        rmap->gmap = gmap;
        rmap->entry = segment_ptr;
-       rmap->vmaddr = address;
+       rmap->vmaddr = address & PMD_MASK;
        spin_lock(&mm->page_table_lock);
        if (*segment_ptr == segment) {
                list_add(&rmap->list, &mp->mapper);
@@ -677,8 +677,7 @@ int gmap_ipte_notify(struct gmap *gmap, unsigned long start, unsigned long len)
                        break;
                }
                /* Get the page mapped */
-               if (get_user_pages(current, gmap->mm, addr, 1, 1, 0,
-                                  NULL, NULL) != 1) {
+               if (fixup_user_fault(current, gmap->mm, addr, FAULT_FLAG_WRITE)) {
                        rc = -EFAULT;
                        break;
                }
index d8f988a..0940682 100644 (file)
@@ -41,8 +41,6 @@
 unsigned long empty_zero_page;
 EXPORT_SYMBOL_GPL(empty_zero_page);
 
-static struct kcore_list kcore_mem, kcore_vmalloc;
-
 static void setup_zero_page(void)
 {
        struct page *page;
index 2e680b5..f7c72b6 100644 (file)
@@ -239,15 +239,6 @@ do_sys_accept4: /* sys_accept4(int, struct sockaddr *, int *, int) */
        nop
        nop
 
-       .globl          sys32_fanotify_mark
-sys32_fanotify_mark:
-       sethi           %hi(sys_fanotify_mark), %g1
-       sllx            %o2, 32, %o2
-       or              %o2, %o3, %o2
-       mov             %o4, %o3
-       jmpl            %g1 + %lo(sys_fanotify_mark), %g0
-        mov            %o5, %o4
-
        .section        __ex_table,"a"
        .align          4
        .word           1b, __retl_efault, 2b, __retl_efault
index 8fd9320..6d81597 100644 (file)
@@ -84,7 +84,7 @@ sys_call_table32:
        .word compat_sys_timerfd_settime, compat_sys_timerfd_gettime, compat_sys_signalfd4, sys_eventfd2, sys_epoll_create1
 /*320*/        .word sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, compat_sys_preadv
        .word compat_sys_pwritev, compat_sys_rt_tgsigqueueinfo, sys_perf_event_open, compat_sys_recvmmsg, sys_fanotify_init
-/*330*/        .word sys32_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, compat_sys_open_by_handle_at, compat_sys_clock_adjtime
+/*330*/        .word compat_sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, compat_sys_open_by_handle_at, compat_sys_clock_adjtime
        .word sys_syncfs, compat_sys_sendmmsg, sys_setns, compat_sys_process_vm_readv, compat_sys_process_vm_writev
 /*340*/        .word sys_kern_features, sys_kcmp, sys_finit_module
 
index cfe79c9..f9e8625 100644 (file)
 #include <asm/syscalls.h>
 #include <asm/cacheflush.h>
 
-/* Note: used by the compat code even in 64-bit Linux. */
-SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len,
-               unsigned long, prot, unsigned long, flags,
-               unsigned long, fd, unsigned long, off_4k)
-{
-       return sys_mmap_pgoff(addr, len, prot, flags, fd,
-                             off_4k);
-}
-
 /* Provide the actual syscall number to call mapping. */
 #undef __SYSCALL
 #define __SYSCALL(nr, call)    [nr] = (call),
 
+#define sys_mmap2 sys_mmap_pgoff
 /* Note that we don't include <linux/unistd.h> but <asm/unistd.h> */
 void *sys_call_table[__NR_syscalls] = {
        [0 ... __NR_syscalls-1] = sys_ni_syscall,
index 6a154a9..685692c 100644 (file)
@@ -108,7 +108,6 @@ config X86
        select GENERIC_CLOCKEVENTS_BROADCAST if X86_64 || (X86_32 && X86_LOCAL_APIC)
        select GENERIC_TIME_VSYSCALL if X86_64
        select KTIME_SCALAR if X86_32
-       select ALWAYS_USE_PERSISTENT_CLOCK
        select GENERIC_STRNCPY_FROM_USER
        select GENERIC_STRNLEN_USER
        select HAVE_CONTEXT_TRACKING if X86_64
index 94c27df..f247304 100644 (file)
@@ -240,7 +240,7 @@ fold_64:
        pand    %xmm3, %xmm1
        PCLMULQDQ 0x00, CONSTANT, %xmm1
        pxor    %xmm2, %xmm1
-       pextrd  $0x01, %xmm1, %eax
+       PEXTRD  0x01, %xmm1, %eax
 
        ret
 ENDPROC(crc32_pclmul_le_16)
index 56610c4..642f156 100644 (file)
@@ -118,7 +118,7 @@ y2 = %r15d
 
 _INP_END_SIZE = 8
 _INP_SIZE = 8
-_XFER_SIZE = 8
+_XFER_SIZE = 16
 _XMM_SAVE_SIZE = 0
 
 _INP_END = 0
index 98d3c39..f833b74 100644 (file)
@@ -111,7 +111,7 @@ y2 = %r15d
 
 _INP_END_SIZE = 8
 _INP_SIZE = 8
-_XFER_SIZE = 8
+_XFER_SIZE = 16
 _XMM_SAVE_SIZE = 0
 
 _INP_END = 0
index 4e4907c..8e0ceec 100644 (file)
@@ -243,12 +243,3 @@ asmlinkage long sys32_fallocate(int fd, int mode, unsigned offset_lo,
        return sys_fallocate(fd, mode, ((u64)offset_hi << 32) | offset_lo,
                             ((u64)len_hi << 32) | len_lo);
 }
-
-asmlinkage long sys32_fanotify_mark(int fanotify_fd, unsigned int flags,
-                                   u32 mask_lo, u32 mask_hi,
-                                   int fd, const char  __user *pathname)
-{
-       return sys_fanotify_mark(fanotify_fd, flags,
-                                ((u64)mask_hi << 32) | mask_lo,
-                                fd, pathname);
-}
index 280bf7f..3e11527 100644 (file)
@@ -9,12 +9,68 @@
 
 #define REG_NUM_INVALID                100
 
-#define REG_TYPE_R64           0
-#define REG_TYPE_XMM           1
+#define REG_TYPE_R32           0
+#define REG_TYPE_R64           1
+#define REG_TYPE_XMM           2
 #define REG_TYPE_INVALID       100
 
+       .macro R32_NUM opd r32
+       \opd = REG_NUM_INVALID
+       .ifc \r32,%eax
+       \opd = 0
+       .endif
+       .ifc \r32,%ecx
+       \opd = 1
+       .endif
+       .ifc \r32,%edx
+       \opd = 2
+       .endif
+       .ifc \r32,%ebx
+       \opd = 3
+       .endif
+       .ifc \r32,%esp
+       \opd = 4
+       .endif
+       .ifc \r32,%ebp
+       \opd = 5
+       .endif
+       .ifc \r32,%esi
+       \opd = 6
+       .endif
+       .ifc \r32,%edi
+       \opd = 7
+       .endif
+#ifdef CONFIG_X86_64
+       .ifc \r32,%r8d
+       \opd = 8
+       .endif
+       .ifc \r32,%r9d
+       \opd = 9
+       .endif
+       .ifc \r32,%r10d
+       \opd = 10
+       .endif
+       .ifc \r32,%r11d
+       \opd = 11
+       .endif
+       .ifc \r32,%r12d
+       \opd = 12
+       .endif
+       .ifc \r32,%r13d
+       \opd = 13
+       .endif
+       .ifc \r32,%r14d
+       \opd = 14
+       .endif
+       .ifc \r32,%r15d
+       \opd = 15
+       .endif
+#endif
+       .endm
+
        .macro R64_NUM opd r64
        \opd = REG_NUM_INVALID
+#ifdef CONFIG_X86_64
        .ifc \r64,%rax
        \opd = 0
        .endif
        .ifc \r64,%r15
        \opd = 15
        .endif
+#endif
        .endm
 
        .macro XMM_NUM opd xmm
        .endm
 
        .macro REG_TYPE type reg
+       R32_NUM reg_type_r32 \reg
        R64_NUM reg_type_r64 \reg
        XMM_NUM reg_type_xmm \reg
        .if reg_type_r64 <> REG_NUM_INVALID
        \type = REG_TYPE_R64
+       .elseif reg_type_r32 <> REG_NUM_INVALID
+       \type = REG_TYPE_R32
        .elseif reg_type_xmm <> REG_NUM_INVALID
        \type = REG_TYPE_XMM
        .else
        .byte \imm8
        .endm
 
+       .macro PEXTRD imm8 xmm gpr
+       R32_NUM extrd_opd1 \gpr
+       XMM_NUM extrd_opd2 \xmm
+       PFX_OPD_SIZE
+       PFX_REX extrd_opd1 extrd_opd2
+       .byte 0x0f, 0x3a, 0x16
+       MODRM 0xc0 extrd_opd1 extrd_opd2
+       .byte \imm8
+       .endm
+
        .macro AESKEYGENASSIST rcon xmm1 xmm2
        XMM_NUM aeskeygen_opd1 \xmm1
        XMM_NUM aeskeygen_opd2 \xmm2
index 0ef202e..82c34ee 100644 (file)
@@ -50,9 +50,6 @@ asmlinkage long sys32_fallocate(int, int, unsigned,
 asmlinkage long sys32_sigreturn(void);
 asmlinkage long sys32_rt_sigreturn(void);
 
-asmlinkage long sys32_fanotify_mark(int, unsigned int, u32, u32, int,
-                                   const char __user *);
-
 #endif /* CONFIG_COMPAT */
 
 #endif /* _ASM_X86_SYS_IA32_H */
index 5f87b35..2917a64 100644 (file)
@@ -37,8 +37,8 @@ asmlinkage long sys_get_thread_area(struct user_desc __user *);
 unsigned long sys_sigreturn(void);
 
 /* kernel/vm86_32.c */
-int sys_vm86old(struct vm86_struct __user *);
-int sys_vm86(unsigned long, unsigned long);
+asmlinkage long sys_vm86old(struct vm86_struct __user *);
+asmlinkage long sys_vm86(unsigned long, unsigned long);
 
 #else /* CONFIG_X86_32 */
 
index b3a4866..2af848d 100644 (file)
 #define MSR_CORE_C6_RESIDENCY          0x000003fd
 #define MSR_CORE_C7_RESIDENCY          0x000003fe
 #define MSR_PKG_C2_RESIDENCY           0x0000060d
+#define MSR_PKG_C8_RESIDENCY           0x00000630
+#define MSR_PKG_C9_RESIDENCY           0x00000631
+#define MSR_PKG_C10_RESIDENCY          0x00000632
 
 /* Run Time Average Power Limiting (RAPL) Interface */
 
index dab95a8..55b6761 100644 (file)
@@ -34,7 +34,7 @@
 extern pgd_t early_level4_pgt[PTRS_PER_PGD];
 extern pmd_t early_dynamic_pgts[EARLY_DYNAMIC_PAGE_TABLES][PTRS_PER_PMD];
 static unsigned int __initdata next_early_pgt = 2;
-pmdval_t __initdata early_pmd_flags = __PAGE_KERNEL_LARGE & ~(_PAGE_GLOBAL | _PAGE_NX);
+pmdval_t early_pmd_flags = __PAGE_KERNEL_LARGE & ~(_PAGE_GLOBAL | _PAGE_NX);
 
 /* Wipe all early page tables except for the kernel symbol map */
 static void __init reset_early_page_tables(void)
index 08f7e80..321d65e 100644 (file)
@@ -115,8 +115,10 @@ startup_64:
        movq    %rdi, %rax
        shrq    $PUD_SHIFT, %rax
        andl    $(PTRS_PER_PUD-1), %eax
-       movq    %rdx, (4096+0)(%rbx,%rax,8)
-       movq    %rdx, (4096+8)(%rbx,%rax,8)
+       movq    %rdx, 4096(%rbx,%rax,8)
+       incl    %eax
+       andl    $(PTRS_PER_PUD-1), %eax
+       movq    %rdx, 4096(%rbx,%rax,8)
 
        addq    $8192, %rbx
        movq    %rdi, %rax
index 245a71d..cb33909 100644 (file)
 /*
  * Were we in an interrupt that interrupted kernel mode?
  *
- * For now, with eagerfpu we will return interrupted kernel FPU
- * state as not-idle. TBD: Ideally we can change the return value
- * to something like __thread_has_fpu(current). But we need to
- * be careful of doing __thread_clear_has_fpu() before saving
- * the FPU etc for supporting nested uses etc. For now, take
- * the simple route!
- *
  * On others, we can do a kernel_fpu_begin/end() pair *ONLY* if that
  * pair does nothing at all: the thread must not have fpu (so
  * that we don't try to save the FPU state), and TS must
  * be set (so that the clts/stts pair does nothing that is
  * visible in the interrupted kernel thread).
+ *
+ * Except for the eagerfpu case when we return 1 unless we've already
+ * been eager and saved the state in kernel_fpu_begin().
  */
 static inline bool interrupted_kernel_fpu_idle(void)
 {
        if (use_eager_fpu())
-               return 0;
+               return __thread_has_fpu(current);
 
        return !__thread_has_fpu(current) &&
                (read_cr0() & X86_CR0_TS);
@@ -78,8 +74,8 @@ void __kernel_fpu_begin(void)
        struct task_struct *me = current;
 
        if (__thread_has_fpu(me)) {
-               __save_init_fpu(me);
                __thread_clear_has_fpu(me);
+               __save_init_fpu(me);
                /* We do 'stts()' in __kernel_fpu_end() */
        } else if (!use_eager_fpu()) {
                this_cpu_write(fpu_owner_task, NULL);
index d893e8e..2e9e128 100644 (file)
@@ -487,6 +487,7 @@ static inline void show_saved_mc(void)
 #endif
 
 #if defined(CONFIG_MICROCODE_INTEL_EARLY) && defined(CONFIG_HOTPLUG_CPU)
+static DEFINE_MUTEX(x86_cpu_microcode_mutex);
 /*
  * Save this mc into mc_saved_data. So it will be loaded early when a CPU is
  * hot added or resumes.
@@ -507,7 +508,7 @@ int save_mc_for_early(u8 *mc)
         * Hold hotplug lock so mc_saved_data is not accessed by a CPU in
         * hotplug.
         */
-       cpu_hotplug_driver_lock();
+       mutex_lock(&x86_cpu_microcode_mutex);
 
        mc_saved_count_init = mc_saved_data.mc_saved_count;
        mc_saved_count = mc_saved_data.mc_saved_count;
@@ -544,7 +545,7 @@ int save_mc_for_early(u8 *mc)
        }
 
 out:
-       cpu_hotplug_driver_unlock();
+       mutex_unlock(&x86_cpu_microcode_mutex);
 
        return ret;
 }
index 607af0d..4e7a37f 100644 (file)
@@ -312,6 +312,8 @@ void arch_cpu_idle(void)
 {
        if (cpuidle_idle_call())
                x86_idle();
+       else
+               local_irq_enable();
 }
 
 /*
@@ -368,9 +370,6 @@ void amd_e400_remove_cpu(int cpu)
  */
 static void amd_e400_idle(void)
 {
-       if (need_resched())
-               return;
-
        if (!amd_e400_c1e_detected) {
                u32 lo, hi;
 
index 1cf5766..e8edcf5 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/capability.h>
 #include <linux/errno.h>
 #include <linux/interrupt.h>
+#include <linux/syscalls.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
@@ -48,7 +49,6 @@
 #include <asm/io.h>
 #include <asm/tlbflush.h>
 #include <asm/irq.h>
-#include <asm/syscalls.h>
 
 /*
  * Known problems:
@@ -202,36 +202,32 @@ out:
 static int do_vm86_irq_handling(int subfunction, int irqnumber);
 static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk);
 
-int sys_vm86old(struct vm86_struct __user *v86)
+SYSCALL_DEFINE1(vm86old, struct vm86_struct __user *, v86)
 {
        struct kernel_vm86_struct info; /* declare this _on top_,
                                         * this avoids wasting of stack space.
                                         * This remains on the stack until we
                                         * return to 32 bit user space.
                                         */
-       struct task_struct *tsk;
-       int tmp, ret = -EPERM;
+       struct task_struct *tsk = current;
+       int tmp;
 
-       tsk = current;
        if (tsk->thread.saved_sp0)
-               goto out;
+               return -EPERM;
        tmp = copy_vm86_regs_from_user(&info.regs, &v86->regs,
                                       offsetof(struct kernel_vm86_struct, vm86plus) -
                                       sizeof(info.regs));
-       ret = -EFAULT;
        if (tmp)
-               goto out;
+               return -EFAULT;
        memset(&info.vm86plus, 0, (int)&info.regs32 - (int)&info.vm86plus);
        info.regs32 = current_pt_regs();
        tsk->thread.vm86_info = v86;
        do_sys_vm86(&info, tsk);
-       ret = 0;        /* we never return here */
-out:
-       return ret;
+       return 0;       /* we never return here */
 }
 
 
-int sys_vm86(unsigned long cmd, unsigned long arg)
+SYSCALL_DEFINE2(vm86, unsigned long, cmd, unsigned long, arg)
 {
        struct kernel_vm86_struct info; /* declare this _on top_,
                                         * this avoids wasting of stack space.
@@ -239,7 +235,7 @@ int sys_vm86(unsigned long cmd, unsigned long arg)
                                         * return to 32 bit user space.
                                         */
        struct task_struct *tsk;
-       int tmp, ret;
+       int tmp;
        struct vm86plus_struct __user *v86;
 
        tsk = current;
@@ -248,8 +244,7 @@ int sys_vm86(unsigned long cmd, unsigned long arg)
        case VM86_FREE_IRQ:
        case VM86_GET_IRQ_BITS:
        case VM86_GET_AND_RESET_IRQ:
-               ret = do_vm86_irq_handling(cmd, (int)arg);
-               goto out;
+               return do_vm86_irq_handling(cmd, (int)arg);
        case VM86_PLUS_INSTALL_CHECK:
                /*
                 * NOTE: on old vm86 stuff this will return the error
@@ -257,28 +252,23 @@ int sys_vm86(unsigned long cmd, unsigned long arg)
                 *  interpreted as (invalid) address to vm86_struct.
                 *  So the installation check works.
                 */
-               ret = 0;
-               goto out;
+               return 0;
        }
 
        /* we come here only for functions VM86_ENTER, VM86_ENTER_NO_BYPASS */
-       ret = -EPERM;
        if (tsk->thread.saved_sp0)
-               goto out;
+               return -EPERM;
        v86 = (struct vm86plus_struct __user *)arg;
        tmp = copy_vm86_regs_from_user(&info.regs, &v86->regs,
                                       offsetof(struct kernel_vm86_struct, regs32) -
                                       sizeof(info.regs));
-       ret = -EFAULT;
        if (tmp)
-               goto out;
+               return -EFAULT;
        info.regs32 = current_pt_regs();
        info.vm86plus.is_vm86pus = 1;
        tsk->thread.vm86_info = (struct vm86_struct __user *)v86;
        do_sys_vm86(&info, tsk);
-       ret = 0;        /* we never return here */
-out:
-       return ret;
+       return 0;       /* we never return here */
 }
 
 
index 8e517bb..5953dce 100644 (file)
@@ -60,6 +60,7 @@
 #define OpGS              25ull  /* GS */
 #define OpMem8            26ull  /* 8-bit zero extended memory operand */
 #define OpImm64           27ull  /* Sign extended 16/32/64-bit immediate */
+#define OpXLat            28ull  /* memory at BX/EBX/RBX + zero-extended AL */
 
 #define OpBits             5  /* Width of operand field */
 #define OpMask             ((1ull << OpBits) - 1)
 #define SrcImmUByte (OpImmUByte << SrcShift)
 #define SrcImmU     (OpImmU << SrcShift)
 #define SrcSI       (OpSI << SrcShift)
+#define SrcXLat     (OpXLat << SrcShift)
 #define SrcImmFAddr (OpImmFAddr << SrcShift)
 #define SrcMemFAddr (OpMemFAddr << SrcShift)
 #define SrcAcc      (OpAcc << SrcShift)
@@ -533,6 +535,9 @@ FOP_SETCC(setle)
 FOP_SETCC(setnle)
 FOP_END;
 
+FOP_START(salc) "pushf; sbb %al, %al; popf \n\t" FOP_RET
+FOP_END;
+
 #define __emulate_1op_rax_rdx(ctxt, _op, _suffix, _ex)                 \
        do {                                                            \
                unsigned long _tmp;                                     \
@@ -1235,9 +1240,12 @@ static int decode_modrm(struct x86_emulate_ctxt *ctxt,
        ctxt->modrm_seg = VCPU_SREG_DS;
 
        if (ctxt->modrm_mod == 3) {
+               int highbyte_regs = ctxt->rex_prefix == 0;
+
                op->type = OP_REG;
                op->bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
-               op->addr.reg = decode_register(ctxt, ctxt->modrm_rm, ctxt->d & ByteOp);
+               op->addr.reg = decode_register(ctxt, ctxt->modrm_rm,
+                                              highbyte_regs && (ctxt->d & ByteOp));
                if (ctxt->d & Sse) {
                        op->type = OP_XMM;
                        op->bytes = 16;
@@ -2996,6 +3004,28 @@ static int em_das(struct x86_emulate_ctxt *ctxt)
        return X86EMUL_CONTINUE;
 }
 
+static int em_aam(struct x86_emulate_ctxt *ctxt)
+{
+       u8 al, ah;
+
+       if (ctxt->src.val == 0)
+               return emulate_de(ctxt);
+
+       al = ctxt->dst.val & 0xff;
+       ah = al / ctxt->src.val;
+       al %= ctxt->src.val;
+
+       ctxt->dst.val = (ctxt->dst.val & 0xffff0000) | al | (ah << 8);
+
+       /* Set PF, ZF, SF */
+       ctxt->src.type = OP_IMM;
+       ctxt->src.val = 0;
+       ctxt->src.bytes = 1;
+       fastop(ctxt, em_or);
+
+       return X86EMUL_CONTINUE;
+}
+
 static int em_aad(struct x86_emulate_ctxt *ctxt)
 {
        u8 al = ctxt->dst.val & 0xff;
@@ -3936,7 +3966,10 @@ static const struct opcode opcode_table[256] = {
        /* 0xD0 - 0xD7 */
        G(Src2One | ByteOp, group2), G(Src2One, group2),
        G(Src2CL | ByteOp, group2), G(Src2CL, group2),
-       N, I(DstAcc | SrcImmByte | No64, em_aad), N, N,
+       I(DstAcc | SrcImmUByte | No64, em_aam),
+       I(DstAcc | SrcImmUByte | No64, em_aad),
+       F(DstAcc | ByteOp | No64, em_salc),
+       I(DstAcc | SrcXLat | ByteOp, em_mov),
        /* 0xD8 - 0xDF */
        N, E(0, &escape_d9), N, E(0, &escape_db), N, E(0, &escape_dd), N, N,
        /* 0xE0 - 0xE7 */
@@ -3967,7 +4000,8 @@ static const struct opcode twobyte_table[256] = {
        DI(ImplicitOps | Priv, invd), DI(ImplicitOps | Priv, wbinvd), N, N,
        N, D(ImplicitOps | ModRM), N, N,
        /* 0x10 - 0x1F */
-       N, N, N, N, N, N, N, N, D(ImplicitOps | ModRM), N, N, N, N, N, N, N,
+       N, N, N, N, N, N, N, N,
+       D(ImplicitOps | ModRM), N, N, N, N, N, N, D(ImplicitOps | ModRM),
        /* 0x20 - 0x2F */
        DIP(ModRM | DstMem | Priv | Op3264, cr_read, check_cr_read),
        DIP(ModRM | DstMem | Priv | Op3264, dr_read, check_dr_read),
@@ -4198,6 +4232,16 @@ static int decode_operand(struct x86_emulate_ctxt *ctxt, struct operand *op,
                op->val = 0;
                op->count = 1;
                break;
+       case OpXLat:
+               op->type = OP_MEM;
+               op->bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
+               op->addr.mem.ea =
+                       register_address(ctxt,
+                               reg_read(ctxt, VCPU_REGS_RBX) +
+                               (reg_read(ctxt, VCPU_REGS_RAX) & 0xff));
+               op->addr.mem.seg = seg_override(ctxt);
+               op->val = 0;
+               break;
        case OpImmFAddr:
                op->type = OP_IMM;
                op->addr.mem.ea = ctxt->_eip;
@@ -4796,6 +4840,7 @@ twobyte_insn:
        case 0x08:              /* invd */
        case 0x0d:              /* GrpP (prefetch) */
        case 0x18:              /* Grp16 (prefetch/nop) */
+       case 0x1f:              /* nop */
                break;
        case 0x20: /* mov cr, reg */
                ctxt->dst.val = ops->get_cr(ctxt, ctxt->modrm_reg);
index e1adbb4..0eee2c8 100644 (file)
@@ -1861,11 +1861,14 @@ void kvm_apic_accept_events(struct kvm_vcpu *vcpu)
 {
        struct kvm_lapic *apic = vcpu->arch.apic;
        unsigned int sipi_vector;
+       unsigned long pe;
 
-       if (!kvm_vcpu_has_lapic(vcpu))
+       if (!kvm_vcpu_has_lapic(vcpu) || !apic->pending_events)
                return;
 
-       if (test_and_clear_bit(KVM_APIC_INIT, &apic->pending_events)) {
+       pe = xchg(&apic->pending_events, 0);
+
+       if (test_bit(KVM_APIC_INIT, &pe)) {
                kvm_lapic_reset(vcpu);
                kvm_vcpu_reset(vcpu);
                if (kvm_vcpu_is_bsp(apic->vcpu))
@@ -1873,7 +1876,7 @@ void kvm_apic_accept_events(struct kvm_vcpu *vcpu)
                else
                        vcpu->arch.mp_state = KVM_MP_STATE_INIT_RECEIVED;
        }
-       if (test_and_clear_bit(KVM_APIC_SIPI, &apic->pending_events) &&
+       if (test_bit(KVM_APIC_SIPI, &pe) &&
            vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED) {
                /* evaluate pending_events before reading the vector */
                smp_rmb();
index 25a791e..260a919 100644 (file)
@@ -5434,6 +5434,12 @@ static int handle_invalid_guest_state(struct kvm_vcpu *vcpu)
                        return 0;
                }
 
+               if (vcpu->arch.halt_request) {
+                       vcpu->arch.halt_request = 0;
+                       ret = kvm_emulate_halt(vcpu);
+                       goto out;
+               }
+
                if (signal_pending(current))
                        goto out;
                if (need_resched())
index 05a8b1a..094b5d9 100644 (file)
@@ -555,6 +555,25 @@ void kvm_lmsw(struct kvm_vcpu *vcpu, unsigned long msw)
 }
 EXPORT_SYMBOL_GPL(kvm_lmsw);
 
+static void kvm_load_guest_xcr0(struct kvm_vcpu *vcpu)
+{
+       if (kvm_read_cr4_bits(vcpu, X86_CR4_OSXSAVE) &&
+                       !vcpu->guest_xcr0_loaded) {
+               /* kvm_set_xcr() also depends on this */
+               xsetbv(XCR_XFEATURE_ENABLED_MASK, vcpu->arch.xcr0);
+               vcpu->guest_xcr0_loaded = 1;
+       }
+}
+
+static void kvm_put_guest_xcr0(struct kvm_vcpu *vcpu)
+{
+       if (vcpu->guest_xcr0_loaded) {
+               if (vcpu->arch.xcr0 != host_xcr0)
+                       xsetbv(XCR_XFEATURE_ENABLED_MASK, host_xcr0);
+               vcpu->guest_xcr0_loaded = 0;
+       }
+}
+
 int __kvm_set_xcr(struct kvm_vcpu *vcpu, u32 index, u64 xcr)
 {
        u64 xcr0;
@@ -571,8 +590,8 @@ int __kvm_set_xcr(struct kvm_vcpu *vcpu, u32 index, u64 xcr)
                return 1;
        if (xcr0 & ~host_xcr0)
                return 1;
+       kvm_put_guest_xcr0(vcpu);
        vcpu->arch.xcr0 = xcr0;
-       vcpu->guest_xcr0_loaded = 0;
        return 0;
 }
 
@@ -5614,25 +5633,6 @@ static void inject_pending_event(struct kvm_vcpu *vcpu)
        }
 }
 
-static void kvm_load_guest_xcr0(struct kvm_vcpu *vcpu)
-{
-       if (kvm_read_cr4_bits(vcpu, X86_CR4_OSXSAVE) &&
-                       !vcpu->guest_xcr0_loaded) {
-               /* kvm_set_xcr() also depends on this */
-               xsetbv(XCR_XFEATURE_ENABLED_MASK, vcpu->arch.xcr0);
-               vcpu->guest_xcr0_loaded = 1;
-       }
-}
-
-static void kvm_put_guest_xcr0(struct kvm_vcpu *vcpu)
-{
-       if (vcpu->guest_xcr0_loaded) {
-               if (vcpu->arch.xcr0 != host_xcr0)
-                       xsetbv(XCR_XFEATURE_ENABLED_MASK, host_xcr0);
-               vcpu->guest_xcr0_loaded = 0;
-       }
-}
-
 static void process_nmi(struct kvm_vcpu *vcpu)
 {
        unsigned limit = 2;
index fdc5dca..eaac174 100644 (file)
@@ -359,7 +359,17 @@ unsigned long __init_refok init_memory_mapping(unsigned long start,
 }
 
 /*
- * would have hole in the middle or ends, and only ram parts will be mapped.
+ * We need to iterate through the E820 memory map and create direct mappings
+ * for only E820_RAM and E820_KERN_RESERVED regions. We cannot simply
+ * create direct mappings for all pfns from [0 to max_low_pfn) and
+ * [4GB to max_pfn) because of possible memory holes in high addresses
+ * that cannot be marked as UC by fixed/variable range MTRRs.
+ * Depending on the alignment of E820 ranges, this may possibly result
+ * in using smaller size (i.e. 4K instead of 2M or 1G) page tables.
+ *
+ * init_mem_mapping() calls init_range_memory_mapping() with big range.
+ * That range would have hole in the middle or ends, and only ram parts
+ * will be mapped in init_range_memory_mapping().
  */
 static unsigned long __init init_range_memory_mapping(
                                           unsigned long r_start,
@@ -419,6 +429,13 @@ void __init init_mem_mapping(void)
        max_pfn_mapped = 0; /* will get exact value next */
        min_pfn_mapped = real_end >> PAGE_SHIFT;
        last_start = start = real_end;
+
+       /*
+        * We start from the top (end of memory) and go to the bottom.
+        * The memblock_find_in_range() gets us a block of RAM from the
+        * end of RAM in [min_pfn_mapped, max_pfn_mapped) used as new pages
+        * for page table.
+        */
        while (last_start > ISA_END_ADDRESS) {
                if (last_start > step_size) {
                        start = round_down(last_start - 1, step_size);
index 305c68b..981c2db 100644 (file)
@@ -628,7 +628,9 @@ int pcibios_add_device(struct pci_dev *dev)
 
        pa_data = boot_params.hdr.setup_data;
        while (pa_data) {
-               data = phys_to_virt(pa_data);
+               data = ioremap(pa_data, sizeof(*rom));
+               if (!data)
+                       return -ENOMEM;
 
                if (data->type == SETUP_PCI) {
                        rom = (struct pci_setup_rom *)data;
@@ -645,6 +647,7 @@ int pcibios_add_device(struct pci_dev *dev)
                        }
                }
                pa_data = data->next;
+               iounmap(data);
        }
        return 0;
 }
index 0e0fabf..6eb18c4 100644 (file)
@@ -141,11 +141,6 @@ static int pci_device_update_fixed(struct pci_bus *bus, unsigned int devfn,
  */
 static bool type1_access_ok(unsigned int bus, unsigned int devfn, int reg)
 {
-       if (bus == 0 && (devfn == PCI_DEVFN(2, 0)
-                               || devfn == PCI_DEVFN(0, 0)
-                               || devfn == PCI_DEVFN(3, 0)))
-               return 1;
-
        /* This is a workaround for A0 LNC bug where PCI status register does
         * not have new CAP bit set. can not be written by SW either.
         *
@@ -155,7 +150,10 @@ static bool type1_access_ok(unsigned int bus, unsigned int devfn, int reg)
         */
        if (reg >= 0x100 || reg == PCI_STATUS || reg == PCI_HEADER_TYPE)
                return 0;
-
+       if (bus == 0 && (devfn == PCI_DEVFN(2, 0)
+                               || devfn == PCI_DEVFN(0, 0)
+                               || devfn == PCI_DEVFN(3, 0)))
+               return 1;
        return 0; /* langwell on others */
 }
 
index 4a9be6d..48e8461 100644 (file)
@@ -295,11 +295,10 @@ static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
                        int pos;
                        u32 table_offset, bir;
 
-                       pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
-
+                       pos = dev->msix_cap;
                        pci_read_config_dword(dev, pos + PCI_MSIX_TABLE,
                                              &table_offset);
-                       bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK);
+                       bir = (u8)(table_offset & PCI_MSIX_TABLE_BIR);
 
                        map_irq.table_base = pci_resource_start(dev, bir);
                        map_irq.entry_nr = msidesc->msi_attrib.entry_nr;
index 55856b2..82089d8 100644 (file)
@@ -206,7 +206,7 @@ static efi_status_t virt_efi_get_next_variable(unsigned long *name_size,
        }
 
        if (boot_used_size && !finished) {
-               unsigned long size;
+               unsigned long size = 0;
                u32 attr;
                efi_status_t s;
                void *tmp;
index d0d59bf..aabfb83 100644 (file)
 336    i386    perf_event_open         sys_perf_event_open
 337    i386    recvmmsg                sys_recvmmsg                    compat_sys_recvmmsg
 338    i386    fanotify_init           sys_fanotify_init
-339    i386    fanotify_mark           sys_fanotify_mark               sys32_fanotify_mark
+339    i386    fanotify_mark           sys_fanotify_mark               compat_sys_fanotify_mark
 340    i386    prlimit64               sys_prlimit64
 341    i386    name_to_handle_at       sys_name_to_handle_at
 342    i386    open_by_handle_at       sys_open_by_handle_at           compat_sys_open_by_handle_at
index 53d4f68..a492be2 100644 (file)
 
 EXPORT_SYMBOL_GPL(hypercall_page);
 
+/*
+ * Pointer to the xen_vcpu_info structure or
+ * &HYPERVISOR_shared_info->vcpu_info[cpu]. See xen_hvm_init_shared_info
+ * and xen_vcpu_setup for details. By default it points to share_info->vcpu_info
+ * but if the hypervisor supports VCPUOP_register_vcpu_info then it can point
+ * to xen_vcpu_info. The pointer is used in __xen_evtchn_do_upcall to
+ * acknowledge pending events.
+ * Also more subtly it is used by the patched version of irq enable/disable
+ * e.g. xen_irq_enable_direct and xen_iret in PV mode.
+ *
+ * The desire to be able to do those mask/unmask operations as a single
+ * instruction by using the per-cpu offset held in %gs is the real reason
+ * vcpu info is in a per-cpu pointer and the original reason for this
+ * hypercall.
+ *
+ */
 DEFINE_PER_CPU(struct vcpu_info *, xen_vcpu);
+
+/*
+ * Per CPU pages used if hypervisor supports VCPUOP_register_vcpu_info
+ * hypercall. This can be used both in PV and PVHVM mode. The structure
+ * overrides the default per_cpu(xen_vcpu, cpu) value.
+ */
 DEFINE_PER_CPU(struct vcpu_info, xen_vcpu_info);
 
 enum xen_domain_type xen_domain_type = XEN_NATIVE;
@@ -157,6 +179,21 @@ static void xen_vcpu_setup(int cpu)
 
        BUG_ON(HYPERVISOR_shared_info == &xen_dummy_shared_info);
 
+       /*
+        * This path is called twice on PVHVM - first during bootup via
+        * smp_init -> xen_hvm_cpu_notify, and then if the VCPU is being
+        * hotplugged: cpu_up -> xen_hvm_cpu_notify.
+        * As we can only do the VCPUOP_register_vcpu_info once lets
+        * not over-write its result.
+        *
+        * For PV it is called during restore (xen_vcpu_restore) and bootup
+        * (xen_setup_vcpu_info_placement). The hotplug mechanism does not
+        * use this function.
+        */
+       if (xen_hvm_domain()) {
+               if (per_cpu(xen_vcpu, cpu) == &per_cpu(xen_vcpu_info, cpu))
+                       return;
+       }
        if (cpu < MAX_VIRT_CPUS)
                per_cpu(xen_vcpu,cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu];
 
@@ -172,7 +209,12 @@ static void xen_vcpu_setup(int cpu)
 
        /* Check to see if the hypervisor will put the vcpu_info
           structure where we want it, which allows direct access via
-          a percpu-variable. */
+          a percpu-variable.
+          N.B. This hypercall can _only_ be called once per CPU. Subsequent
+          calls will error out with -EINVAL. This is due to the fact that
+          hypervisor has no unregister variant and this hypercall does not
+          allow to over-write info.mfn and info.offset.
+        */
        err = HYPERVISOR_vcpu_op(VCPUOP_register_vcpu_info, cpu, &info);
 
        if (err) {
@@ -387,6 +429,9 @@ static void __init xen_init_cpuid_mask(void)
                cpuid_leaf1_edx_mask &=
                        ~((1 << X86_FEATURE_APIC) |  /* disable local APIC */
                          (1 << X86_FEATURE_ACPI));  /* disable ACPI */
+
+       cpuid_leaf1_ecx_mask &= ~(1 << (X86_FEATURE_X2APIC % 32));
+
        ax = 1;
        cx = 0;
        xen_cpuid(&ax, &bx, &cx, &dx);
@@ -1603,6 +1648,9 @@ void __ref xen_hvm_init_shared_info(void)
         * online but xen_hvm_init_shared_info is run at resume time too and
         * in that case multiple vcpus might be online. */
        for_each_online_cpu(cpu) {
+               /* Leave it to be NULL. */
+               if (cpu >= MAX_VIRT_CPUS)
+                       continue;
                per_cpu(xen_vcpu, cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu];
        }
 }
index 8ff3799..d99cae8 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/slab.h>
 #include <linux/smp.h>
 #include <linux/irq_work.h>
+#include <linux/tick.h>
 
 #include <asm/paravirt.h>
 #include <asm/desc.h>
@@ -447,6 +448,13 @@ static void __cpuinit xen_play_dead(void) /* used only with HOTPLUG_CPU */
        play_dead_common();
        HYPERVISOR_vcpu_op(VCPUOP_down, smp_processor_id(), NULL);
        cpu_bringup();
+       /*
+        * commit 4b0c0f294 (tick: Cleanup NOHZ per cpu data on cpu down)
+        * clears certain data that the cpu_idle loop (which called us
+        * and that we return from) expects. The only way to get that
+        * data back is to call:
+        */
+       tick_nohz_idle_enter();
 }
 
 #else /* !CONFIG_HOTPLUG_CPU */
@@ -576,24 +584,22 @@ void xen_send_IPI_mask_allbutself(const struct cpumask *mask,
 {
        unsigned cpu;
        unsigned int this_cpu = smp_processor_id();
+       int xen_vector = xen_map_vector(vector);
 
-       if (!(num_online_cpus() > 1))
+       if (!(num_online_cpus() > 1) || (xen_vector < 0))
                return;
 
        for_each_cpu_and(cpu, mask, cpu_online_mask) {
                if (this_cpu == cpu)
                        continue;
 
-               xen_smp_send_call_function_single_ipi(cpu);
+               xen_send_IPI_one(cpu, xen_vector);
        }
 }
 
 void xen_send_IPI_allbutself(int vector)
 {
-       int xen_vector = xen_map_vector(vector);
-
-       if (xen_vector >= 0)
-               xen_send_IPI_mask_allbutself(cpu_online_mask, xen_vector);
+       xen_send_IPI_mask_allbutself(cpu_online_mask, vector);
 }
 
 static irqreturn_t xen_call_function_interrupt(int irq, void *dev_id)
index 8981a76..c7c2d89 100644 (file)
@@ -5,7 +5,6 @@ extern void xen_send_IPI_mask(const struct cpumask *mask,
 extern void xen_send_IPI_mask_allbutself(const struct cpumask *mask,
                                int vector);
 extern void xen_send_IPI_allbutself(int vector);
-extern void physflat_send_IPI_allbutself(int vector);
 extern void xen_send_IPI_all(int vector);
 extern void xen_send_IPI_self(int vector);
 
index 8b54603..3002ec1 100644 (file)
@@ -364,7 +364,7 @@ void __cpuinit xen_init_lock_cpu(int cpu)
        int irq;
        const char *name;
 
-       WARN(per_cpu(lock_kicker_irq, cpu) > 0, "spinlock on CPU%d exists on IRQ%d!\n",
+       WARN(per_cpu(lock_kicker_irq, cpu) >= 0, "spinlock on CPU%d exists on IRQ%d!\n",
             cpu, per_cpu(lock_kicker_irq, cpu));
 
        /*
index 33c33bc..d5745b5 100644 (file)
@@ -3164,7 +3164,7 @@ void blk_post_runtime_resume(struct request_queue *q, int err)
                q->rpm_status = RPM_ACTIVE;
                __blk_run_queue(q);
                pm_runtime_mark_last_busy(q->dev);
-               pm_runtime_autosuspend(q->dev);
+               pm_request_autosuspend(q->dev);
        } else {
                q->rpm_status = RPM_SUSPENDED;
        }
index 622d8a4..bf8148e 100644 (file)
@@ -823,6 +823,7 @@ config CRYPTO_BLOWFISH_X86_64
 config CRYPTO_BLOWFISH_AVX2_X86_64
        tristate "Blowfish cipher algorithm (x86_64/AVX2)"
        depends on X86 && 64BIT
+       depends on BROKEN
        select CRYPTO_ALGAPI
        select CRYPTO_CRYPTD
        select CRYPTO_ABLK_HELPER_X86
@@ -1299,6 +1300,7 @@ config CRYPTO_TWOFISH_AVX_X86_64
 config CRYPTO_TWOFISH_AVX2_X86_64
        tristate "Twofish cipher algorithm (x86_64/AVX2)"
        depends on X86 && 64BIT
+       depends on BROKEN
        select CRYPTO_ALGAPI
        select CRYPTO_CRYPTD
        select CRYPTO_ABLK_HELPER_X86
index ecb743b..536562c 100644 (file)
@@ -24,7 +24,7 @@ acpi-y                                += nvs.o
 # Power management related files
 acpi-y                         += wakeup.o
 acpi-y                         += sleep.o
-acpi-$(CONFIG_PM)              += device_pm.o
+acpi-y                         += device_pm.o
 acpi-$(CONFIG_ACPI_SLEEP)      += proc.o
 
 
@@ -38,7 +38,6 @@ acpi-y                                += processor_core.o
 acpi-y                         += ec.o
 acpi-$(CONFIG_ACPI_DOCK)       += dock.o
 acpi-y                         += pci_root.o pci_link.o pci_irq.o
-acpi-y                         += csrt.o
 acpi-$(CONFIG_X86_INTEL_LPSS)  += acpi_lpss.o
 acpi-y                         += acpi_platform.o
 acpi-y                         += power.o
index 00d2efd..4f4e741 100644 (file)
@@ -28,6 +28,8 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/types.h>
+#include <linux/dmi.h>
+#include <linux/delay.h>
 #ifdef CONFIG_ACPI_PROCFS_POWER
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
@@ -74,6 +76,8 @@ static int acpi_ac_resume(struct device *dev);
 #endif
 static SIMPLE_DEV_PM_OPS(acpi_ac_pm, NULL, acpi_ac_resume);
 
+static int ac_sleep_before_get_state_ms;
+
 static struct acpi_driver acpi_ac_driver = {
        .name = "ac",
        .class = ACPI_AC_CLASS,
@@ -252,6 +256,16 @@ static void acpi_ac_notify(struct acpi_device *device, u32 event)
        case ACPI_AC_NOTIFY_STATUS:
        case ACPI_NOTIFY_BUS_CHECK:
        case ACPI_NOTIFY_DEVICE_CHECK:
+               /*
+                * A buggy BIOS may notify AC first and then sleep for
+                * a specific time before doing actual operations in the
+                * EC event handler (_Qxx). This will cause the AC state
+                * reported by the ACPI event to be incorrect, so wait for a
+                * specific time for the EC event handler to make progress.
+                */
+               if (ac_sleep_before_get_state_ms > 0)
+                       msleep(ac_sleep_before_get_state_ms);
+
                acpi_ac_get_state(ac);
                acpi_bus_generate_proc_event(device, event, (u32) ac->state);
                acpi_bus_generate_netlink_event(device->pnp.device_class,
@@ -264,6 +278,24 @@ static void acpi_ac_notify(struct acpi_device *device, u32 event)
        return;
 }
 
+static int thinkpad_e530_quirk(const struct dmi_system_id *d)
+{
+       ac_sleep_before_get_state_ms = 1000;
+       return 0;
+}
+
+static struct dmi_system_id ac_dmi_table[] = {
+       {
+       .callback = thinkpad_e530_quirk,
+       .ident = "thinkpad e530",
+       .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "32597CG"),
+               },
+       },
+       {},
+};
+
 static int acpi_ac_add(struct acpi_device *device)
 {
        int result = 0;
@@ -312,6 +344,7 @@ static int acpi_ac_add(struct acpi_device *device)
                kfree(ac);
        }
 
+       dmi_check_system(ac_dmi_table);
        return result;
 }
 
index b1c9542..652fd5c 100644 (file)
@@ -35,11 +35,16 @@ ACPI_MODULE_NAME("acpi_lpss");
 
 struct lpss_device_desc {
        bool clk_required;
-       const char *clk_parent;
+       const char *clkdev_name;
        bool ltr_required;
        unsigned int prv_offset;
 };
 
+static struct lpss_device_desc lpss_dma_desc = {
+       .clk_required = true,
+       .clkdev_name = "hclk",
+};
+
 struct lpss_private_data {
        void __iomem *mmio_base;
        resource_size_t mmio_size;
@@ -49,7 +54,6 @@ struct lpss_private_data {
 
 static struct lpss_device_desc lpt_dev_desc = {
        .clk_required = true,
-       .clk_parent = "lpss_clk",
        .prv_offset = 0x800,
        .ltr_required = true,
 };
@@ -60,6 +64,9 @@ static struct lpss_device_desc lpt_sdio_dev_desc = {
 };
 
 static const struct acpi_device_id acpi_lpss_device_ids[] = {
+       /* Generic LPSS devices */
+       { "INTL9C60", (unsigned long)&lpss_dma_desc },
+
        /* Lynxpoint LPSS devices */
        { "INT33C0", (unsigned long)&lpt_dev_desc },
        { "INT33C1", (unsigned long)&lpt_dev_desc },
@@ -91,16 +98,27 @@ static int register_device_clock(struct acpi_device *adev,
                                 struct lpss_private_data *pdata)
 {
        const struct lpss_device_desc *dev_desc = pdata->dev_desc;
+       struct lpss_clk_data *clk_data;
 
        if (!lpss_clk_dev)
                lpt_register_clock_device();
 
-       if (!dev_desc->clk_parent || !pdata->mmio_base
+       clk_data = platform_get_drvdata(lpss_clk_dev);
+       if (!clk_data)
+               return -ENODEV;
+
+       if (dev_desc->clkdev_name) {
+               clk_register_clkdev(clk_data->clk, dev_desc->clkdev_name,
+                                   dev_name(&adev->dev));
+               return 0;
+       }
+
+       if (!pdata->mmio_base
            || pdata->mmio_size < dev_desc->prv_offset + LPSS_CLK_SIZE)
                return -ENODATA;
 
        pdata->clk = clk_register_gate(NULL, dev_name(&adev->dev),
-                                      dev_desc->clk_parent, 0,
+                                      clk_data->name, 0,
                                       pdata->mmio_base + dev_desc->prv_offset,
                                       0, 0, NULL);
        if (IS_ERR(pdata->clk))
index fefc2ca..33dc6a0 100644 (file)
@@ -250,10 +250,6 @@ static const char *cper_pcie_port_type_strs[] = {
 static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie,
                            const struct acpi_hest_generic_data *gdata)
 {
-#ifdef CONFIG_ACPI_APEI_PCIEAER
-       struct pci_dev *dev;
-#endif
-
        if (pcie->validation_bits & CPER_PCIE_VALID_PORT_TYPE)
                printk("%s""port_type: %d, %s\n", pfx, pcie->port_type,
                       pcie->port_type < ARRAY_SIZE(cper_pcie_port_type_strs) ?
@@ -285,20 +281,6 @@ static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie,
                printk(
        "%s""bridge: secondary_status: 0x%04x, control: 0x%04x\n",
        pfx, pcie->bridge.secondary_status, pcie->bridge.control);
-#ifdef CONFIG_ACPI_APEI_PCIEAER
-       dev = pci_get_domain_bus_and_slot(pcie->device_id.segment,
-                       pcie->device_id.bus, pcie->device_id.function);
-       if (!dev) {
-               pr_err("PCI AER Cannot get PCI device %04x:%02x:%02x.%d\n",
-                       pcie->device_id.segment, pcie->device_id.bus,
-                       pcie->device_id.slot, pcie->device_id.function);
-               return;
-       }
-       if (pcie->validation_bits & CPER_PCIE_VALID_AER_INFO)
-               cper_print_aer(pfx, dev, gdata->error_severity,
-                               (struct aer_capability_regs *) pcie->aer_info);
-       pci_dev_put(dev);
-#endif
 }
 
 static const char *apei_estatus_section_flag_strs[] = {
index d668a8a..fcd7d91 100644 (file)
@@ -454,7 +454,9 @@ static void ghes_do_proc(struct ghes *ghes,
                                aer_severity = cper_severity_to_aer(sev);
                                aer_recover_queue(pcie_err->device_id.segment,
                                                  pcie_err->device_id.bus,
-                                                 devfn, aer_severity);
+                                                 devfn, aer_severity,
+                                                 (struct aer_capability_regs *)
+                                                 pcie_err->aer_info);
                        }
 
                }
@@ -917,13 +919,14 @@ static int ghes_probe(struct platform_device *ghes_dev)
                break;
        case ACPI_HEST_NOTIFY_EXTERNAL:
                /* External interrupt vector is GSI */
-               if (acpi_gsi_to_irq(generic->notify.vector, &ghes->irq)) {
+               rc = acpi_gsi_to_irq(generic->notify.vector, &ghes->irq);
+               if (rc) {
                        pr_err(GHES_PFX "Failed to map GSI to IRQ for generic hardware error source: %d\n",
                               generic->header.source_id);
                        goto err_edac_unreg;
                }
-               if (request_irq(ghes->irq, ghes_irq_func,
-                               0, "GHES IRQ", ghes)) {
+               rc = request_irq(ghes->irq, ghes_irq_func, 0, "GHES IRQ", ghes);
+               if (rc) {
                        pr_err(GHES_PFX "Failed to register IRQ for generic hardware error source: %d\n",
                               generic->header.source_id);
                        goto err_edac_unreg;
diff --git a/drivers/acpi/csrt.c b/drivers/acpi/csrt.c
deleted file mode 100644 (file)
index 5c15a91..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Support for Core System Resources Table (CSRT)
- *
- * Copyright (C) 2013, Intel Corporation
- * Authors: Mika Westerberg <mika.westerberg@linux.intel.com>
- *         Andy Shevchenko <andriy.shevchenko@linux.intel.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#define pr_fmt(fmt) "ACPI: CSRT: " fmt
-
-#include <linux/acpi.h>
-#include <linux/device.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/sizes.h>
-
-ACPI_MODULE_NAME("CSRT");
-
-static int __init acpi_csrt_parse_shared_info(struct platform_device *pdev,
-                                             const struct acpi_csrt_group *grp)
-{
-       const struct acpi_csrt_shared_info *si;
-       struct resource res[3];
-       size_t nres;
-       int ret;
-
-       memset(res, 0, sizeof(res));
-       nres = 0;
-
-       si = (const struct acpi_csrt_shared_info *)&grp[1];
-       /*
-        * The peripherals that are listed on CSRT typically support only
-        * 32-bit addresses so we only use the low part of MMIO base for
-        * now.
-        */
-       if (!si->mmio_base_high && si->mmio_base_low) {
-               /*
-                * There is no size of the memory resource in shared_info
-                * so we assume that it is 4k here.
-                */
-               res[nres].start = si->mmio_base_low;
-               res[nres].end = res[0].start + SZ_4K - 1;
-               res[nres++].flags = IORESOURCE_MEM;
-       }
-
-       if (si->gsi_interrupt) {
-               int irq = acpi_register_gsi(NULL, si->gsi_interrupt,
-                                           si->interrupt_mode,
-                                           si->interrupt_polarity);
-               res[nres].start = irq;
-               res[nres].end = irq;
-               res[nres++].flags = IORESOURCE_IRQ;
-       }
-
-       if (si->base_request_line || si->num_handshake_signals) {
-               /*
-                * We pass the driver a DMA resource describing the range
-                * of request lines the device supports.
-                */
-               res[nres].start = si->base_request_line;
-               res[nres].end = res[nres].start + si->num_handshake_signals - 1;
-               res[nres++].flags = IORESOURCE_DMA;
-       }
-
-       ret = platform_device_add_resources(pdev, res, nres);
-       if (ret) {
-               if (si->gsi_interrupt)
-                       acpi_unregister_gsi(si->gsi_interrupt);
-               return ret;
-       }
-
-       return 0;
-}
-
-static int __init
-acpi_csrt_parse_resource_group(const struct acpi_csrt_group *grp)
-{
-       struct platform_device *pdev;
-       char vendor[5], name[16];
-       int ret, i;
-
-       vendor[0] = grp->vendor_id;
-       vendor[1] = grp->vendor_id >> 8;
-       vendor[2] = grp->vendor_id >> 16;
-       vendor[3] = grp->vendor_id >> 24;
-       vendor[4] = '\0';
-
-       if (grp->shared_info_length != sizeof(struct acpi_csrt_shared_info))
-               return -ENODEV;
-
-       snprintf(name, sizeof(name), "%s%04X", vendor, grp->device_id);
-       pdev = platform_device_alloc(name, PLATFORM_DEVID_AUTO);
-       if (!pdev)
-               return -ENOMEM;
-
-       /* Add resources based on the shared info */
-       ret = acpi_csrt_parse_shared_info(pdev, grp);
-       if (ret)
-               goto fail;
-
-       ret = platform_device_add(pdev);
-       if (ret)
-               goto fail;
-
-       for (i = 0; i < pdev->num_resources; i++)
-               dev_dbg(&pdev->dev, "%pR\n", &pdev->resource[i]);
-
-       return 0;
-
-fail:
-       platform_device_put(pdev);
-       return ret;
-}
-
-/*
- * CSRT or Core System Resources Table is a proprietary ACPI table
- * introduced by Microsoft. This table can contain devices that are not in
- * the system DSDT table. In particular DMA controllers might be described
- * here.
- *
- * We present these devices as normal platform devices that don't have ACPI
- * IDs or handle. The platform device name will be something like
- * <VENDOR><DEVID>.<n>.auto for example: INTL9C06.0.auto.
- */
-void __init acpi_csrt_init(void)
-{
-       struct acpi_csrt_group *grp, *end;
-       struct acpi_table_csrt *csrt;
-       acpi_status status;
-       int ret;
-
-       status = acpi_get_table(ACPI_SIG_CSRT, 0,
-                               (struct acpi_table_header **)&csrt);
-       if (ACPI_FAILURE(status)) {
-               if (status != AE_NOT_FOUND)
-                       pr_warn("failed to get the CSRT table\n");
-               return;
-       }
-
-       pr_debug("parsing CSRT table for devices\n");
-
-       grp = (struct acpi_csrt_group *)(csrt + 1);
-       end = (struct acpi_csrt_group *)((void *)csrt + csrt->header.length);
-
-       while (grp < end) {
-               ret = acpi_csrt_parse_resource_group(grp);
-               if (ret) {
-                       pr_warn("error in parsing resource group: %d\n", ret);
-                       return;
-               }
-
-               grp = (struct acpi_csrt_group *)((void *)grp + grp->length);
-       }
-}
index 96de787..318fa32 100644 (file)
 #define _COMPONENT     ACPI_POWER_COMPONENT
 ACPI_MODULE_NAME("device_pm");
 
-static DEFINE_MUTEX(acpi_pm_notifier_lock);
-
-/**
- * acpi_add_pm_notifier - Register PM notifier for given ACPI device.
- * @adev: ACPI device to add the notifier for.
- * @context: Context information to pass to the notifier routine.
- *
- * NOTE: @adev need not be a run-wake or wakeup device to be a valid source of
- * PM wakeup events.  For example, wakeup events may be generated for bridges
- * if one of the devices below the bridge is signaling wakeup, even if the
- * bridge itself doesn't have a wakeup GPE associated with it.
- */
-acpi_status acpi_add_pm_notifier(struct acpi_device *adev,
-                                acpi_notify_handler handler, void *context)
-{
-       acpi_status status = AE_ALREADY_EXISTS;
-
-       mutex_lock(&acpi_pm_notifier_lock);
-
-       if (adev->wakeup.flags.notifier_present)
-               goto out;
-
-       status = acpi_install_notify_handler(adev->handle,
-                                            ACPI_SYSTEM_NOTIFY,
-                                            handler, context);
-       if (ACPI_FAILURE(status))
-               goto out;
-
-       adev->wakeup.flags.notifier_present = true;
-
- out:
-       mutex_unlock(&acpi_pm_notifier_lock);
-       return status;
-}
-
-/**
- * acpi_remove_pm_notifier - Unregister PM notifier from given ACPI device.
- * @adev: ACPI device to remove the notifier from.
- */
-acpi_status acpi_remove_pm_notifier(struct acpi_device *adev,
-                                   acpi_notify_handler handler)
-{
-       acpi_status status = AE_BAD_PARAMETER;
-
-       mutex_lock(&acpi_pm_notifier_lock);
-
-       if (!adev->wakeup.flags.notifier_present)
-               goto out;
-
-       status = acpi_remove_notify_handler(adev->handle,
-                                           ACPI_SYSTEM_NOTIFY,
-                                           handler);
-       if (ACPI_FAILURE(status))
-               goto out;
-
-       adev->wakeup.flags.notifier_present = false;
-
- out:
-       mutex_unlock(&acpi_pm_notifier_lock);
-       return status;
-}
-
 /**
  * acpi_power_state_string - String representation of ACPI device power state.
  * @state: ACPI device power state to return the string representation of.
@@ -340,11 +278,13 @@ int acpi_bus_init_power(struct acpi_device *device)
                if (result)
                        return result;
        } else if (state == ACPI_STATE_UNKNOWN) {
-               /* No power resources and missing _PSC? Try to force D0. */
+               /*
+                * No power resources and missing _PSC?  Cross fingers and make
+                * it D0 in hope that this is what the BIOS put the device into.
+                * [We tried to force D0 here by executing _PS0, but that broke
+                * Toshiba P870-303 in a nasty way.]
+                */
                state = ACPI_STATE_D0;
-               result = acpi_dev_pm_explicit_set(device, state);
-               if (result)
-                       return result;
        }
        device->power.state = state;
        return 0;
@@ -385,6 +325,69 @@ bool acpi_bus_power_manageable(acpi_handle handle)
 }
 EXPORT_SYMBOL(acpi_bus_power_manageable);
 
+#ifdef CONFIG_PM
+static DEFINE_MUTEX(acpi_pm_notifier_lock);
+
+/**
+ * acpi_add_pm_notifier - Register PM notifier for given ACPI device.
+ * @adev: ACPI device to add the notifier for.
+ * @context: Context information to pass to the notifier routine.
+ *
+ * NOTE: @adev need not be a run-wake or wakeup device to be a valid source of
+ * PM wakeup events.  For example, wakeup events may be generated for bridges
+ * if one of the devices below the bridge is signaling wakeup, even if the
+ * bridge itself doesn't have a wakeup GPE associated with it.
+ */
+acpi_status acpi_add_pm_notifier(struct acpi_device *adev,
+                                acpi_notify_handler handler, void *context)
+{
+       acpi_status status = AE_ALREADY_EXISTS;
+
+       mutex_lock(&acpi_pm_notifier_lock);
+
+       if (adev->wakeup.flags.notifier_present)
+               goto out;
+
+       status = acpi_install_notify_handler(adev->handle,
+                                            ACPI_SYSTEM_NOTIFY,
+                                            handler, context);
+       if (ACPI_FAILURE(status))
+               goto out;
+
+       adev->wakeup.flags.notifier_present = true;
+
+ out:
+       mutex_unlock(&acpi_pm_notifier_lock);
+       return status;
+}
+
+/**
+ * acpi_remove_pm_notifier - Unregister PM notifier from given ACPI device.
+ * @adev: ACPI device to remove the notifier from.
+ */
+acpi_status acpi_remove_pm_notifier(struct acpi_device *adev,
+                                   acpi_notify_handler handler)
+{
+       acpi_status status = AE_BAD_PARAMETER;
+
+       mutex_lock(&acpi_pm_notifier_lock);
+
+       if (!adev->wakeup.flags.notifier_present)
+               goto out;
+
+       status = acpi_remove_notify_handler(adev->handle,
+                                           ACPI_SYSTEM_NOTIFY,
+                                           handler);
+       if (ACPI_FAILURE(status))
+               goto out;
+
+       adev->wakeup.flags.notifier_present = false;
+
+ out:
+       mutex_unlock(&acpi_pm_notifier_lock);
+       return status;
+}
+
 bool acpi_bus_can_wakeup(acpi_handle handle)
 {
        struct acpi_device *device;
@@ -1023,3 +1026,4 @@ void acpi_dev_pm_remove_dependent(acpi_handle handle, struct device *depdev)
        mutex_unlock(&adev->physical_node_lock);
 }
 EXPORT_SYMBOL_GPL(acpi_dev_pm_remove_dependent);
+#endif /* CONFIG_PM */
index d45b287..edc0081 100644 (file)
@@ -223,7 +223,7 @@ static int ec_check_sci_sync(struct acpi_ec *ec, u8 state)
 static int ec_poll(struct acpi_ec *ec)
 {
        unsigned long flags;
-       int repeat = 2; /* number of command restarts */
+       int repeat = 5; /* number of command restarts */
        while (repeat--) {
                unsigned long delay = jiffies +
                        msecs_to_jiffies(ec_delay);
@@ -241,8 +241,6 @@ static int ec_poll(struct acpi_ec *ec)
                        }
                        advance_transaction(ec, acpi_ec_read_status(ec));
                } while (time_before(jiffies, delay));
-               if (acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF)
-                       break;
                pr_debug(PREFIX "controller reset, restart transaction\n");
                spin_lock_irqsave(&ec->lock, flags);
                start_transaction(ec);
index 6f1afd9..297cbf4 100644 (file)
@@ -35,7 +35,6 @@ void acpi_pci_link_init(void);
 void acpi_pci_root_hp_init(void);
 void acpi_platform_init(void);
 int acpi_sysfs_init(void);
-void acpi_csrt_init(void);
 #ifdef CONFIG_ACPI_CONTAINER
 void acpi_container_init(void);
 #else
index 1dd6f6c..e427dc5 100644 (file)
@@ -641,7 +641,9 @@ static void _handle_hotplug_event_root(struct work_struct *work)
                /* bus enumerate */
                printk(KERN_DEBUG "%s: Bus check notify on %s\n", __func__,
                                 (char *)buffer.pointer);
-               if (!root)
+               if (root)
+                       acpiphp_check_host_bridge(handle);
+               else
                        handle_root_bridge_insertion(handle);
 
                break;
index bec717f..c266cdc 100644 (file)
@@ -95,9 +95,6 @@ static const struct acpi_device_id processor_device_ids[] = {
 };
 MODULE_DEVICE_TABLE(acpi, processor_device_ids);
 
-static SIMPLE_DEV_PM_OPS(acpi_processor_pm,
-                        acpi_processor_suspend, acpi_processor_resume);
-
 static struct acpi_driver acpi_processor_driver = {
        .name = "processor",
        .class = ACPI_PROCESSOR_CLASS,
@@ -107,7 +104,6 @@ static struct acpi_driver acpi_processor_driver = {
                .remove = acpi_processor_remove,
                .notify = acpi_processor_notify,
                },
-       .drv.pm = &acpi_processor_pm,
 };
 
 #define INSTALL_NOTIFY_HANDLER         1
@@ -934,6 +930,8 @@ static int __init acpi_processor_init(void)
        if (result < 0)
                return result;
 
+       acpi_processor_syscore_init();
+
        acpi_processor_install_hotplug_notify();
 
        acpi_thermal_cpufreq_init();
@@ -956,6 +954,8 @@ static void __exit acpi_processor_exit(void)
 
        acpi_processor_uninstall_hotplug_notify();
 
+       acpi_processor_syscore_exit();
+
        acpi_bus_unregister_driver(&acpi_processor_driver);
 
        return;
index f0df2c9..eb133c7 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/sched.h>       /* need_resched() */
 #include <linux/clockchips.h>
 #include <linux/cpuidle.h>
+#include <linux/syscore_ops.h>
 
 /*
  * Include the apic definitions for x86 to have the APIC timer related defines
@@ -210,33 +211,41 @@ static void lapic_timer_state_broadcast(struct acpi_processor *pr,
 
 #endif
 
+#ifdef CONFIG_PM_SLEEP
 static u32 saved_bm_rld;
 
-static void acpi_idle_bm_rld_save(void)
+int acpi_processor_suspend(void)
 {
        acpi_read_bit_register(ACPI_BITREG_BUS_MASTER_RLD, &saved_bm_rld);
+       return 0;
 }
-static void acpi_idle_bm_rld_restore(void)
+
+void acpi_processor_resume(void)
 {
        u32 resumed_bm_rld;
 
        acpi_read_bit_register(ACPI_BITREG_BUS_MASTER_RLD, &resumed_bm_rld);
+       if (resumed_bm_rld == saved_bm_rld)
+               return;
 
-       if (resumed_bm_rld != saved_bm_rld)
-               acpi_write_bit_register(ACPI_BITREG_BUS_MASTER_RLD, saved_bm_rld);
+       acpi_write_bit_register(ACPI_BITREG_BUS_MASTER_RLD, saved_bm_rld);
 }
 
-int acpi_processor_suspend(struct device *dev)
+static struct syscore_ops acpi_processor_syscore_ops = {
+       .suspend = acpi_processor_suspend,
+       .resume = acpi_processor_resume,
+};
+
+void acpi_processor_syscore_init(void)
 {
-       acpi_idle_bm_rld_save();
-       return 0;
+       register_syscore_ops(&acpi_processor_syscore_ops);
 }
 
-int acpi_processor_resume(struct device *dev)
+void acpi_processor_syscore_exit(void)
 {
-       acpi_idle_bm_rld_restore();
-       return 0;
+       unregister_syscore_ops(&acpi_processor_syscore_ops);
 }
+#endif /* CONFIG_PM_SLEEP */
 
 #if defined(CONFIG_X86)
 static void tsc_check_state(int state)
index fe158fd..44225cb 100644 (file)
@@ -1785,7 +1785,7 @@ static void acpi_scan_init_hotplug(acpi_handle handle, int type)
        acpi_set_pnp_ids(handle, &pnp, type);
 
        if (!pnp.type.hardware_id)
-               return;
+               goto out;
 
        /*
         * This relies on the fact that acpi_install_notify_handler() will not
@@ -1800,6 +1800,7 @@ static void acpi_scan_init_hotplug(acpi_handle handle, int type)
                }
        }
 
+out:
        acpi_free_pnp_ids(&pnp);
 }
 
@@ -2042,7 +2043,6 @@ int __init acpi_scan_init(void)
        acpi_pci_link_init();
        acpi_platform_init();
        acpi_lpss_init();
-       acpi_csrt_init();
        acpi_container_init();
        acpi_memory_hotplug_init();
 
index c3932d0..5d7075d 100644 (file)
@@ -456,6 +456,30 @@ static struct dmi_system_id video_dmi_table[] __initdata = {
                DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dm4 Notebook PC"),
                },
        },
+       {
+        .callback = video_ignore_initial_backlight,
+        .ident = "HP Pavilion g6 Notebook PC",
+        .matches = {
+                DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
+                DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion g6 Notebook PC"),
+               },
+       },
+       {
+        .callback = video_ignore_initial_backlight,
+        .ident = "HP 1000 Notebook PC",
+        .matches = {
+               DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "HP 1000 Notebook PC"),
+               },
+       },
+       {
+        .callback = video_ignore_initial_backlight,
+        .ident = "HP Pavilion m4",
+        .matches = {
+               DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion m4 Notebook PC"),
+               },
+       },
        {}
 };
 
index 66f6762..e6bd910 100644 (file)
@@ -161,6 +161,14 @@ static struct dmi_system_id video_detect_dmi_table[] = {
                DMI_MATCH(DMI_PRODUCT_NAME, "UL30VT"),
                },
        },
+       {
+       .callback = video_detect_force_vendor,
+       .ident = "Asus UL30A",
+       .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
+               DMI_MATCH(DMI_PRODUCT_NAME, "UL30A"),
+               },
+       },
        { },
 };
 
index 4e94ba2..9d0cf01 100644 (file)
@@ -2,7 +2,7 @@
 /*
  *  acard-ahci.c - ACard AHCI SATA support
  *
- *  Maintained by:  Jeff Garzik <jgarzik@pobox.com>
+ *  Maintained by:  Tejun Heo <tj@kernel.org>
  *                 Please ALWAYS copy linux-ide@vger.kernel.org
  *                 on emails.
  *
index 251e57d..2b50dfd 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  ahci.c - AHCI SATA support
  *
- *  Maintained by:  Jeff Garzik <jgarzik@pobox.com>
+ *  Maintained by:  Tejun Heo <tj@kernel.org>
  *                 Please ALWAYS copy linux-ide@vger.kernel.org
  *                 on emails.
  *
@@ -423,6 +423,8 @@ static const struct pci_device_id ahci_pci_tbl[] = {
          .driver_data = board_ahci_yes_fbs },                  /* 88se9125 */
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x917a),
          .driver_data = board_ahci_yes_fbs },                  /* 88se9172 */
+       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9172),
+         .driver_data = board_ahci_yes_fbs },                  /* 88se9172 */
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9192),
          .driver_data = board_ahci_yes_fbs },                  /* 88se9172 on some Gigabyte */
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a3),
index b830e6c..10b14d4 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  ahci.h - Common AHCI SATA definitions and declarations
  *
- *  Maintained by:  Jeff Garzik <jgarzik@pobox.com>
+ *  Maintained by:  Tejun Heo <tj@kernel.org>
  *                 Please ALWAYS copy linux-ide@vger.kernel.org
  *                 on emails.
  *
index 2f48123..9a8a674 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *    ata_piix.c - Intel PATA/SATA controllers
  *
- *    Maintained by:  Jeff Garzik <jgarzik@pobox.com>
+ *    Maintained by:  Tejun Heo <tj@kernel.org>
  *                 Please ALWAYS copy linux-ide@vger.kernel.org
  *                 on emails.
  *
@@ -151,6 +151,7 @@ enum piix_controller_ids {
        piix_pata_vmw,                  /* PIIX4 for VMware, spurious DMA_ERR */
        ich8_sata_snb,
        ich8_2port_sata_snb,
+       ich8_2port_sata_byt,
 };
 
 struct piix_map_db {
@@ -334,6 +335,9 @@ static const struct pci_device_id piix_pci_tbl[] = {
        { 0x8086, 0x8d60, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
        /* SATA Controller IDE (Wellsburg) */
        { 0x8086, 0x8d68, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
+       /* SATA Controller IDE (BayTrail) */
+       { 0x8086, 0x0F20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata_byt },
+       { 0x8086, 0x0F21, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata_byt },
 
        { }     /* terminate list */
 };
@@ -441,6 +445,7 @@ static const struct piix_map_db *piix_map_db_table[] = {
        [tolapai_sata]          = &tolapai_map_db,
        [ich8_sata_snb]         = &ich8_map_db,
        [ich8_2port_sata_snb]   = &ich8_2port_map_db,
+       [ich8_2port_sata_byt]   = &ich8_2port_map_db,
 };
 
 static struct pci_bits piix_enable_bits[] = {
@@ -1254,6 +1259,16 @@ static struct ata_port_info piix_port_info[] = {
                .udma_mask      = ATA_UDMA6,
                .port_ops       = &piix_sata_ops,
        },
+
+       [ich8_2port_sata_byt] =
+       {
+               .flags          = PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR | PIIX_FLAG_PIO16,
+               .pio_mask       = ATA_PIO4,
+               .mwdma_mask     = ATA_MWDMA2,
+               .udma_mask      = ATA_UDMA6,
+               .port_ops       = &piix_sata_ops,
+       },
+
 };
 
 #define AHCI_PCI_BAR 5
index 34c8216..a70ff15 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  libahci.c - Common AHCI SATA low-level routines
  *
- *  Maintained by:  Jeff Garzik <jgarzik@pobox.com>
+ *  Maintained by:  Tejun Heo <tj@kernel.org>
  *                 Please ALWAYS copy linux-ide@vger.kernel.org
  *                 on emails.
  *
index 63c743b..f218427 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  libata-core.c - helper library for ATA
  *
- *  Maintained by:  Jeff Garzik <jgarzik@pobox.com>
+ *  Maintained by:  Tejun Heo <tj@kernel.org>
  *                 Please ALWAYS copy linux-ide@vger.kernel.org
  *                 on emails.
  *
@@ -1602,6 +1602,12 @@ unsigned ata_exec_internal_sg(struct ata_device *dev,
        qc->tf = *tf;
        if (cdb)
                memcpy(qc->cdb, cdb, ATAPI_CDB_LEN);
+
+       /* some SATA bridges need us to indicate data xfer direction */
+       if (tf->protocol == ATAPI_PROT_DMA && (dev->flags & ATA_DFLAG_DMADIR) &&
+           dma_dir == DMA_FROM_DEVICE)
+               qc->tf.feature |= ATAPI_DMADIR;
+
        qc->flags |= ATA_QCFLAG_RESULT_TF;
        qc->dma_dir = dma_dir;
        if (dma_dir != DMA_NONE) {
index f9476fb..c69fcce 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  libata-eh.c - libata error handling
  *
- *  Maintained by:  Jeff Garzik <jgarzik@pobox.com>
+ *  Maintained by:  Tejun Heo <tj@kernel.org>
  *                 Please ALWAYS copy linux-ide@vger.kernel.org
  *                 on emails.
  *
index dd310b2..0101af5 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  libata-scsi.c - helper library for ATA
  *
- *  Maintained by:  Jeff Garzik <jgarzik@pobox.com>
+ *  Maintained by:  Tejun Heo <tj@kernel.org>
  *                 Please ALWAYS copy linux-ide@vger.kernel.org
  *                 on emails.
  *
index d8af325..b603720 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  libata-sff.c - helper library for PCI IDE BMDMA
  *
- *  Maintained by:  Jeff Garzik <jgarzik@pobox.com>
+ *  Maintained by:  Tejun Heo <tj@kernel.org>
  *                 Please ALWAYS copy linux-ide@vger.kernel.org
  *                 on emails.
  *
index c1bfaf4..980b88e 100644 (file)
@@ -933,11 +933,6 @@ static int ep93xx_pata_probe(struct platform_device *pdev)
        }
 
        mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!mem_res) {
-               err = -ENXIO;
-               goto err_rel_gpio;
-       }
-
        ide_base = devm_ioremap_resource(&pdev->dev, mem_res);
        if (IS_ERR(ide_base)) {
                err = PTR_ERR(ide_base);
index 5053333..8ea6e6a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  pdc_adma.c - Pacific Digital Corporation ADMA
  *
- *  Maintained by:  Mark Lord <mlord@pobox.com>
+ *  Maintained by:  Tejun Heo <tj@kernel.org>
  *
  *  Copyright 2005 Mark Lord
  *
index fb0dd87..958ba2a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  sata_promise.c - Promise SATA
  *
- *  Maintained by:  Jeff Garzik <jgarzik@pobox.com>
+ *  Maintained by:  Tejun Heo <tj@kernel.org>
  *                 Mikael Pettersson <mikpe@it.uu.se>
  *                 Please ALWAYS copy linux-ide@vger.kernel.org
  *                 on emails.
index 4799868..249c8a2 100644 (file)
@@ -549,6 +549,7 @@ static void sata_rcar_bmdma_start(struct ata_queued_cmd *qc)
 
        /* start host DMA transaction */
        dmactl = ioread32(priv->base + ATAPI_CONTROL1_REG);
+       dmactl &= ~ATAPI_CONTROL1_STOP;
        dmactl |= ATAPI_CONTROL1_START;
        iowrite32(dmactl, priv->base + ATAPI_CONTROL1_REG);
 }
@@ -618,17 +619,16 @@ static struct ata_port_operations sata_rcar_port_ops = {
        .bmdma_status           = sata_rcar_bmdma_status,
 };
 
-static int sata_rcar_serr_interrupt(struct ata_port *ap)
+static void sata_rcar_serr_interrupt(struct ata_port *ap)
 {
        struct sata_rcar_priv *priv = ap->host->private_data;
        struct ata_eh_info *ehi = &ap->link.eh_info;
        int freeze = 0;
-       int handled = 0;
        u32 serror;
 
        serror = ioread32(priv->base + SCRSERR_REG);
        if (!serror)
-               return 0;
+               return;
 
        DPRINTK("SError @host_intr: 0x%x\n", serror);
 
@@ -641,7 +641,6 @@ static int sata_rcar_serr_interrupt(struct ata_port *ap)
                ata_ehi_push_desc(ehi, "%s", "hotplug");
 
                freeze = serror & SERR_COMM_WAKE ? 0 : 1;
-               handled = 1;
        }
 
        /* freeze or abort */
@@ -649,11 +648,9 @@ static int sata_rcar_serr_interrupt(struct ata_port *ap)
                ata_port_freeze(ap);
        else
                ata_port_abort(ap);
-
-       return handled;
 }
 
-static int sata_rcar_ata_interrupt(struct ata_port *ap)
+static void sata_rcar_ata_interrupt(struct ata_port *ap)
 {
        struct ata_queued_cmd *qc;
        int handled = 0;
@@ -662,7 +659,9 @@ static int sata_rcar_ata_interrupt(struct ata_port *ap)
        if (qc)
                handled |= ata_bmdma_port_intr(ap, qc);
 
-       return handled;
+       /* be sure to clear ATA interrupt */
+       if (!handled)
+               sata_rcar_check_status(ap);
 }
 
 static irqreturn_t sata_rcar_interrupt(int irq, void *dev_instance)
@@ -677,20 +676,21 @@ static irqreturn_t sata_rcar_interrupt(int irq, void *dev_instance)
        spin_lock_irqsave(&host->lock, flags);
 
        sataintstat = ioread32(priv->base + SATAINTSTAT_REG);
+       sataintstat &= SATA_RCAR_INT_MASK;
        if (!sataintstat)
                goto done;
        /* ack */
-       iowrite32(sataintstat & ~SATA_RCAR_INT_MASK,
-                priv->base + SATAINTSTAT_REG);
+       iowrite32(~sataintstat & 0x7ff, priv->base + SATAINTSTAT_REG);
 
        ap = host->ports[0];
 
        if (sataintstat & SATAINTSTAT_ATA)
-               handled |= sata_rcar_ata_interrupt(ap);
+               sata_rcar_ata_interrupt(ap);
 
        if (sataintstat & SATAINTSTAT_SERR)
-               handled |= sata_rcar_serr_interrupt(ap);
+               sata_rcar_serr_interrupt(ap);
 
+       handled = 1;
 done:
        spin_unlock_irqrestore(&host->lock, flags);
 
index a7b3167..0ae3ca4 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  sata_sil.c - Silicon Image SATA
  *
- *  Maintained by:  Jeff Garzik <jgarzik@pobox.com>
+ *  Maintained by:  Tejun Heo <tj@kernel.org>
  *                 Please ALWAYS copy linux-ide@vger.kernel.org
  *                 on emails.
  *
index 7b7127a..9947010 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  sata_sx4.c - Promise SATA
  *
- *  Maintained by:  Jeff Garzik <jgarzik@pobox.com>
+ *  Maintained by:  Tejun Heo <tj@kernel.org>
  *                 Please ALWAYS copy linux-ide@vger.kernel.org
  *                 on emails.
  *
index 5913ea9..87f056e 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  sata_via.c - VIA Serial ATA controllers
  *
- *  Maintained by:  Jeff Garzik <jgarzik@pobox.com>
+ *  Maintained by:  Tejun Heo <tj@kernel.org>
  *                Please ALWAYS copy linux-ide@vger.kernel.org
  *                on emails.
  *
index 1a68f94..d414331 100644 (file)
@@ -1295,6 +1295,7 @@ int subsys_virtual_register(struct bus_type *subsys,
 
        return subsys_register(subsys, groups, virtual_dir);
 }
+EXPORT_SYMBOL_GPL(subsys_virtual_register);
 
 int __init buses_init(void)
 {
index 0163124..2499cef 100644 (file)
@@ -572,9 +572,11 @@ int device_create_file(struct device *dev,
 
        if (dev) {
                WARN(((attr->attr.mode & S_IWUGO) && !attr->store),
-                               "Write permission without 'store'\n");
+                       "Attribute %s: write permission without 'store'\n",
+                       attr->attr.name);
                WARN(((attr->attr.mode & S_IRUGO) && !attr->show),
-                               "Read permission without 'show'\n");
+                       "Attribute %s: read permission without 'show'\n",
+                       attr->attr.name);
                error = sysfs_create_file(&dev->kobj, &attr->attr);
        }
 
index 39c3252..5da9140 100644 (file)
@@ -61,24 +61,24 @@ EXPORT_SYMBOL_GPL(dev_pm_get_subsys_data);
 int dev_pm_put_subsys_data(struct device *dev)
 {
        struct pm_subsys_data *psd;
-       int ret = 0;
+       int ret = 1;
 
        spin_lock_irq(&dev->power.lock);
 
        psd = dev_to_psd(dev);
-       if (!psd) {
-               ret = -EINVAL;
+       if (!psd)
                goto out;
-       }
 
        if (--psd->refcount == 0) {
                dev->power.subsys_data = NULL;
-               kfree(psd);
-               ret = 1;
+       } else {
+               psd = NULL;
+               ret = 0;
        }
 
  out:
        spin_unlock_irq(&dev->power.lock);
+       kfree(psd);
 
        return ret;
 }
index aa0875f..02f490b 100644 (file)
@@ -143,7 +143,7 @@ static int rbtree_show(struct seq_file *s, void *ignored)
        int registers = 0;
        int this_registers, average;
 
-       map->lock(map);
+       map->lock(map->lock_arg);
 
        mem_size = sizeof(*rbtree_ctx);
        mem_size += BITS_TO_LONGS(map->cache_present_nbits) * sizeof(long);
@@ -170,7 +170,7 @@ static int rbtree_show(struct seq_file *s, void *ignored)
        seq_printf(s, "%d nodes, %d registers, average %d registers, used %zu bytes\n",
                   nodes, registers, average, mem_size);
 
-       map->unlock(map);
+       map->unlock(map->lock_arg);
 
        return 0;
 }
@@ -391,8 +391,6 @@ static int regcache_rbtree_sync(struct regmap *map, unsigned int min,
        for (node = rb_first(&rbtree_ctx->root); node; node = rb_next(node)) {
                rbnode = rb_entry(node, struct regcache_rbtree_node, node);
 
-               if (rbnode->base_reg < min)
-                       continue;
                if (rbnode->base_reg > max)
                        break;
                if (rbnode->base_reg + rbnode->blklen < min)
index 75923f2..507ee2d 100644 (file)
@@ -270,7 +270,7 @@ int regcache_sync(struct regmap *map)
 
        BUG_ON(!map->cache_ops || !map->cache_ops->sync);
 
-       map->lock(map);
+       map->lock(map->lock_arg);
        /* Remember the initial bypass state */
        bypass = map->cache_bypass;
        dev_dbg(map->dev, "Syncing %s cache\n",
@@ -306,7 +306,7 @@ out:
        trace_regcache_sync(map->dev, name, "stop");
        /* Restore the bypass state */
        map->cache_bypass = bypass;
-       map->unlock(map);
+       map->unlock(map->lock_arg);
 
        return ret;
 }
@@ -333,7 +333,7 @@ int regcache_sync_region(struct regmap *map, unsigned int min,
 
        BUG_ON(!map->cache_ops || !map->cache_ops->sync);
 
-       map->lock(map);
+       map->lock(map->lock_arg);
 
        /* Remember the initial bypass state */
        bypass = map->cache_bypass;
@@ -352,7 +352,7 @@ out:
        trace_regcache_sync(map->dev, name, "stop region");
        /* Restore the bypass state */
        map->cache_bypass = bypass;
-       map->unlock(map);
+       map->unlock(map->lock_arg);
 
        return ret;
 }
@@ -372,11 +372,11 @@ EXPORT_SYMBOL_GPL(regcache_sync_region);
  */
 void regcache_cache_only(struct regmap *map, bool enable)
 {
-       map->lock(map);
+       map->lock(map->lock_arg);
        WARN_ON(map->cache_bypass && enable);
        map->cache_only = enable;
        trace_regmap_cache_only(map->dev, enable);
-       map->unlock(map);
+       map->unlock(map->lock_arg);
 }
 EXPORT_SYMBOL_GPL(regcache_cache_only);
 
@@ -391,9 +391,9 @@ EXPORT_SYMBOL_GPL(regcache_cache_only);
  */
 void regcache_mark_dirty(struct regmap *map)
 {
-       map->lock(map);
+       map->lock(map->lock_arg);
        map->cache_dirty = true;
-       map->unlock(map);
+       map->unlock(map->lock_arg);
 }
 EXPORT_SYMBOL_GPL(regcache_mark_dirty);
 
@@ -410,11 +410,11 @@ EXPORT_SYMBOL_GPL(regcache_mark_dirty);
  */
 void regcache_cache_bypass(struct regmap *map, bool enable)
 {
-       map->lock(map);
+       map->lock(map->lock_arg);
        WARN_ON(map->cache_only && enable);
        map->cache_bypass = enable;
        trace_regmap_cache_bypass(map->dev, enable);
-       map->unlock(map);
+       map->unlock(map->lock_arg);
 }
 EXPORT_SYMBOL_GPL(regcache_cache_bypass);
 
index 23b701f..975719b 100644 (file)
@@ -265,6 +265,7 @@ static ssize_t regmap_map_write_file(struct file *file,
        char *start = buf;
        unsigned long reg, value;
        struct regmap *map = file->private_data;
+       int ret;
 
        buf_size = min(count, (sizeof(buf)-1));
        if (copy_from_user(buf, user_buf, buf_size))
@@ -282,7 +283,9 @@ static ssize_t regmap_map_write_file(struct file *file,
        /* Userspace has been fiddling around behind the kernel's back */
        add_taint(TAINT_USER, LOCKDEP_NOW_UNRELIABLE);
 
-       regmap_write(map, reg, value);
+       ret = regmap_write(map, reg, value);
+       if (ret < 0)
+               return ret;
        return buf_size;
 }
 #else
index bca9c80..8bffa5c 100644 (file)
@@ -84,6 +84,8 @@ static const struct bcma_device_id_name bcma_bcm_device_names[] = {
        { BCMA_CORE_I2S, "I2S" },
        { BCMA_CORE_SDR_DDR1_MEM_CTL, "SDR/DDR1 Memory Controller" },
        { BCMA_CORE_SHIM, "SHIM" },
+       { BCMA_CORE_PCIE2, "PCIe Gen2" },
+       { BCMA_CORE_ARM_CR4, "ARM CR4" },
        { BCMA_CORE_DEFAULT, "Default" },
 };
 
index f1a29f8..9bf4371 100644 (file)
@@ -117,13 +117,13 @@ static struct page *brd_insert_page(struct brd_device *brd, sector_t sector)
 
        spin_lock(&brd->brd_lock);
        idx = sector >> PAGE_SECTORS_SHIFT;
+       page->index = idx;
        if (radix_tree_insert(&brd->brd_pages, idx, page)) {
                __free_page(page);
                page = radix_tree_lookup(&brd->brd_pages, idx);
                BUG_ON(!page);
                BUG_ON(page->index != idx);
-       } else
-               page->index = idx;
+       }
        spin_unlock(&brd->brd_lock);
 
        radix_tree_preload_end();
index 6374dc1..62b6c2c 100644 (file)
@@ -168,8 +168,6 @@ static irqreturn_t do_cciss_msix_intr(int irq, void *dev_id);
 static int cciss_open(struct block_device *bdev, fmode_t mode);
 static int cciss_unlocked_open(struct block_device *bdev, fmode_t mode);
 static void cciss_release(struct gendisk *disk, fmode_t mode);
-static int do_ioctl(struct block_device *bdev, fmode_t mode,
-                   unsigned int cmd, unsigned long arg);
 static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
                       unsigned int cmd, unsigned long arg);
 static int cciss_getgeo(struct block_device *bdev, struct hd_geometry *geo);
@@ -235,7 +233,7 @@ static const struct block_device_operations cciss_fops = {
        .owner = THIS_MODULE,
        .open = cciss_unlocked_open,
        .release = cciss_release,
-       .ioctl = do_ioctl,
+       .ioctl = cciss_ioctl,
        .getgeo = cciss_getgeo,
 #ifdef CONFIG_COMPAT
        .compat_ioctl = cciss_compat_ioctl,
@@ -1143,16 +1141,6 @@ static void cciss_release(struct gendisk *disk, fmode_t mode)
        mutex_unlock(&cciss_mutex);
 }
 
-static int do_ioctl(struct block_device *bdev, fmode_t mode,
-                   unsigned cmd, unsigned long arg)
-{
-       int ret;
-       mutex_lock(&cciss_mutex);
-       ret = cciss_ioctl(bdev, mode, cmd, arg);
-       mutex_unlock(&cciss_mutex);
-       return ret;
-}
-
 #ifdef CONFIG_COMPAT
 
 static int cciss_ioctl32_passthru(struct block_device *bdev, fmode_t mode,
@@ -1179,7 +1167,7 @@ static int cciss_compat_ioctl(struct block_device *bdev, fmode_t mode,
        case CCISS_REGNEWD:
        case CCISS_RESCANDISK:
        case CCISS_GETLUNINFO:
-               return do_ioctl(bdev, mode, cmd, arg);
+               return cciss_ioctl(bdev, mode, cmd, arg);
 
        case CCISS_PASSTHRU32:
                return cciss_ioctl32_passthru(bdev, mode, cmd, arg);
@@ -1219,7 +1207,7 @@ static int cciss_ioctl32_passthru(struct block_device *bdev, fmode_t mode,
        if (err)
                return -EFAULT;
 
-       err = do_ioctl(bdev, mode, CCISS_PASSTHRU, (unsigned long)p);
+       err = cciss_ioctl(bdev, mode, CCISS_PASSTHRU, (unsigned long)p);
        if (err)
                return err;
        err |=
@@ -1261,7 +1249,7 @@ static int cciss_ioctl32_big_passthru(struct block_device *bdev, fmode_t mode,
        if (err)
                return -EFAULT;
 
-       err = do_ioctl(bdev, mode, CCISS_BIG_PASSTHRU, (unsigned long)p);
+       err = cciss_ioctl(bdev, mode, CCISS_BIG_PASSTHRU, (unsigned long)p);
        if (err)
                return err;
        err |=
@@ -1311,11 +1299,14 @@ static int cciss_getpciinfo(ctlr_info_t *h, void __user *argp)
 static int cciss_getintinfo(ctlr_info_t *h, void __user *argp)
 {
        cciss_coalint_struct intinfo;
+       unsigned long flags;
 
        if (!argp)
                return -EINVAL;
+       spin_lock_irqsave(&h->lock, flags);
        intinfo.delay = readl(&h->cfgtable->HostWrite.CoalIntDelay);
        intinfo.count = readl(&h->cfgtable->HostWrite.CoalIntCount);
+       spin_unlock_irqrestore(&h->lock, flags);
        if (copy_to_user
            (argp, &intinfo, sizeof(cciss_coalint_struct)))
                return -EFAULT;
@@ -1356,12 +1347,15 @@ static int cciss_setintinfo(ctlr_info_t *h, void __user *argp)
 static int cciss_getnodename(ctlr_info_t *h, void __user *argp)
 {
        NodeName_type NodeName;
+       unsigned long flags;
        int i;
 
        if (!argp)
                return -EINVAL;
+       spin_lock_irqsave(&h->lock, flags);
        for (i = 0; i < 16; i++)
                NodeName[i] = readb(&h->cfgtable->ServerName[i]);
+       spin_unlock_irqrestore(&h->lock, flags);
        if (copy_to_user(argp, NodeName, sizeof(NodeName_type)))
                return -EFAULT;
        return 0;
@@ -1398,10 +1392,13 @@ static int cciss_setnodename(ctlr_info_t *h, void __user *argp)
 static int cciss_getheartbeat(ctlr_info_t *h, void __user *argp)
 {
        Heartbeat_type heartbeat;
+       unsigned long flags;
 
        if (!argp)
                return -EINVAL;
+       spin_lock_irqsave(&h->lock, flags);
        heartbeat = readl(&h->cfgtable->HeartBeat);
+       spin_unlock_irqrestore(&h->lock, flags);
        if (copy_to_user(argp, &heartbeat, sizeof(Heartbeat_type)))
                return -EFAULT;
        return 0;
@@ -1410,10 +1407,13 @@ static int cciss_getheartbeat(ctlr_info_t *h, void __user *argp)
 static int cciss_getbustypes(ctlr_info_t *h, void __user *argp)
 {
        BusTypes_type BusTypes;
+       unsigned long flags;
 
        if (!argp)
                return -EINVAL;
+       spin_lock_irqsave(&h->lock, flags);
        BusTypes = readl(&h->cfgtable->BusTypes);
+       spin_unlock_irqrestore(&h->lock, flags);
        if (copy_to_user(argp, &BusTypes, sizeof(BusTypes_type)))
                return -EFAULT;
        return 0;
index 847107e..20dd52a 100644 (file)
@@ -3002,7 +3002,8 @@ static int mtip_hw_debugfs_init(struct driver_data *dd)
 
 static void mtip_hw_debugfs_exit(struct driver_data *dd)
 {
-       debugfs_remove_recursive(dd->dfs_node);
+       if (dd->dfs_node)
+               debugfs_remove_recursive(dd->dfs_node);
 }
 
 
@@ -3863,7 +3864,7 @@ static void mtip_make_request(struct request_queue *queue, struct bio *bio)
        struct driver_data *dd = queue->queuedata;
        struct scatterlist *sg;
        struct bio_vec *bvec;
-       int nents = 0;
+       int i, nents = 0;
        int tag = 0, unaligned = 0;
 
        if (unlikely(dd->dd_flag & MTIP_DDF_STOP_IO)) {
@@ -3921,11 +3922,12 @@ static void mtip_make_request(struct request_queue *queue, struct bio *bio)
                }
 
                /* Create the scatter list for this bio. */
-               bio_for_each_segment(bvec, bio, nents) {
+               bio_for_each_segment(bvec, bio, i) {
                        sg_set_page(&sg[nents],
                                        bvec->bv_page,
                                        bvec->bv_len,
                                        bvec->bv_offset);
+                       nents++;
                }
 
                /* Issue the read/write. */
index 8efdfaa..ce79a59 100644 (file)
@@ -629,7 +629,7 @@ static int nvme_submit_bio_queue(struct nvme_queue *nvmeq, struct nvme_ns *ns,
        struct nvme_command *cmnd;
        struct nvme_iod *iod;
        enum dma_data_direction dma_dir;
-       int cmdid, length, result = -ENOMEM;
+       int cmdid, length, result;
        u16 control;
        u32 dsmgmt;
        int psegs = bio_phys_segments(ns->queue, bio);
@@ -640,6 +640,7 @@ static int nvme_submit_bio_queue(struct nvme_queue *nvmeq, struct nvme_ns *ns,
                        return result;
        }
 
+       result = -ENOMEM;
        iod = nvme_alloc_iod(psegs, bio->bi_size, GFP_ATOMIC);
        if (!iod)
                goto nomem;
@@ -977,6 +978,8 @@ static void nvme_cancel_ios(struct nvme_queue *nvmeq, bool timeout)
 
                if (timeout && !time_after(now, info[cmdid].timeout))
                        continue;
+               if (info[cmdid].ctx == CMD_CTX_CANCELLED)
+                       continue;
                dev_warn(nvmeq->q_dmadev, "Cancelling I/O %d\n", cmdid);
                ctx = cancel_cmdid(nvmeq, cmdid, &fn);
                fn(nvmeq->dev, ctx, &cqe);
@@ -1206,7 +1209,7 @@ struct nvme_iod *nvme_map_user_pages(struct nvme_dev *dev, int write,
 
        if (addr & 3)
                return ERR_PTR(-EINVAL);
-       if (!length)
+       if (!length || length > INT_MAX - PAGE_SIZE)
                return ERR_PTR(-EINVAL);
 
        offset = offset_in_page(addr);
@@ -1227,7 +1230,8 @@ struct nvme_iod *nvme_map_user_pages(struct nvme_dev *dev, int write,
        sg_init_table(sg, count);
        for (i = 0; i < count; i++) {
                sg_set_page(&sg[i], pages[i],
-                               min_t(int, length, PAGE_SIZE - offset), offset);
+                           min_t(unsigned, length, PAGE_SIZE - offset),
+                           offset);
                length -= (PAGE_SIZE - offset);
                offset = 0;
        }
@@ -1435,7 +1439,7 @@ static int nvme_user_admin_cmd(struct nvme_dev *dev,
                nvme_free_iod(dev, iod);
        }
 
-       if (!status && copy_to_user(&ucmd->result, &cmd.result,
+       if ((status >= 0) && copy_to_user(&ucmd->result, &cmd.result,
                                                        sizeof(cmd.result)))
                status = -EFAULT;
 
@@ -1633,7 +1637,8 @@ static int set_queue_count(struct nvme_dev *dev, int count)
 
 static int nvme_setup_io_queues(struct nvme_dev *dev)
 {
-       int result, cpu, i, nr_io_queues, db_bar_size, q_depth;
+       struct pci_dev *pdev = dev->pci_dev;
+       int result, cpu, i, nr_io_queues, db_bar_size, q_depth, q_count;
 
        nr_io_queues = num_online_cpus();
        result = set_queue_count(dev, nr_io_queues);
@@ -1642,14 +1647,14 @@ static int nvme_setup_io_queues(struct nvme_dev *dev)
        if (result < nr_io_queues)
                nr_io_queues = result;
 
+       q_count = nr_io_queues;
        /* Deregister the admin queue's interrupt */
        free_irq(dev->entry[0].vector, dev->queues[0]);
 
        db_bar_size = 4096 + ((nr_io_queues + 1) << (dev->db_stride + 3));
        if (db_bar_size > 8192) {
                iounmap(dev->bar);
-               dev->bar = ioremap(pci_resource_start(dev->pci_dev, 0),
-                                                               db_bar_size);
+               dev->bar = ioremap(pci_resource_start(pdev, 0), db_bar_size);
                dev->dbs = ((void __iomem *)dev->bar) + 4096;
                dev->queues[0]->q_db = dev->dbs;
        }
@@ -1657,19 +1662,36 @@ static int nvme_setup_io_queues(struct nvme_dev *dev)
        for (i = 0; i < nr_io_queues; i++)
                dev->entry[i].entry = i;
        for (;;) {
-               result = pci_enable_msix(dev->pci_dev, dev->entry,
-                                                               nr_io_queues);
+               result = pci_enable_msix(pdev, dev->entry, nr_io_queues);
                if (result == 0) {
                        break;
                } else if (result > 0) {
                        nr_io_queues = result;
                        continue;
                } else {
-                       nr_io_queues = 1;
+                       nr_io_queues = 0;
                        break;
                }
        }
 
+       if (nr_io_queues == 0) {
+               nr_io_queues = q_count;
+               for (;;) {
+                       result = pci_enable_msi_block(pdev, nr_io_queues);
+                       if (result == 0) {
+                               for (i = 0; i < nr_io_queues; i++)
+                                       dev->entry[i].vector = i + pdev->irq;
+                               break;
+                       } else if (result > 0) {
+                               nr_io_queues = result;
+                               continue;
+                       } else {
+                               nr_io_queues = 1;
+                               break;
+                       }
+               }
+       }
+
        result = queue_request_irq(dev, dev->queues[0], "nvme admin");
        /* XXX: handle failure here */
 
@@ -1850,7 +1872,10 @@ static void nvme_free_dev(struct kref *kref)
 {
        struct nvme_dev *dev = container_of(kref, struct nvme_dev, kref);
        nvme_dev_remove(dev);
-       pci_disable_msix(dev->pci_dev);
+       if (dev->pci_dev->msi_enabled)
+               pci_disable_msi(dev->pci_dev);
+       else if (dev->pci_dev->msix_enabled)
+               pci_disable_msix(dev->pci_dev);
        iounmap(dev->bar);
        nvme_release_instance(dev);
        nvme_release_prp_pools(dev);
@@ -1923,8 +1948,14 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        INIT_LIST_HEAD(&dev->namespaces);
        dev->pci_dev = pdev;
        pci_set_drvdata(pdev, dev);
-       dma_set_mask(&pdev->dev, DMA_BIT_MASK(64));
-       dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64));
+
+       if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(64)))
+               dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64));
+       else if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)))
+               dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
+       else
+               goto disable;
+
        result = nvme_set_instance(dev);
        if (result)
                goto disable;
@@ -1977,7 +2008,10 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
  unmap:
        iounmap(dev->bar);
  disable_msix:
-       pci_disable_msix(pdev);
+       if (dev->pci_dev->msi_enabled)
+               pci_disable_msi(dev->pci_dev);
+       else if (dev->pci_dev->msix_enabled)
+               pci_disable_msix(dev->pci_dev);
        nvme_release_instance(dev);
        nvme_release_prp_pools(dev);
  disable:
index fed54b0..102de2f 100644 (file)
@@ -44,7 +44,6 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/types.h>
-#include <linux/version.h>
 #include <scsi/sg.h>
 #include <scsi/scsi.h>
 
@@ -1654,7 +1653,7 @@ static void nvme_trans_modesel_save_bd(struct nvme_ns *ns, u8 *parm_list,
        }
 }
 
-static u16 nvme_trans_modesel_get_mp(struct nvme_ns *ns, struct sg_io_hdr *hdr,
+static int nvme_trans_modesel_get_mp(struct nvme_ns *ns, struct sg_io_hdr *hdr,
                                        u8 *mode_page, u8 page_code)
 {
        int res = SNTI_TRANSLATION_SUCCESS;
index 3c08983..f5d0ea1 100644 (file)
@@ -83,7 +83,8 @@
 
 #define MAX_SPEED 0xffff
 
-#define ZONE(sector, pd) (((sector) + (pd)->offset) & ~((pd)->settings.size - 1))
+#define ZONE(sector, pd) (((sector) + (pd)->offset) & \
+                       ~(sector_t)((pd)->settings.size - 1))
 
 static DEFINE_MUTEX(pktcdvd_mutex);
 static struct pktcdvd_device *pkt_devs[MAX_WRITERS];
index ca63104..3063452 100644 (file)
 #define        SECTOR_SHIFT    9
 #define        SECTOR_SIZE     (1ULL << SECTOR_SHIFT)
 
+/*
+ * Increment the given counter and return its updated value.
+ * If the counter is already 0 it will not be incremented.
+ * If the counter is already at its maximum value returns
+ * -EINVAL without updating it.
+ */
+static int atomic_inc_return_safe(atomic_t *v)
+{
+       unsigned int counter;
+
+       counter = (unsigned int)__atomic_add_unless(v, 1, 0);
+       if (counter <= (unsigned int)INT_MAX)
+               return (int)counter;
+
+       atomic_dec(v);
+
+       return -EINVAL;
+}
+
+/* Decrement the counter.  Return the resulting value, or -EINVAL */
+static int atomic_dec_return_safe(atomic_t *v)
+{
+       int counter;
+
+       counter = atomic_dec_return(v);
+       if (counter >= 0)
+               return counter;
+
+       atomic_inc(v);
+
+       return -EINVAL;
+}
+
 #define RBD_DRV_NAME "rbd"
 #define RBD_DRV_NAME_LONG "rbd (rados block device)"
 
  * block device image metadata (in-memory version)
  */
 struct rbd_image_header {
-       /* These four fields never change for a given rbd image */
+       /* These six fields never change for a given rbd image */
        char *object_prefix;
-       u64 features;
        __u8 obj_order;
        __u8 crypt_type;
        __u8 comp_type;
+       u64 stripe_unit;
+       u64 stripe_count;
+       u64 features;           /* Might be changeable someday? */
 
        /* The remaining fields need to be updated occasionally */
        u64 image_size;
        struct ceph_snap_context *snapc;
-       char *snap_names;
-       u64 *snap_sizes;
-
-       u64 stripe_unit;
-       u64 stripe_count;
+       char *snap_names;       /* format 1 only */
+       u64 *snap_sizes;        /* format 1 only */
 };
 
 /*
@@ -225,6 +257,7 @@ struct rbd_obj_request {
                };
        };
        struct page             **copyup_pages;
+       u32                     copyup_page_count;
 
        struct ceph_osd_request *osd_req;
 
@@ -257,6 +290,7 @@ struct rbd_img_request {
                struct rbd_obj_request  *obj_request;   /* obj req initiator */
        };
        struct page             **copyup_pages;
+       u32                     copyup_page_count;
        spinlock_t              completion_lock;/* protects next_completion */
        u32                     next_completion;
        rbd_img_callback_t      callback;
@@ -311,6 +345,7 @@ struct rbd_device {
 
        struct rbd_spec         *parent_spec;
        u64                     parent_overlap;
+       atomic_t                parent_ref;
        struct rbd_device       *parent;
 
        /* protects updating the header */
@@ -359,7 +394,8 @@ 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,
                          size_t count);
-static int rbd_dev_image_probe(struct rbd_device *rbd_dev);
+static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping);
+static void rbd_spec_put(struct rbd_spec *spec);
 
 static struct bus_attribute rbd_bus_attrs[] = {
        __ATTR(add, S_IWUSR, NULL, rbd_add),
@@ -426,7 +462,8 @@ static void rbd_img_parent_read(struct rbd_obj_request *obj_request);
 static void rbd_dev_remove_parent(struct rbd_device *rbd_dev);
 
 static int rbd_dev_refresh(struct rbd_device *rbd_dev);
-static int rbd_dev_v2_refresh(struct rbd_device *rbd_dev);
+static int rbd_dev_v2_header_onetime(struct rbd_device *rbd_dev);
+static int rbd_dev_v2_header_info(struct rbd_device *rbd_dev);
 static const char *rbd_dev_v2_snap_name(struct rbd_device *rbd_dev,
                                        u64 snap_id);
 static int _rbd_dev_v2_snap_size(struct rbd_device *rbd_dev, u64 snap_id,
@@ -482,8 +519,8 @@ static const struct block_device_operations rbd_bd_ops = {
 };
 
 /*
- * Initialize an rbd client instance.
- * We own *ceph_opts.
+ * Initialize an rbd client instance.  Success or not, this function
+ * consumes ceph_opts.
  */
 static struct rbd_client *rbd_client_create(struct ceph_options *ceph_opts)
 {
@@ -638,7 +675,8 @@ static int parse_rbd_opts_token(char *c, void *private)
 
 /*
  * Get a ceph client with specific addr and configuration, if one does
- * not exist create it.
+ * not exist create it.  Either way, ceph_opts is consumed by this
+ * function.
  */
 static struct rbd_client *rbd_get_client(struct ceph_options *ceph_opts)
 {
@@ -726,88 +764,123 @@ static bool rbd_dev_ondisk_valid(struct rbd_image_header_ondisk *ondisk)
 }
 
 /*
- * Create a new header structure, translate header format from the on-disk
- * header.
+ * Fill an rbd image header with information from the given format 1
+ * on-disk header.
  */
-static int rbd_header_from_disk(struct rbd_image_header *header,
+static int rbd_header_from_disk(struct rbd_device *rbd_dev,
                                 struct rbd_image_header_ondisk *ondisk)
 {
+       struct rbd_image_header *header = &rbd_dev->header;
+       bool first_time = header->object_prefix == NULL;
+       struct ceph_snap_context *snapc;
+       char *object_prefix = NULL;
+       char *snap_names = NULL;
+       u64 *snap_sizes = NULL;
        u32 snap_count;
-       size_t len;
        size_t size;
+       int ret = -ENOMEM;
        u32 i;
 
-       memset(header, 0, sizeof (*header));
+       /* Allocate this now to avoid having to handle failure below */
 
-       snap_count = le32_to_cpu(ondisk->snap_count);
+       if (first_time) {
+               size_t len;
 
-       len = strnlen(ondisk->object_prefix, sizeof (ondisk->object_prefix));
-       header->object_prefix = kmalloc(len + 1, GFP_KERNEL);
-       if (!header->object_prefix)
-               return -ENOMEM;
-       memcpy(header->object_prefix, ondisk->object_prefix, len);
-       header->object_prefix[len] = '\0';
+               len = strnlen(ondisk->object_prefix,
+                               sizeof (ondisk->object_prefix));
+               object_prefix = kmalloc(len + 1, GFP_KERNEL);
+               if (!object_prefix)
+                       return -ENOMEM;
+               memcpy(object_prefix, ondisk->object_prefix, len);
+               object_prefix[len] = '\0';
+       }
+
+       /* Allocate the snapshot context and fill it in */
 
+       snap_count = le32_to_cpu(ondisk->snap_count);
+       snapc = ceph_create_snap_context(snap_count, GFP_KERNEL);
+       if (!snapc)
+               goto out_err;
+       snapc->seq = le64_to_cpu(ondisk->snap_seq);
        if (snap_count) {
+               struct rbd_image_snap_ondisk *snaps;
                u64 snap_names_len = le64_to_cpu(ondisk->snap_names_len);
 
-               /* Save a copy of the snapshot names */
+               /* We'll keep a copy of the snapshot names... */
 
-               if (snap_names_len > (u64) SIZE_MAX)
-                       return -EIO;
-               header->snap_names = kmalloc(snap_names_len, GFP_KERNEL);
-               if (!header->snap_names)
+               if (snap_names_len > (u64)SIZE_MAX)
+                       goto out_2big;
+               snap_names = kmalloc(snap_names_len, GFP_KERNEL);
+               if (!snap_names)
+                       goto out_err;
+
+               /* ...as well as the array of their sizes. */
+
+               size = snap_count * sizeof (*header->snap_sizes);
+               snap_sizes = kmalloc(size, GFP_KERNEL);
+               if (!snap_sizes)
                        goto out_err;
+
                /*
-                * Note that rbd_dev_v1_header_read() guarantees
-                * the ondisk buffer we're working with has
+                * Copy the names, and fill in each snapshot's id
+                * and size.
+                *
+                * Note that rbd_dev_v1_header_info() guarantees the
+                * ondisk buffer we're working with has
                 * snap_names_len bytes beyond the end of the
                 * snapshot id array, this memcpy() is safe.
                 */
-               memcpy(header->snap_names, &ondisk->snaps[snap_count],
-                       snap_names_len);
+               memcpy(snap_names, &ondisk->snaps[snap_count], snap_names_len);
+               snaps = ondisk->snaps;
+               for (i = 0; i < snap_count; i++) {
+                       snapc->snaps[i] = le64_to_cpu(snaps[i].id);
+                       snap_sizes[i] = le64_to_cpu(snaps[i].image_size);
+               }
+       }
 
-               /* Record each snapshot's size */
+       /* We won't fail any more, fill in the header */
 
-               size = snap_count * sizeof (*header->snap_sizes);
-               header->snap_sizes = kmalloc(size, GFP_KERNEL);
-               if (!header->snap_sizes)
-                       goto out_err;
-               for (i = 0; i < snap_count; i++)
-                       header->snap_sizes[i] =
-                               le64_to_cpu(ondisk->snaps[i].image_size);
+       down_write(&rbd_dev->header_rwsem);
+       if (first_time) {
+               header->object_prefix = object_prefix;
+               header->obj_order = ondisk->options.order;
+               header->crypt_type = ondisk->options.crypt_type;
+               header->comp_type = ondisk->options.comp_type;
+               /* The rest aren't used for format 1 images */
+               header->stripe_unit = 0;
+               header->stripe_count = 0;
+               header->features = 0;
        } else {
-               header->snap_names = NULL;
-               header->snap_sizes = NULL;
+               ceph_put_snap_context(header->snapc);
+               kfree(header->snap_names);
+               kfree(header->snap_sizes);
        }
 
-       header->features = 0;   /* No features support in v1 images */
-       header->obj_order = ondisk->options.order;
-       header->crypt_type = ondisk->options.crypt_type;
-       header->comp_type = ondisk->options.comp_type;
-
-       /* Allocate and fill in the snapshot context */
+       /* The remaining fields always get updated (when we refresh) */
 
        header->image_size = le64_to_cpu(ondisk->image_size);
+       header->snapc = snapc;
+       header->snap_names = snap_names;
+       header->snap_sizes = snap_sizes;
 
-       header->snapc = ceph_create_snap_context(snap_count, GFP_KERNEL);
-       if (!header->snapc)
-               goto out_err;
-       header->snapc->seq = le64_to_cpu(ondisk->snap_seq);
-       for (i = 0; i < snap_count; i++)
-               header->snapc->snaps[i] = le64_to_cpu(ondisk->snaps[i].id);
+       /* Make sure mapping size is consistent with header info */
 
-       return 0;
+       if (rbd_dev->spec->snap_id == CEPH_NOSNAP || first_time)
+               if (rbd_dev->mapping.size != header->image_size)
+                       rbd_dev->mapping.size = header->image_size;
 
+       up_write(&rbd_dev->header_rwsem);
+
+       return 0;
+out_2big:
+       ret = -EIO;
 out_err:
-       kfree(header->snap_sizes);
-       header->snap_sizes = NULL;
-       kfree(header->snap_names);
-       header->snap_names = NULL;
-       kfree(header->object_prefix);
-       header->object_prefix = NULL;
+       kfree(snap_sizes);
+       kfree(snap_names);
+       ceph_put_snap_context(snapc);
+       kfree(object_prefix);
 
-       return -ENOMEM;
+       return ret;
 }
 
 static const char *_rbd_dev_v1_snap_name(struct rbd_device *rbd_dev, u32 which)
@@ -934,20 +1007,11 @@ static int rbd_snap_features(struct rbd_device *rbd_dev, u64 snap_id,
 
 static int rbd_dev_mapping_set(struct rbd_device *rbd_dev)
 {
-       const char *snap_name = rbd_dev->spec->snap_name;
-       u64 snap_id;
+       u64 snap_id = rbd_dev->spec->snap_id;
        u64 size = 0;
        u64 features = 0;
        int ret;
 
-       if (strcmp(snap_name, RBD_SNAP_HEAD_NAME)) {
-               snap_id = rbd_snap_id_by_name(rbd_dev, snap_name);
-               if (snap_id == CEPH_NOSNAP)
-                       return -ENOENT;
-       } else {
-               snap_id = CEPH_NOSNAP;
-       }
-
        ret = rbd_snap_size(rbd_dev, snap_id, &size);
        if (ret)
                return ret;
@@ -958,11 +1022,6 @@ static int rbd_dev_mapping_set(struct rbd_device *rbd_dev)
        rbd_dev->mapping.size = size;
        rbd_dev->mapping.features = features;
 
-       /* If we are mapping a snapshot it must be marked read-only */
-
-       if (snap_id != CEPH_NOSNAP)
-               rbd_dev->mapping.read_only = true;
-
        return 0;
 }
 
@@ -970,14 +1029,6 @@ static void rbd_dev_mapping_clear(struct rbd_device *rbd_dev)
 {
        rbd_dev->mapping.size = 0;
        rbd_dev->mapping.features = 0;
-       rbd_dev->mapping.read_only = true;
-}
-
-static void rbd_dev_clear_mapping(struct rbd_device *rbd_dev)
-{
-       rbd_dev->mapping.size = 0;
-       rbd_dev->mapping.features = 0;
-       rbd_dev->mapping.read_only = true;
 }
 
 static const char *rbd_segment_name(struct rbd_device *rbd_dev, u64 offset)
@@ -1342,20 +1393,18 @@ static void rbd_obj_request_put(struct rbd_obj_request *obj_request)
        kref_put(&obj_request->kref, rbd_obj_request_destroy);
 }
 
-static void rbd_img_request_get(struct rbd_img_request *img_request)
-{
-       dout("%s: img %p (was %d)\n", __func__, img_request,
-               atomic_read(&img_request->kref.refcount));
-       kref_get(&img_request->kref);
-}
-
+static bool img_request_child_test(struct rbd_img_request *img_request);
+static void rbd_parent_request_destroy(struct kref *kref);
 static void rbd_img_request_destroy(struct kref *kref);
 static void rbd_img_request_put(struct rbd_img_request *img_request)
 {
        rbd_assert(img_request != NULL);
        dout("%s: img %p (was %d)\n", __func__, img_request,
                atomic_read(&img_request->kref.refcount));
-       kref_put(&img_request->kref, rbd_img_request_destroy);
+       if (img_request_child_test(img_request))
+               kref_put(&img_request->kref, rbd_parent_request_destroy);
+       else
+               kref_put(&img_request->kref, rbd_img_request_destroy);
 }
 
 static inline void rbd_img_obj_request_add(struct rbd_img_request *img_request,
@@ -1472,6 +1521,12 @@ static void img_request_child_set(struct rbd_img_request *img_request)
        smp_mb();
 }
 
+static void img_request_child_clear(struct rbd_img_request *img_request)
+{
+       clear_bit(IMG_REQ_CHILD, &img_request->flags);
+       smp_mb();
+}
+
 static bool img_request_child_test(struct rbd_img_request *img_request)
 {
        smp_mb();
@@ -1484,6 +1539,12 @@ static void img_request_layered_set(struct rbd_img_request *img_request)
        smp_mb();
 }
 
+static void img_request_layered_clear(struct rbd_img_request *img_request)
+{
+       clear_bit(IMG_REQ_LAYERED, &img_request->flags);
+       smp_mb();
+}
+
 static bool img_request_layered_test(struct rbd_img_request *img_request)
 {
        smp_mb();
@@ -1827,6 +1888,74 @@ static void rbd_obj_request_destroy(struct kref *kref)
        kmem_cache_free(rbd_obj_request_cache, obj_request);
 }
 
+/* It's OK to call this for a device with no parent */
+
+static void rbd_spec_put(struct rbd_spec *spec);
+static void rbd_dev_unparent(struct rbd_device *rbd_dev)
+{
+       rbd_dev_remove_parent(rbd_dev);
+       rbd_spec_put(rbd_dev->parent_spec);
+       rbd_dev->parent_spec = NULL;
+       rbd_dev->parent_overlap = 0;
+}
+
+/*
+ * Parent image reference counting is used to determine when an
+ * image's parent fields can be safely torn down--after there are no
+ * more in-flight requests to the parent image.  When the last
+ * reference is dropped, cleaning them up is safe.
+ */
+static void rbd_dev_parent_put(struct rbd_device *rbd_dev)
+{
+       int counter;
+
+       if (!rbd_dev->parent_spec)
+               return;
+
+       counter = atomic_dec_return_safe(&rbd_dev->parent_ref);
+       if (counter > 0)
+               return;
+
+       /* Last reference; clean up parent data structures */
+
+       if (!counter)
+               rbd_dev_unparent(rbd_dev);
+       else
+               rbd_warn(rbd_dev, "parent reference underflow\n");
+}
+
+/*
+ * If an image has a non-zero parent overlap, get a reference to its
+ * parent.
+ *
+ * We must get the reference before checking for the overlap to
+ * coordinate properly with zeroing the parent overlap in
+ * rbd_dev_v2_parent_info() when an image gets flattened.  We
+ * drop it again if there is no overlap.
+ *
+ * Returns true if the rbd device has a parent with a non-zero
+ * overlap and a reference for it was successfully taken, or
+ * false otherwise.
+ */
+static bool rbd_dev_parent_get(struct rbd_device *rbd_dev)
+{
+       int counter;
+
+       if (!rbd_dev->parent_spec)
+               return false;
+
+       counter = atomic_inc_return_safe(&rbd_dev->parent_ref);
+       if (counter > 0 && rbd_dev->parent_overlap)
+               return true;
+
+       /* Image was flattened, but parent is not yet torn down */
+
+       if (counter < 0)
+               rbd_warn(rbd_dev, "parent reference overflow\n");
+
+       return false;
+}
+
 /*
  * Caller is responsible for filling in the list of object requests
  * that comprises the image request, and the Linux request pointer
@@ -1835,8 +1964,7 @@ static void rbd_obj_request_destroy(struct kref *kref)
 static struct rbd_img_request *rbd_img_request_create(
                                        struct rbd_device *rbd_dev,
                                        u64 offset, u64 length,
-                                       bool write_request,
-                                       bool child_request)
+                                       bool write_request)
 {
        struct rbd_img_request *img_request;
 
@@ -1861,9 +1989,7 @@ static struct rbd_img_request *rbd_img_request_create(
        } else {
                img_request->snap_id = rbd_dev->spec->snap_id;
        }
-       if (child_request)
-               img_request_child_set(img_request);
-       if (rbd_dev->parent_spec)
+       if (rbd_dev_parent_get(rbd_dev))
                img_request_layered_set(img_request);
        spin_lock_init(&img_request->completion_lock);
        img_request->next_completion = 0;
@@ -1873,9 +1999,6 @@ static struct rbd_img_request *rbd_img_request_create(
        INIT_LIST_HEAD(&img_request->obj_requests);
        kref_init(&img_request->kref);
 
-       rbd_img_request_get(img_request);       /* Avoid a warning */
-       rbd_img_request_put(img_request);       /* TEMPORARY */
-
        dout("%s: rbd_dev %p %s %llu/%llu -> img %p\n", __func__, rbd_dev,
                write_request ? "write" : "read", offset, length,
                img_request);
@@ -1897,15 +2020,54 @@ static void rbd_img_request_destroy(struct kref *kref)
                rbd_img_obj_request_del(img_request, obj_request);
        rbd_assert(img_request->obj_request_count == 0);
 
+       if (img_request_layered_test(img_request)) {
+               img_request_layered_clear(img_request);
+               rbd_dev_parent_put(img_request->rbd_dev);
+       }
+
        if (img_request_write_test(img_request))
                ceph_put_snap_context(img_request->snapc);
 
-       if (img_request_child_test(img_request))
-               rbd_obj_request_put(img_request->obj_request);
-
        kmem_cache_free(rbd_img_request_cache, img_request);
 }
 
+static struct rbd_img_request *rbd_parent_request_create(
+                                       struct rbd_obj_request *obj_request,
+                                       u64 img_offset, u64 length)
+{
+       struct rbd_img_request *parent_request;
+       struct rbd_device *rbd_dev;
+
+       rbd_assert(obj_request->img_request);
+       rbd_dev = obj_request->img_request->rbd_dev;
+
+       parent_request = rbd_img_request_create(rbd_dev->parent,
+                                               img_offset, length, false);
+       if (!parent_request)
+               return NULL;
+
+       img_request_child_set(parent_request);
+       rbd_obj_request_get(obj_request);
+       parent_request->obj_request = obj_request;
+
+       return parent_request;
+}
+
+static void rbd_parent_request_destroy(struct kref *kref)
+{
+       struct rbd_img_request *parent_request;
+       struct rbd_obj_request *orig_request;
+
+       parent_request = container_of(kref, struct rbd_img_request, kref);
+       orig_request = parent_request->obj_request;
+
+       parent_request->obj_request = NULL;
+       rbd_obj_request_put(orig_request);
+       img_request_child_clear(parent_request);
+
+       rbd_img_request_destroy(kref);
+}
+
 static bool rbd_img_obj_end_request(struct rbd_obj_request *obj_request)
 {
        struct rbd_img_request *img_request;
@@ -2114,7 +2276,7 @@ rbd_img_obj_copyup_callback(struct rbd_obj_request *obj_request)
 {
        struct rbd_img_request *img_request;
        struct rbd_device *rbd_dev;
-       u64 length;
+       struct page **pages;
        u32 page_count;
 
        rbd_assert(obj_request->type == OBJ_REQUEST_BIO);
@@ -2124,12 +2286,14 @@ rbd_img_obj_copyup_callback(struct rbd_obj_request *obj_request)
 
        rbd_dev = img_request->rbd_dev;
        rbd_assert(rbd_dev);
-       length = (u64)1 << rbd_dev->header.obj_order;
-       page_count = (u32)calc_pages_for(0, length);
 
-       rbd_assert(obj_request->copyup_pages);
-       ceph_release_page_vector(obj_request->copyup_pages, page_count);
+       pages = obj_request->copyup_pages;
+       rbd_assert(pages != NULL);
        obj_request->copyup_pages = NULL;
+       page_count = obj_request->copyup_page_count;
+       rbd_assert(page_count);
+       obj_request->copyup_page_count = 0;
+       ceph_release_page_vector(pages, page_count);
 
        /*
         * We want the transfer count to reflect the size of the
@@ -2153,9 +2317,11 @@ rbd_img_obj_parent_read_full_callback(struct rbd_img_request *img_request)
        struct ceph_osd_client *osdc;
        struct rbd_device *rbd_dev;
        struct page **pages;
-       int result;
-       u64 obj_size;
-       u64 xferred;
+       u32 page_count;
+       int img_result;
+       u64 parent_length;
+       u64 offset;
+       u64 length;
 
        rbd_assert(img_request_child_test(img_request));
 
@@ -2164,46 +2330,74 @@ rbd_img_obj_parent_read_full_callback(struct rbd_img_request *img_request)
        pages = img_request->copyup_pages;
        rbd_assert(pages != NULL);
        img_request->copyup_pages = NULL;
+       page_count = img_request->copyup_page_count;
+       rbd_assert(page_count);
+       img_request->copyup_page_count = 0;
 
        orig_request = img_request->obj_request;
        rbd_assert(orig_request != NULL);
-       rbd_assert(orig_request->type == OBJ_REQUEST_BIO);
-       result = img_request->result;
-       obj_size = img_request->length;
-       xferred = img_request->xferred;
+       rbd_assert(obj_request_type_valid(orig_request->type));
+       img_result = img_request->result;
+       parent_length = img_request->length;
+       rbd_assert(parent_length == img_request->xferred);
+       rbd_img_request_put(img_request);
 
-       rbd_dev = img_request->rbd_dev;
+       rbd_assert(orig_request->img_request);
+       rbd_dev = orig_request->img_request->rbd_dev;
        rbd_assert(rbd_dev);
-       rbd_assert(obj_size == (u64)1 << rbd_dev->header.obj_order);
 
-       rbd_img_request_put(img_request);
+       /*
+        * If the overlap has become 0 (most likely because the
+        * image has been flattened) we need to free the pages
+        * and re-submit the original write request.
+        */
+       if (!rbd_dev->parent_overlap) {
+               struct ceph_osd_client *osdc;
 
-       if (result)
-               goto out_err;
+               ceph_release_page_vector(pages, page_count);
+               osdc = &rbd_dev->rbd_client->client->osdc;
+               img_result = rbd_obj_request_submit(osdc, orig_request);
+               if (!img_result)
+                       return;
+       }
 
-       /* Allocate the new copyup osd request for the original request */
+       if (img_result)
+               goto out_err;
 
-       result = -ENOMEM;
-       rbd_assert(!orig_request->osd_req);
+       /*
+        * The original osd request is of no use to use any more.
+        * We need a new one that can hold the two ops in a copyup
+        * request.  Allocate the new copyup osd request for the
+        * original request, and release the old one.
+        */
+       img_result = -ENOMEM;
        osd_req = rbd_osd_req_create_copyup(orig_request);
        if (!osd_req)
                goto out_err;
+       rbd_osd_req_destroy(orig_request->osd_req);
        orig_request->osd_req = osd_req;
        orig_request->copyup_pages = pages;
+       orig_request->copyup_page_count = page_count;
 
        /* Initialize the copyup op */
 
        osd_req_op_cls_init(osd_req, 0, CEPH_OSD_OP_CALL, "rbd", "copyup");
-       osd_req_op_cls_request_data_pages(osd_req, 0, pages, obj_size, 0,
+       osd_req_op_cls_request_data_pages(osd_req, 0, pages, parent_length, 0,
                                                false, false);
 
        /* Then the original write request op */
 
+       offset = orig_request->offset;
+       length = orig_request->length;
        osd_req_op_extent_init(osd_req, 1, CEPH_OSD_OP_WRITE,
-                                       orig_request->offset,
-                                       orig_request->length, 0, 0);
-       osd_req_op_extent_osd_data_bio(osd_req, 1, orig_request->bio_list,
-                                       orig_request->length);
+                                       offset, length, 0, 0);
+       if (orig_request->type == OBJ_REQUEST_BIO)
+               osd_req_op_extent_osd_data_bio(osd_req, 1,
+                                       orig_request->bio_list, length);
+       else
+               osd_req_op_extent_osd_data_pages(osd_req, 1,
+                                       orig_request->pages, length,
+                                       offset & ~PAGE_MASK, false, false);
 
        rbd_osd_req_format_write(orig_request);
 
@@ -2211,13 +2405,13 @@ rbd_img_obj_parent_read_full_callback(struct rbd_img_request *img_request)
 
        orig_request->callback = rbd_img_obj_copyup_callback;
        osdc = &rbd_dev->rbd_client->client->osdc;
-       result = rbd_obj_request_submit(osdc, orig_request);
-       if (!result)
+       img_result = rbd_obj_request_submit(osdc, orig_request);
+       if (!img_result)
                return;
 out_err:
        /* Record the error code and complete the request */
 
-       orig_request->result = result;
+       orig_request->result = img_result;
        orig_request->xferred = 0;
        obj_request_done_set(orig_request);
        rbd_obj_request_complete(orig_request);
@@ -2249,22 +2443,13 @@ static int rbd_img_obj_parent_read_full(struct rbd_obj_request *obj_request)
        int result;
 
        rbd_assert(obj_request_img_data_test(obj_request));
-       rbd_assert(obj_request->type == OBJ_REQUEST_BIO);
+       rbd_assert(obj_request_type_valid(obj_request->type));
 
        img_request = obj_request->img_request;
        rbd_assert(img_request != NULL);
        rbd_dev = img_request->rbd_dev;
        rbd_assert(rbd_dev->parent != NULL);
 
-       /*
-        * First things first.  The original osd request is of no
-        * use to use any more, we'll need a new one that can hold
-        * the two ops in a copyup request.  We'll get that later,
-        * but for now we can release the old one.
-        */
-       rbd_osd_req_destroy(obj_request->osd_req);
-       obj_request->osd_req = NULL;
-
        /*
         * Determine the byte range covered by the object in the
         * child image to which the original request was to be sent.
@@ -2295,18 +2480,16 @@ static int rbd_img_obj_parent_read_full(struct rbd_obj_request *obj_request)
        }
 
        result = -ENOMEM;
-       parent_request = rbd_img_request_create(rbd_dev->parent,
-                                               img_offset, length,
-                                               false, true);
+       parent_request = rbd_parent_request_create(obj_request,
+                                               img_offset, length);
        if (!parent_request)
                goto out_err;
-       rbd_obj_request_get(obj_request);
-       parent_request->obj_request = obj_request;
 
        result = rbd_img_request_fill(parent_request, OBJ_REQUEST_PAGES, pages);
        if (result)
                goto out_err;
        parent_request->copyup_pages = pages;
+       parent_request->copyup_page_count = page_count;
 
        parent_request->callback = rbd_img_obj_parent_read_full_callback;
        result = rbd_img_request_submit(parent_request);
@@ -2314,6 +2497,7 @@ static int rbd_img_obj_parent_read_full(struct rbd_obj_request *obj_request)
                return 0;
 
        parent_request->copyup_pages = NULL;
+       parent_request->copyup_page_count = 0;
        parent_request->obj_request = NULL;
        rbd_obj_request_put(obj_request);
 out_err:
@@ -2331,6 +2515,7 @@ out_err:
 static void rbd_img_obj_exists_callback(struct rbd_obj_request *obj_request)
 {
        struct rbd_obj_request *orig_request;
+       struct rbd_device *rbd_dev;
        int result;
 
        rbd_assert(!obj_request_img_data_test(obj_request));
@@ -2353,8 +2538,21 @@ static void rbd_img_obj_exists_callback(struct rbd_obj_request *obj_request)
                obj_request->xferred, obj_request->length);
        rbd_obj_request_put(obj_request);
 
-       rbd_assert(orig_request);
-       rbd_assert(orig_request->img_request);
+       /*
+        * If the overlap has become 0 (most likely because the
+        * image has been flattened) we need to free the pages
+        * and re-submit the original write request.
+        */
+       rbd_dev = orig_request->img_request->rbd_dev;
+       if (!rbd_dev->parent_overlap) {
+               struct ceph_osd_client *osdc;
+
+               rbd_obj_request_put(orig_request);
+               osdc = &rbd_dev->rbd_client->client->osdc;
+               result = rbd_obj_request_submit(osdc, orig_request);
+               if (!result)
+                       return;
+       }
 
        /*
         * Our only purpose here is to determine whether the object
@@ -2512,14 +2710,36 @@ static void rbd_img_parent_read_callback(struct rbd_img_request *img_request)
        struct rbd_obj_request *obj_request;
        struct rbd_device *rbd_dev;
        u64 obj_end;
+       u64 img_xferred;
+       int img_result;
 
        rbd_assert(img_request_child_test(img_request));
 
+       /* First get what we need from the image request and release it */
+
        obj_request = img_request->obj_request;
+       img_xferred = img_request->xferred;
+       img_result = img_request->result;
+       rbd_img_request_put(img_request);
+
+       /*
+        * If the overlap has become 0 (most likely because the
+        * image has been flattened) we need to re-submit the
+        * original request.
+        */
        rbd_assert(obj_request);
        rbd_assert(obj_request->img_request);
+       rbd_dev = obj_request->img_request->rbd_dev;
+       if (!rbd_dev->parent_overlap) {
+               struct ceph_osd_client *osdc;
 
-       obj_request->result = img_request->result;
+               osdc = &rbd_dev->rbd_client->client->osdc;
+               img_result = rbd_obj_request_submit(osdc, obj_request);
+               if (!img_result)
+                       return;
+       }
+
+       obj_request->result = img_result;
        if (obj_request->result)
                goto out;
 
@@ -2532,7 +2752,6 @@ static void rbd_img_parent_read_callback(struct rbd_img_request *img_request)
         */
        rbd_assert(obj_request->img_offset < U64_MAX - obj_request->length);
        obj_end = obj_request->img_offset + obj_request->length;
-       rbd_dev = obj_request->img_request->rbd_dev;
        if (obj_end > rbd_dev->parent_overlap) {
                u64 xferred = 0;
 
@@ -2540,43 +2759,39 @@ static void rbd_img_parent_read_callback(struct rbd_img_request *img_request)
                        xferred = rbd_dev->parent_overlap -
                                        obj_request->img_offset;
 
-               obj_request->xferred = min(img_request->xferred, xferred);
+               obj_request->xferred = min(img_xferred, xferred);
        } else {
-               obj_request->xferred = img_request->xferred;
+               obj_request->xferred = img_xferred;
        }
 out:
-       rbd_img_request_put(img_request);
        rbd_img_obj_request_read_callback(obj_request);
        rbd_obj_request_complete(obj_request);
 }
 
 static void rbd_img_parent_read(struct rbd_obj_request *obj_request)
 {
-       struct rbd_device *rbd_dev;
        struct rbd_img_request *img_request;
        int result;
 
        rbd_assert(obj_request_img_data_test(obj_request));
        rbd_assert(obj_request->img_request != NULL);
        rbd_assert(obj_request->result == (s32) -ENOENT);
-       rbd_assert(obj_request->type == OBJ_REQUEST_BIO);
+       rbd_assert(obj_request_type_valid(obj_request->type));
 
-       rbd_dev = obj_request->img_request->rbd_dev;
-       rbd_assert(rbd_dev->parent != NULL);
        /* rbd_read_finish(obj_request, obj_request->length); */
-       img_request = rbd_img_request_create(rbd_dev->parent,
+       img_request = rbd_parent_request_create(obj_request,
                                                obj_request->img_offset,
-                                               obj_request->length,
-                                               false, true);
+                                               obj_request->length);
        result = -ENOMEM;
        if (!img_request)
                goto out_err;
 
-       rbd_obj_request_get(obj_request);
-       img_request->obj_request = obj_request;
-
-       result = rbd_img_request_fill(img_request, OBJ_REQUEST_BIO,
-                                       obj_request->bio_list);
+       if (obj_request->type == OBJ_REQUEST_BIO)
+               result = rbd_img_request_fill(img_request, OBJ_REQUEST_BIO,
+                                               obj_request->bio_list);
+       else
+               result = rbd_img_request_fill(img_request, OBJ_REQUEST_PAGES,
+                                               obj_request->pages);
        if (result)
                goto out_err;
 
@@ -2626,6 +2841,7 @@ out:
 static void rbd_watch_cb(u64 ver, u64 notify_id, u8 opcode, void *data)
 {
        struct rbd_device *rbd_dev = (struct rbd_device *)data;
+       int ret;
 
        if (!rbd_dev)
                return;
@@ -2633,7 +2849,9 @@ static void rbd_watch_cb(u64 ver, u64 notify_id, u8 opcode, void *data)
        dout("%s: \"%s\" notify_id %llu opcode %u\n", __func__,
                rbd_dev->header_name, (unsigned long long)notify_id,
                (unsigned int)opcode);
-       (void)rbd_dev_refresh(rbd_dev);
+       ret = rbd_dev_refresh(rbd_dev);
+       if (ret)
+               rbd_warn(rbd_dev, ": header refresh error (%d)\n", ret);
 
        rbd_obj_notify_ack(rbd_dev, notify_id);
 }
@@ -2642,7 +2860,7 @@ static void rbd_watch_cb(u64 ver, u64 notify_id, u8 opcode, void *data)
  * Request sync osd watch/unwatch.  The value of "start" determines
  * whether a watch request is being initiated or torn down.
  */
-static int rbd_dev_header_watch_sync(struct rbd_device *rbd_dev, int start)
+static int rbd_dev_header_watch_sync(struct rbd_device *rbd_dev, bool start)
 {
        struct ceph_osd_client *osdc = &rbd_dev->rbd_client->client->osdc;
        struct rbd_obj_request *obj_request;
@@ -2676,7 +2894,7 @@ static int rbd_dev_header_watch_sync(struct rbd_device *rbd_dev, int start)
                                        rbd_dev->watch_request->osd_req);
 
        osd_req_op_watch_init(obj_request->osd_req, 0, CEPH_OSD_OP_WATCH,
-                               rbd_dev->watch_event->cookie, 0, start);
+                               rbd_dev->watch_event->cookie, 0, start ? 1 : 0);
        rbd_osd_req_format_write(obj_request);
 
        ret = rbd_obj_request_submit(osdc, obj_request);
@@ -2869,9 +3087,16 @@ static void rbd_request_fn(struct request_queue *q)
                        goto end_request;       /* Shouldn't happen */
                }
 
+               result = -EIO;
+               if (offset + length > rbd_dev->mapping.size) {
+                       rbd_warn(rbd_dev, "beyond EOD (%llu~%llu > %llu)\n",
+                               offset, length, rbd_dev->mapping.size);
+                       goto end_request;
+               }
+
                result = -ENOMEM;
                img_request = rbd_img_request_create(rbd_dev, offset, length,
-                                                       write_request, false);
+                                                       write_request);
                if (!img_request)
                        goto end_request;
 
@@ -3022,17 +3247,11 @@ out:
 }
 
 /*
- * Read the complete header for the given rbd device.
- *
- * Returns a pointer to a dynamically-allocated buffer containing
- * the complete and validated header.  Caller can pass the address
- * of a variable that will be filled in with the version of the
- * header object at the time it was read.
- *
- * Returns a pointer-coded errno if a failure occurs.
+ * Read the complete header for the given rbd device.  On successful
+ * return, the rbd_dev->header field will contain up-to-date
+ * information about the image.
  */
-static struct rbd_image_header_ondisk *
-rbd_dev_v1_header_read(struct rbd_device *rbd_dev)
+static int rbd_dev_v1_header_info(struct rbd_device *rbd_dev)
 {
        struct rbd_image_header_ondisk *ondisk = NULL;
        u32 snap_count = 0;
@@ -3057,22 +3276,22 @@ rbd_dev_v1_header_read(struct rbd_device *rbd_dev)
                size += names_size;
                ondisk = kmalloc(size, GFP_KERNEL);
                if (!ondisk)
-                       return ERR_PTR(-ENOMEM);
+                       return -ENOMEM;
 
                ret = rbd_obj_read_sync(rbd_dev, rbd_dev->header_name,
                                       0, size, ondisk);
                if (ret < 0)
-                       goto out_err;
+                       goto out;
                if ((size_t)ret < size) {
                        ret = -ENXIO;
                        rbd_warn(rbd_dev, "short header read (want %zd got %d)",
                                size, ret);
-                       goto out_err;
+                       goto out;
                }
                if (!rbd_dev_ondisk_valid(ondisk)) {
                        ret = -ENXIO;
                        rbd_warn(rbd_dev, "invalid header");
-                       goto out_err;
+                       goto out;
                }
 
                names_size = le64_to_cpu(ondisk->snap_names_len);
@@ -3080,85 +3299,13 @@ rbd_dev_v1_header_read(struct rbd_device *rbd_dev)
                snap_count = le32_to_cpu(ondisk->snap_count);
        } while (snap_count != want_count);
 
-       return ondisk;
-
-out_err:
-       kfree(ondisk);
-
-       return ERR_PTR(ret);
-}
-
-/*
- * reload the ondisk the header
- */
-static int rbd_read_header(struct rbd_device *rbd_dev,
-                          struct rbd_image_header *header)
-{
-       struct rbd_image_header_ondisk *ondisk;
-       int ret;
-
-       ondisk = rbd_dev_v1_header_read(rbd_dev);
-       if (IS_ERR(ondisk))
-               return PTR_ERR(ondisk);
-       ret = rbd_header_from_disk(header, ondisk);
+       ret = rbd_header_from_disk(rbd_dev, ondisk);
+out:
        kfree(ondisk);
 
        return ret;
 }
 
-static void rbd_update_mapping_size(struct rbd_device *rbd_dev)
-{
-       if (rbd_dev->spec->snap_id != CEPH_NOSNAP)
-               return;
-
-       if (rbd_dev->mapping.size != rbd_dev->header.image_size) {
-               sector_t size;
-
-               rbd_dev->mapping.size = rbd_dev->header.image_size;
-               size = (sector_t)rbd_dev->mapping.size / SECTOR_SIZE;
-               dout("setting size to %llu sectors", (unsigned long long)size);
-               set_capacity(rbd_dev->disk, size);
-       }
-}
-
-/*
- * only read the first part of the ondisk header, without the snaps info
- */
-static int rbd_dev_v1_refresh(struct rbd_device *rbd_dev)
-{
-       int ret;
-       struct rbd_image_header h;
-
-       ret = rbd_read_header(rbd_dev, &h);
-       if (ret < 0)
-               return ret;
-
-       down_write(&rbd_dev->header_rwsem);
-
-       /* Update image size, and check for resize of mapped image */
-       rbd_dev->header.image_size = h.image_size;
-       rbd_update_mapping_size(rbd_dev);
-
-       /* rbd_dev->header.object_prefix shouldn't change */
-       kfree(rbd_dev->header.snap_sizes);
-       kfree(rbd_dev->header.snap_names);
-       /* osd requests may still refer to snapc */
-       ceph_put_snap_context(rbd_dev->header.snapc);
-
-       rbd_dev->header.image_size = h.image_size;
-       rbd_dev->header.snapc = h.snapc;
-       rbd_dev->header.snap_names = h.snap_names;
-       rbd_dev->header.snap_sizes = h.snap_sizes;
-       /* Free the extra copy of the object prefix */
-       if (strcmp(rbd_dev->header.object_prefix, h.object_prefix))
-               rbd_warn(rbd_dev, "object prefix changed (ignoring)");
-       kfree(h.object_prefix);
-
-       up_write(&rbd_dev->header_rwsem);
-
-       return ret;
-}
-
 /*
  * Clear the rbd device's EXISTS flag if the snapshot it's mapped to
  * has disappeared from the (just updated) snapshot context.
@@ -3180,26 +3327,29 @@ static void rbd_exists_validate(struct rbd_device *rbd_dev)
 
 static int rbd_dev_refresh(struct rbd_device *rbd_dev)
 {
-       u64 image_size;
+       u64 mapping_size;
        int ret;
 
        rbd_assert(rbd_image_format_valid(rbd_dev->image_format));
-       image_size = rbd_dev->header.image_size;
+       mapping_size = rbd_dev->mapping.size;
        mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
        if (rbd_dev->image_format == 1)
-               ret = rbd_dev_v1_refresh(rbd_dev);
+               ret = rbd_dev_v1_header_info(rbd_dev);
        else
-               ret = rbd_dev_v2_refresh(rbd_dev);
+               ret = rbd_dev_v2_header_info(rbd_dev);
 
        /* If it's a mapped snapshot, validate its EXISTS flag */
 
        rbd_exists_validate(rbd_dev);
        mutex_unlock(&ctl_mutex);
-       if (ret)
-               rbd_warn(rbd_dev, "got notification but failed to "
-                          " update snaps: %d\n", ret);
-       if (image_size != rbd_dev->header.image_size)
+       if (mapping_size != rbd_dev->mapping.size) {
+               sector_t size;
+
+               size = (sector_t)rbd_dev->mapping.size / SECTOR_SIZE;
+               dout("setting size to %llu sectors", (unsigned long long)size);
+               set_capacity(rbd_dev->disk, size);
                revalidate_disk(rbd_dev->disk);
+       }
 
        return ret;
 }
@@ -3403,6 +3553,8 @@ static ssize_t rbd_image_refresh(struct device *dev,
        int ret;
 
        ret = rbd_dev_refresh(rbd_dev);
+       if (ret)
+               rbd_warn(rbd_dev, ": manual header refresh error (%d)\n", ret);
 
        return ret < 0 ? ret : size;
 }
@@ -3501,6 +3653,7 @@ static struct rbd_device *rbd_dev_create(struct rbd_client *rbdc,
 
        spin_lock_init(&rbd_dev->lock);
        rbd_dev->flags = 0;
+       atomic_set(&rbd_dev->parent_ref, 0);
        INIT_LIST_HEAD(&rbd_dev->node);
        init_rwsem(&rbd_dev->header_rwsem);
 
@@ -3650,6 +3803,7 @@ static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev)
        __le64 snapid;
        void *p;
        void *end;
+       u64 pool_id;
        char *image_id;
        u64 overlap;
        int ret;
@@ -3680,18 +3834,37 @@ static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev)
        p = reply_buf;
        end = reply_buf + ret;
        ret = -ERANGE;
-       ceph_decode_64_safe(&p, end, parent_spec->pool_id, out_err);
-       if (parent_spec->pool_id == CEPH_NOPOOL)
+       ceph_decode_64_safe(&p, end, pool_id, out_err);
+       if (pool_id == CEPH_NOPOOL) {
+               /*
+                * Either the parent never existed, or we have
+                * record of it but the image got flattened so it no
+                * longer has a parent.  When the parent of a
+                * layered image disappears we immediately set the
+                * overlap to 0.  The effect of this is that all new
+                * requests will be treated as if the image had no
+                * parent.
+                */
+               if (rbd_dev->parent_overlap) {
+                       rbd_dev->parent_overlap = 0;
+                       smp_mb();
+                       rbd_dev_parent_put(rbd_dev);
+                       pr_info("%s: clone image has been flattened\n",
+                               rbd_dev->disk->disk_name);
+               }
+
                goto out;       /* No parent?  No problem. */
+       }
 
        /* The ceph file layout needs to fit pool id in 32 bits */
 
        ret = -EIO;
-       if (parent_spec->pool_id > (u64)U32_MAX) {
+       if (pool_id > (u64)U32_MAX) {
                rbd_warn(NULL, "parent pool id too large (%llu > %u)\n",
-                       (unsigned long long)parent_spec->pool_id, U32_MAX);
+                       (unsigned long long)pool_id, U32_MAX);
                goto out_err;
        }
+       parent_spec->pool_id = pool_id;
 
        image_id = ceph_extract_encoded_string(&p, end, NULL, GFP_KERNEL);
        if (IS_ERR(image_id)) {
@@ -3702,9 +3875,14 @@ static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev)
        ceph_decode_64_safe(&p, end, parent_spec->snap_id, out_err);
        ceph_decode_64_safe(&p, end, overlap, out_err);
 
-       rbd_dev->parent_overlap = overlap;
-       rbd_dev->parent_spec = parent_spec;
-       parent_spec = NULL;     /* rbd_dev now owns this */
+       if (overlap) {
+               rbd_spec_put(rbd_dev->parent_spec);
+               rbd_dev->parent_spec = parent_spec;
+               parent_spec = NULL;     /* rbd_dev now owns this */
+               rbd_dev->parent_overlap = overlap;
+       } else {
+               rbd_warn(rbd_dev, "ignoring parent of clone with overlap 0\n");
+       }
 out:
        ret = 0;
 out_err:
@@ -4002,6 +4180,7 @@ static int rbd_dev_v2_snap_context(struct rbd_device *rbd_dev)
        for (i = 0; i < snap_count; i++)
                snapc->snaps[i] = ceph_decode_64(&p);
 
+       ceph_put_snap_context(rbd_dev->header.snapc);
        rbd_dev->header.snapc = snapc;
 
        dout("  snap context seq = %llu, snap_count = %u\n",
@@ -4053,21 +4232,56 @@ out:
        return snap_name;
 }
 
-static int rbd_dev_v2_refresh(struct rbd_device *rbd_dev)
+static int rbd_dev_v2_header_info(struct rbd_device *rbd_dev)
 {
+       bool first_time = rbd_dev->header.object_prefix == NULL;
        int ret;
 
        down_write(&rbd_dev->header_rwsem);
 
+       if (first_time) {
+               ret = rbd_dev_v2_header_onetime(rbd_dev);
+               if (ret)
+                       goto out;
+       }
+
+       /*
+        * If the image supports layering, get the parent info.  We
+        * need to probe the first time regardless.  Thereafter we
+        * only need to if there's a parent, to see if it has
+        * disappeared due to the mapped image getting flattened.
+        */
+       if (rbd_dev->header.features & RBD_FEATURE_LAYERING &&
+                       (first_time || rbd_dev->parent_spec)) {
+               bool warn;
+
+               ret = rbd_dev_v2_parent_info(rbd_dev);
+               if (ret)
+                       goto out;
+
+               /*
+                * Print a warning if this is the initial probe and
+                * the image has a parent.  Don't print it if the
+                * image now being probed is itself a parent.  We
+                * can tell at this point because we won't know its
+                * pool name yet (just its pool id).
+                */
+               warn = rbd_dev->parent_spec && rbd_dev->spec->pool_name;
+               if (first_time && warn)
+                       rbd_warn(rbd_dev, "WARNING: kernel layering "
+                                       "is EXPERIMENTAL!");
+       }
+
        ret = rbd_dev_v2_image_size(rbd_dev);
        if (ret)
                goto out;
-       rbd_update_mapping_size(rbd_dev);
+
+       if (rbd_dev->spec->snap_id == CEPH_NOSNAP)
+               if (rbd_dev->mapping.size != rbd_dev->header.image_size)
+                       rbd_dev->mapping.size = rbd_dev->header.image_size;
 
        ret = rbd_dev_v2_snap_context(rbd_dev);
        dout("rbd_dev_v2_snap_context returned %d\n", ret);
-       if (ret)
-               goto out;
 out:
        up_write(&rbd_dev->header_rwsem);
 
@@ -4484,16 +4698,18 @@ out:
        return ret;
 }
 
-/* Undo whatever state changes are made by v1 or v2 image probe */
-
+/*
+ * Undo whatever state changes are made by v1 or v2 header info
+ * call.
+ */
 static void rbd_dev_unprobe(struct rbd_device *rbd_dev)
 {
        struct rbd_image_header *header;
 
-       rbd_dev_remove_parent(rbd_dev);
-       rbd_spec_put(rbd_dev->parent_spec);
-       rbd_dev->parent_spec = NULL;
-       rbd_dev->parent_overlap = 0;
+       /* Drop parent reference unless it's already been done (or none) */
+
+       if (rbd_dev->parent_overlap)
+               rbd_dev_parent_put(rbd_dev);
 
        /* Free dynamic fields from the header, then zero it out */
 
@@ -4505,72 +4721,22 @@ static void rbd_dev_unprobe(struct rbd_device *rbd_dev)
        memset(header, 0, sizeof (*header));
 }
 
-static int rbd_dev_v1_probe(struct rbd_device *rbd_dev)
+static int rbd_dev_v2_header_onetime(struct rbd_device *rbd_dev)
 {
        int ret;
 
-       /* Populate rbd image metadata */
-
-       ret = rbd_read_header(rbd_dev, &rbd_dev->header);
-       if (ret < 0)
-               goto out_err;
-
-       /* Version 1 images have no parent (no layering) */
-
-       rbd_dev->parent_spec = NULL;
-       rbd_dev->parent_overlap = 0;
-
-       dout("discovered version 1 image, header name is %s\n",
-               rbd_dev->header_name);
-
-       return 0;
-
-out_err:
-       kfree(rbd_dev->header_name);
-       rbd_dev->header_name = NULL;
-       kfree(rbd_dev->spec->image_id);
-       rbd_dev->spec->image_id = NULL;
-
-       return ret;
-}
-
-static int rbd_dev_v2_probe(struct rbd_device *rbd_dev)
-{
-       int ret;
-
-       ret = rbd_dev_v2_image_size(rbd_dev);
-       if (ret)
-               goto out_err;
-
-       /* Get the object prefix (a.k.a. block_name) for the image */
-
        ret = rbd_dev_v2_object_prefix(rbd_dev);
        if (ret)
                goto out_err;
 
-       /* Get the and check features for the image */
-
+       /*
+        * Get the and check features for the image.  Currently the
+        * features are assumed to never change.
+        */
        ret = rbd_dev_v2_features(rbd_dev);
        if (ret)
                goto out_err;
 
-       /* If the image supports layering, get the parent info */
-
-       if (rbd_dev->header.features & RBD_FEATURE_LAYERING) {
-               ret = rbd_dev_v2_parent_info(rbd_dev);
-               if (ret)
-                       goto out_err;
-
-               /*
-                * Don't print a warning for parent images.  We can
-                * tell this point because we won't know its pool
-                * name yet (just its pool id).
-                */
-               if (rbd_dev->spec->pool_name)
-                       rbd_warn(rbd_dev, "WARNING: kernel layering "
-                                       "is EXPERIMENTAL!");
-       }
-
        /* If the image supports fancy striping, get its parameters */
 
        if (rbd_dev->header.features & RBD_FEATURE_STRIPINGV2) {
@@ -4578,28 +4744,11 @@ static int rbd_dev_v2_probe(struct rbd_device *rbd_dev)
                if (ret < 0)
                        goto out_err;
        }
-
-       /* crypto and compression type aren't (yet) supported for v2 images */
-
-       rbd_dev->header.crypt_type = 0;
-       rbd_dev->header.comp_type = 0;
-
-       /* Get the snapshot context, plus the header version */
-
-       ret = rbd_dev_v2_snap_context(rbd_dev);
-       if (ret)
-               goto out_err;
-
-       dout("discovered version 2 image, header name is %s\n",
-               rbd_dev->header_name);
+       /* No support for crypto and compression type format 2 images */
 
        return 0;
 out_err:
-       rbd_dev->parent_overlap = 0;
-       rbd_spec_put(rbd_dev->parent_spec);
-       rbd_dev->parent_spec = NULL;
-       kfree(rbd_dev->header_name);
-       rbd_dev->header_name = NULL;
+       rbd_dev->header.features = 0;
        kfree(rbd_dev->header.object_prefix);
        rbd_dev->header.object_prefix = NULL;
 
@@ -4628,15 +4777,16 @@ static int rbd_dev_probe_parent(struct rbd_device *rbd_dev)
        if (!parent)
                goto out_err;
 
-       ret = rbd_dev_image_probe(parent);
+       ret = rbd_dev_image_probe(parent, false);
        if (ret < 0)
                goto out_err;
        rbd_dev->parent = parent;
+       atomic_set(&rbd_dev->parent_ref, 1);
 
        return 0;
 out_err:
        if (parent) {
-               rbd_spec_put(rbd_dev->parent_spec);
+               rbd_dev_unparent(rbd_dev);
                kfree(rbd_dev->header_name);
                rbd_dev_destroy(parent);
        } else {
@@ -4651,10 +4801,6 @@ static int rbd_dev_device_setup(struct rbd_device *rbd_dev)
 {
        int ret;
 
-       ret = rbd_dev_mapping_set(rbd_dev);
-       if (ret)
-               return ret;
-
        /* generate unique id: find highest unique id, add one */
        rbd_dev_id_get(rbd_dev);
 
@@ -4676,13 +4822,17 @@ static int rbd_dev_device_setup(struct rbd_device *rbd_dev)
        if (ret)
                goto err_out_blkdev;
 
-       ret = rbd_bus_add_dev(rbd_dev);
+       ret = rbd_dev_mapping_set(rbd_dev);
        if (ret)
                goto err_out_disk;
+       set_capacity(rbd_dev->disk, rbd_dev->mapping.size / SECTOR_SIZE);
+
+       ret = rbd_bus_add_dev(rbd_dev);
+       if (ret)
+               goto err_out_mapping;
 
        /* Everything's ready.  Announce the disk to the world. */
 
-       set_capacity(rbd_dev->disk, rbd_dev->mapping.size / SECTOR_SIZE);
        set_bit(RBD_DEV_FLAG_EXISTS, &rbd_dev->flags);
        add_disk(rbd_dev->disk);
 
@@ -4691,6 +4841,8 @@ static int rbd_dev_device_setup(struct rbd_device *rbd_dev)
 
        return ret;
 
+err_out_mapping:
+       rbd_dev_mapping_clear(rbd_dev);
 err_out_disk:
        rbd_free_disk(rbd_dev);
 err_out_blkdev:
@@ -4731,12 +4883,7 @@ static int rbd_dev_header_name(struct rbd_device *rbd_dev)
 
 static void rbd_dev_image_release(struct rbd_device *rbd_dev)
 {
-       int ret;
-
        rbd_dev_unprobe(rbd_dev);
-       ret = rbd_dev_header_watch_sync(rbd_dev, 0);
-       if (ret)
-               rbd_warn(rbd_dev, "failed to cancel watch event (%d)\n", ret);
        kfree(rbd_dev->header_name);
        rbd_dev->header_name = NULL;
        rbd_dev->image_format = 0;
@@ -4748,18 +4895,20 @@ static void rbd_dev_image_release(struct rbd_device *rbd_dev)
 
 /*
  * Probe for the existence of the header object for the given rbd
- * device.  For format 2 images this includes determining the image
- * id.
+ * device.  If this image is the one being mapped (i.e., not a
+ * parent), initiate a watch on its header object before using that
+ * object to get detailed information about the rbd image.
  */
-static int rbd_dev_image_probe(struct rbd_device *rbd_dev)
+static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping)
 {
        int ret;
        int tmp;
 
        /*
-        * Get the id from the image id object.  If it's not a
-        * format 2 image, we'll get ENOENT back, and we'll assume
-        * it's a format 1 image.
+        * Get the id from the image id object.  Unless there's an
+        * error, rbd_dev->spec->image_id will be filled in with
+        * a dynamically-allocated string, and rbd_dev->image_format
+        * will be set to either 1 or 2.
         */
        ret = rbd_dev_image_id(rbd_dev);
        if (ret)
@@ -4771,14 +4920,16 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev)
        if (ret)
                goto err_out_format;
 
-       ret = rbd_dev_header_watch_sync(rbd_dev, 1);
-       if (ret)
-               goto out_header_name;
+       if (mapping) {
+               ret = rbd_dev_header_watch_sync(rbd_dev, true);
+               if (ret)
+                       goto out_header_name;
+       }
 
        if (rbd_dev->image_format == 1)
-               ret = rbd_dev_v1_probe(rbd_dev);
+               ret = rbd_dev_v1_header_info(rbd_dev);
        else
-               ret = rbd_dev_v2_probe(rbd_dev);
+               ret = rbd_dev_v2_header_info(rbd_dev);
        if (ret)
                goto err_out_watch;
 
@@ -4787,15 +4938,22 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev)
                goto err_out_probe;
 
        ret = rbd_dev_probe_parent(rbd_dev);
-       if (!ret)
-               return 0;
+       if (ret)
+               goto err_out_probe;
+
+       dout("discovered format %u image, header name is %s\n",
+               rbd_dev->image_format, rbd_dev->header_name);
 
+       return 0;
 err_out_probe:
        rbd_dev_unprobe(rbd_dev);
 err_out_watch:
-       tmp = rbd_dev_header_watch_sync(rbd_dev, 0);
-       if (tmp)
-               rbd_warn(rbd_dev, "unable to tear down watch request\n");
+       if (mapping) {
+               tmp = rbd_dev_header_watch_sync(rbd_dev, false);
+               if (tmp)
+                       rbd_warn(rbd_dev, "unable to tear down "
+                                       "watch request (%d)\n", tmp);
+       }
 out_header_name:
        kfree(rbd_dev->header_name);
        rbd_dev->header_name = NULL;
@@ -4819,6 +4977,7 @@ static ssize_t rbd_add(struct bus_type *bus,
        struct rbd_spec *spec = NULL;
        struct rbd_client *rbdc;
        struct ceph_osd_client *osdc;
+       bool read_only;
        int rc = -ENOMEM;
 
        if (!try_module_get(THIS_MODULE))
@@ -4828,13 +4987,15 @@ static ssize_t rbd_add(struct bus_type *bus,
        rc = rbd_add_parse_args(buf, &ceph_opts, &rbd_opts, &spec);
        if (rc < 0)
                goto err_out_module;
+       read_only = rbd_opts->read_only;
+       kfree(rbd_opts);
+       rbd_opts = NULL;        /* done with this */
 
        rbdc = rbd_get_client(ceph_opts);
        if (IS_ERR(rbdc)) {
                rc = PTR_ERR(rbdc);
                goto err_out_args;
        }
-       ceph_opts = NULL;       /* rbd_dev client now owns this */
 
        /* pick the pool */
        osdc = &rbdc->client->osdc;
@@ -4858,27 +5019,29 @@ static ssize_t rbd_add(struct bus_type *bus,
        rbdc = NULL;            /* rbd_dev now owns this */
        spec = NULL;            /* rbd_dev now owns this */
 
-       rbd_dev->mapping.read_only = rbd_opts->read_only;
-       kfree(rbd_opts);
-       rbd_opts = NULL;        /* done with this */
-
-       rc = rbd_dev_image_probe(rbd_dev);
+       rc = rbd_dev_image_probe(rbd_dev, true);
        if (rc < 0)
                goto err_out_rbd_dev;
 
+       /* If we are mapping a snapshot it must be marked read-only */
+
+       if (rbd_dev->spec->snap_id != CEPH_NOSNAP)
+               read_only = true;
+       rbd_dev->mapping.read_only = read_only;
+
        rc = rbd_dev_device_setup(rbd_dev);
-       if (!rc)
-               return count;
+       if (rc) {
+               rbd_dev_image_release(rbd_dev);
+               goto err_out_module;
+       }
+
+       return count;
 
-       rbd_dev_image_release(rbd_dev);
 err_out_rbd_dev:
        rbd_dev_destroy(rbd_dev);
 err_out_client:
        rbd_put_client(rbdc);
 err_out_args:
-       if (ceph_opts)
-               ceph_destroy_options(ceph_opts);
-       kfree(rbd_opts);
        rbd_spec_put(spec);
 err_out_module:
        module_put(THIS_MODULE);
@@ -4911,7 +5074,7 @@ static void rbd_dev_device_release(struct device *dev)
 
        rbd_free_disk(rbd_dev);
        clear_bit(RBD_DEV_FLAG_EXISTS, &rbd_dev->flags);
-       rbd_dev_clear_mapping(rbd_dev);
+       rbd_dev_mapping_clear(rbd_dev);
        unregister_blkdev(rbd_dev->major, rbd_dev->name);
        rbd_dev->major = 0;
        rbd_dev_id_put(rbd_dev);
@@ -4978,10 +5141,13 @@ static ssize_t rbd_remove(struct bus_type *bus,
        spin_unlock_irq(&rbd_dev->lock);
        if (ret < 0)
                goto done;
-       ret = count;
        rbd_bus_del_dev(rbd_dev);
+       ret = rbd_dev_header_watch_sync(rbd_dev, false);
+       if (ret)
+               rbd_warn(rbd_dev, "failed to cancel watch event (%d)\n", ret);
        rbd_dev_image_release(rbd_dev);
        module_put(THIS_MODULE);
+       ret = count;
 done:
        mutex_unlock(&ctl_mutex);
 
index f8ef15f..3fd130f 100644 (file)
@@ -1160,8 +1160,7 @@ static int ace_probe(struct platform_device *dev)
        dev_dbg(&dev->dev, "ace_probe(%p)\n", dev);
 
        /* device id and bus width */
-       of_property_read_u32(dev->dev.of_node, "port-number", &id);
-       if (id < 0)
+       if (of_property_read_u32(dev->dev.of_node, "port-number", &id))
                id = 0;
        if (of_find_property(dev->dev.of_node, "8-bit", NULL))
                bus_width = ACE_BUS_WIDTH_8;
index fdfd61a..11a6104 100644 (file)
@@ -201,7 +201,7 @@ config BT_MRVL
          The core driver to support Marvell Bluetooth devices.
 
          This driver is required if you want to support
-         Marvell Bluetooth devices, such as 8688/8787/8797.
+         Marvell Bluetooth devices, such as 8688/8787/8797/8897.
 
          Say Y here to compile Marvell Bluetooth driver
          into the kernel or say M to compile it as module.
@@ -214,7 +214,7 @@ config BT_MRVL_SDIO
          The driver for Marvell Bluetooth chipsets with SDIO interface.
 
          This driver is required if you want to use Marvell Bluetooth
-         devices with SDIO interface. Currently SD8688/SD8787/SD8797
+         devices with SDIO interface. Currently SD8688/SD8787/SD8797/SD8897
          chipsets are supported.
 
          Say Y here to compile support for Marvell BT-over-SDIO driver
index c63488c..13693b7 100644 (file)
@@ -82,6 +82,23 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_87xx = {
        .io_port_2 = 0x7a,
 };
 
+static const struct btmrvl_sdio_card_reg btmrvl_reg_88xx = {
+       .cfg = 0x00,
+       .host_int_mask = 0x02,
+       .host_intstatus = 0x03,
+       .card_status = 0x50,
+       .sq_read_base_addr_a0 = 0x60,
+       .sq_read_base_addr_a1 = 0x61,
+       .card_revision = 0xbc,
+       .card_fw_status0 = 0xc0,
+       .card_fw_status1 = 0xc1,
+       .card_rx_len = 0xc2,
+       .card_rx_unit = 0xc3,
+       .io_port_0 = 0xd8,
+       .io_port_1 = 0xd9,
+       .io_port_2 = 0xda,
+};
+
 static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = {
        .helper         = "mrvl/sd8688_helper.bin",
        .firmware       = "mrvl/sd8688.bin",
@@ -103,6 +120,13 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8797 = {
        .sd_blksz_fw_dl = 256,
 };
 
+static const struct btmrvl_sdio_device btmrvl_sdio_sd8897 = {
+       .helper         = NULL,
+       .firmware       = "mrvl/sd8897_uapsta.bin",
+       .reg            = &btmrvl_reg_88xx,
+       .sd_blksz_fw_dl = 256,
+};
+
 static const struct sdio_device_id btmrvl_sdio_ids[] = {
        /* Marvell SD8688 Bluetooth device */
        { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x9105),
@@ -116,6 +140,9 @@ static const struct sdio_device_id btmrvl_sdio_ids[] = {
        /* Marvell SD8797 Bluetooth device */
        { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x912A),
                        .driver_data = (unsigned long) &btmrvl_sdio_sd8797 },
+       /* Marvell SD8897 Bluetooth device */
+       { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x912E),
+                       .driver_data = (unsigned long) &btmrvl_sdio_sd8897 },
 
        { }     /* Terminating entry */
 };
@@ -1194,3 +1221,4 @@ MODULE_FIRMWARE("mrvl/sd8688_helper.bin");
 MODULE_FIRMWARE("mrvl/sd8688.bin");
 MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin");
 MODULE_FIRMWARE("mrvl/sd8797_uapsta.bin");
+MODULE_FIRMWARE("mrvl/sd8897_uapsta.bin");
index 4ca35e8..19a12ac 100644 (file)
@@ -167,11 +167,6 @@ static int __init mxc_rnga_probe(struct platform_device *pdev)
        clk_prepare_enable(mxc_rng->clk);
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               err = -ENOENT;
-               goto err_region;
-       }
-
        mxc_rng->mem = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(mxc_rng->mem)) {
                err = PTR_ERR(mxc_rng->mem);
@@ -189,7 +184,6 @@ static int __init mxc_rnga_probe(struct platform_device *pdev)
        return 0;
 
 err_ioremap:
-err_region:
        clk_disable_unprepare(mxc_rng->clk);
 
 out:
index 749dc16..d2903e7 100644 (file)
@@ -119,11 +119,6 @@ static int omap_rng_probe(struct platform_device *pdev)
        dev_set_drvdata(&pdev->dev, priv);
 
        priv->mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!priv->mem_res) {
-               ret = -ENOENT;
-               goto err_ioremap;
-       }
-
        priv->base = devm_ioremap_resource(&pdev->dev, priv->mem_res);
        if (IS_ERR(priv->base)) {
                ret = PTR_ERR(priv->base);
index cdd4c09..a22a7a5 100644 (file)
@@ -95,9 +95,9 @@ struct si_sm_data {
        enum bt_states  state;
        unsigned char   seq;            /* BT sequence number */
        struct si_sm_io *io;
-       unsigned char   write_data[IPMI_MAX_MSG_LENGTH];
+       unsigned char   write_data[IPMI_MAX_MSG_LENGTH + 2]; /* +2 for memcpy */
        int             write_count;
-       unsigned char   read_data[IPMI_MAX_MSG_LENGTH];
+       unsigned char   read_data[IPMI_MAX_MSG_LENGTH + 2]; /* +2 for memcpy */
        int             read_count;
        int             truncated;
        long            timeout;        /* microseconds countdown */
index 9eb360f..d5a5f02 100644 (file)
@@ -837,13 +837,25 @@ static long compat_ipmi_ioctl(struct file *filep, unsigned int cmd,
                return ipmi_ioctl(filep, cmd, arg);
        }
 }
+
+static long unlocked_compat_ipmi_ioctl(struct file *filep, unsigned int cmd,
+                                      unsigned long arg)
+{
+       int ret;
+
+       mutex_lock(&ipmi_mutex);
+       ret = compat_ipmi_ioctl(filep, cmd, arg);
+       mutex_unlock(&ipmi_mutex);
+
+       return ret;
+}
 #endif
 
 static const struct file_operations ipmi_fops = {
        .owner          = THIS_MODULE,
        .unlocked_ioctl = ipmi_unlocked_ioctl,
 #ifdef CONFIG_COMPAT
-       .compat_ioctl   = compat_ipmi_ioctl,
+       .compat_ioctl   = unlocked_compat_ipmi_ioctl,
 #endif
        .open           = ipmi_open,
        .release        = ipmi_release,
index 4d439d2..4445fa1 100644 (file)
@@ -2037,12 +2037,11 @@ int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name,
        entry = kmalloc(sizeof(*entry), GFP_KERNEL);
        if (!entry)
                return -ENOMEM;
-       entry->name = kmalloc(strlen(name)+1, GFP_KERNEL);
+       entry->name = kstrdup(name, GFP_KERNEL);
        if (!entry->name) {
                kfree(entry);
                return -ENOMEM;
        }
-       strcpy(entry->name, name);
 
        file = proc_create_data(name, 0, smi->proc_dir, proc_ops, data);
        if (!file) {
index 313538a..af4b23f 100644 (file)
@@ -663,8 +663,10 @@ static void handle_transaction_done(struct smi_info *smi_info)
                /* We got the flags from the SMI, now handle them. */
                smi_info->handlers->get_result(smi_info->si_sm, msg, 4);
                if (msg[2] != 0) {
-                       dev_warn(smi_info->dev, "Could not enable interrupts"
-                                ", failed get, using polled mode.\n");
+                       dev_warn(smi_info->dev,
+                                "Couldn't get irq info: %x.\n", msg[2]);
+                       dev_warn(smi_info->dev,
+                                "Maybe ok, but ipmi might run very slowly.\n");
                        smi_info->si_state = SI_NORMAL;
                } else {
                        msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
@@ -685,10 +687,12 @@ static void handle_transaction_done(struct smi_info *smi_info)
 
                /* We got the flags from the SMI, now handle them. */
                smi_info->handlers->get_result(smi_info->si_sm, msg, 4);
-               if (msg[2] != 0)
-                       dev_warn(smi_info->dev, "Could not enable interrupts"
-                                ", failed set, using polled mode.\n");
-               else
+               if (msg[2] != 0) {
+                       dev_warn(smi_info->dev,
+                                "Couldn't set irq info: %x.\n", msg[2]);
+                       dev_warn(smi_info->dev,
+                                "Maybe ok, but ipmi might run very slowly.\n");
+               } else
                        smi_info->interrupt_disabled = 0;
                smi_info->si_state = SI_NORMAL;
                break;
index dafd9ac..0913d79 100644 (file)
@@ -622,9 +622,12 @@ static int lp_do_ioctl(unsigned int minor, unsigned int cmd,
                                return -EFAULT;
                        break;
                case LPGETSTATUS:
+                       if (mutex_lock_interruptible(&lp_table[minor].port_mutex))
+                               return -EINTR;
                        lp_claim_parport_or_block (&lp_table[minor]);
                        status = r_str(minor);
                        lp_release_parport (&lp_table[minor]);
+                       mutex_unlock(&lp_table[minor].port_mutex);
 
                        if (copy_to_user(argp, &status, sizeof(int)))
                                return -EFAULT;
index cd9a621..35487e8 100644 (file)
@@ -865,16 +865,24 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min,
        if (r->entropy_count / 8 < min + reserved) {
                nbytes = 0;
        } else {
+               int entropy_count, orig;
+retry:
+               entropy_count = orig = ACCESS_ONCE(r->entropy_count);
                /* If limited, never pull more than available */
-               if (r->limit && nbytes + reserved >= r->entropy_count / 8)
-                       nbytes = r->entropy_count/8 - reserved;
-
-               if (r->entropy_count / 8 >= nbytes + reserved)
-                       r->entropy_count -= nbytes*8;
-               else
-                       r->entropy_count = reserved;
+               if (r->limit && nbytes + reserved >= entropy_count / 8)
+                       nbytes = entropy_count/8 - reserved;
+
+               if (entropy_count / 8 >= nbytes + reserved) {
+                       entropy_count -= nbytes*8;
+                       if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig)
+                               goto retry;
+               } else {
+                       entropy_count = reserved;
+                       if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig)
+                               goto retry;
+               }
 
-               if (r->entropy_count < random_write_wakeup_thresh)
+               if (entropy_count < random_write_wakeup_thresh)
                        wakeup_write = 1;
        }
 
@@ -957,10 +965,23 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf,
 {
        ssize_t ret = 0, i;
        __u8 tmp[EXTRACT_SIZE];
+       unsigned long flags;
 
        /* if last_data isn't primed, we need EXTRACT_SIZE extra bytes */
-       if (fips_enabled && !r->last_data_init)
-               nbytes += EXTRACT_SIZE;
+       if (fips_enabled) {
+               spin_lock_irqsave(&r->lock, flags);
+               if (!r->last_data_init) {
+                       r->last_data_init = true;
+                       spin_unlock_irqrestore(&r->lock, flags);
+                       trace_extract_entropy(r->name, EXTRACT_SIZE,
+                                             r->entropy_count, _RET_IP_);
+                       xfer_secondary_pool(r, EXTRACT_SIZE);
+                       extract_buf(r, tmp);
+                       spin_lock_irqsave(&r->lock, flags);
+                       memcpy(r->last_data, tmp, EXTRACT_SIZE);
+               }
+               spin_unlock_irqrestore(&r->lock, flags);
+       }
 
        trace_extract_entropy(r->name, nbytes, r->entropy_count, _RET_IP_);
        xfer_secondary_pool(r, nbytes);
@@ -970,19 +991,6 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf,
                extract_buf(r, tmp);
 
                if (fips_enabled) {
-                       unsigned long flags;
-
-
-                       /* prime last_data value if need be, per fips 140-2 */
-                       if (!r->last_data_init) {
-                               spin_lock_irqsave(&r->lock, flags);
-                               memcpy(r->last_data, tmp, EXTRACT_SIZE);
-                               r->last_data_init = true;
-                               nbytes -= EXTRACT_SIZE;
-                               spin_unlock_irqrestore(&r->lock, flags);
-                               extract_buf(r, tmp);
-                       }
-
                        spin_lock_irqsave(&r->lock, flags);
                        if (!memcmp(tmp, r->last_data, EXTRACT_SIZE))
                                panic("Hardware RNG duplicated output!\n");
index 4945bd3..d5d2e4a 100644 (file)
@@ -179,7 +179,6 @@ static int __init ttyprintk_init(void)
 {
        int ret = -ENOMEM;
 
-       tpk_port.port.ops = &null_ops;
        mutex_init(&tpk_port.port_write_mutex);
 
        ttyprintk_driver = tty_alloc_driver(1,
@@ -190,6 +189,7 @@ static int __init ttyprintk_init(void)
                return PTR_ERR(ttyprintk_driver);
 
        tty_port_init(&tpk_port.port);
+       tpk_port.port.ops = &null_ops;
 
        ttyprintk_driver->driver_name = "ttyprintk";
        ttyprintk_driver->name = "ttyprintk";
index 8927284..24f5536 100644 (file)
@@ -932,7 +932,7 @@ static unsigned long si5351_clkout_recalc_rate(struct clk_hw *hw,
        unsigned char reg;
        unsigned char rdiv;
 
-       if (hwdata->num > 5)
+       if (hwdata->num <= 5)
                reg = si5351_msynth_params_address(hwdata->num) + 2;
        else
                reg = SI5351_CLK6_7_OUTPUT_DIVIDER;
@@ -1477,6 +1477,16 @@ static int si5351_i2c_probe(struct i2c_client *client,
                        return -EINVAL;
                }
                drvdata->onecell.clks[n] = clk;
+
+               /* set initial clkout rate */
+               if (pdata->clkout[n].rate != 0) {
+                       int ret;
+                       ret = clk_set_rate(clk, pdata->clkout[n].rate);
+                       if (ret != 0) {
+                               dev_err(&client->dev, "Cannot set rate : %d\n",
+                                       ret);
+                       }
+               }
        }
 
        ret = of_clk_add_provider(client->dev.of_node, of_clk_src_onecell_get,
index debf688..553ac35 100644 (file)
@@ -183,7 +183,7 @@ static int vt8500_dclk_set_rate(struct clk_hw *hw, unsigned long rate,
        writel(divisor, cdev->div_reg);
        vt8500_pmc_wait_busy();
 
-       spin_lock_irqsave(cdev->lock, flags);
+       spin_unlock_irqrestore(cdev->lock, flags);
 
        return 0;
 }
index d0e5eed..4faf0af 100644 (file)
@@ -10,6 +10,7 @@
  */
 
 #include <linux/clk.h>
+#include <linux/clk/mxs.h>
 #include <linux/clkdev.h>
 #include <linux/err.h>
 #include <linux/init.h>
index d0940e6..3c1f888 100644 (file)
@@ -791,7 +791,8 @@ struct samsung_gate_clock exynos4210_gate_clks[] __initdata = {
        GATE(smmu_pcie, "smmu_pcie", "aclk133", GATE_IP_FSYS, 18, 0, 0),
        GATE(modemif, "modemif", "aclk100", GATE_IP_PERIL, 28, 0, 0),
        GATE(chipid, "chipid", "aclk100", E4210_GATE_IP_PERIR, 0, 0, 0),
-       GATE(sysreg, "sysreg", "aclk100", E4210_GATE_IP_PERIR, 0, 0, 0),
+       GATE(sysreg, "sysreg", "aclk100", E4210_GATE_IP_PERIR, 0,
+                       CLK_IGNORE_UNUSED, 0),
        GATE(hdmi_cec, "hdmi_cec", "aclk100", E4210_GATE_IP_PERIR, 11, 0, 0),
        GATE(smmu_rotator, "smmu_rotator", "aclk200",
                        E4210_GATE_IP_IMAGE, 4, 0, 0),
@@ -819,7 +820,8 @@ struct samsung_gate_clock exynos4x12_gate_clks[] __initdata = {
        GATE(smmu_mdma, "smmu_mdma", "aclk200", E4X12_GATE_IP_IMAGE, 5, 0, 0),
        GATE(mipi_hsi, "mipi_hsi", "aclk133", GATE_IP_FSYS, 10, 0, 0),
        GATE(chipid, "chipid", "aclk100", E4X12_GATE_IP_PERIR, 0, 0, 0),
-       GATE(sysreg, "sysreg", "aclk100", E4X12_GATE_IP_PERIR, 1, 0, 0),
+       GATE(sysreg, "sysreg", "aclk100", E4X12_GATE_IP_PERIR, 1,
+                       CLK_IGNORE_UNUSED, 0),
        GATE(hdmi_cec, "hdmi_cec", "aclk100", E4X12_GATE_IP_PERIR, 11, 0, 0),
        GATE(sclk_mdnie0, "sclk_mdnie0", "div_mdnie0",
                        SRC_MASK_LCD0, 4, CLK_SET_RATE_PARENT, 0),
index 8292a00..075db0c 100644 (file)
@@ -872,6 +872,14 @@ static void __init tegra20_periph_clk_init(void)
        struct clk *clk;
        int i;
 
+       /* ac97 */
+       clk = tegra_clk_register_periph_gate("ac97", "pll_a_out0",
+                                   TEGRA_PERIPH_ON_APB,
+                                   clk_base, 0, 3, &periph_l_regs,
+                                   periph_clk_enb_refcnt);
+       clk_register_clkdev(clk, NULL, "tegra20-ac97");
+       clks[ac97] = clk;
+
        /* apbdma */
        clk = tegra_clk_register_periph_gate("apbdma", "pclk", 0, clk_base,
                                    0, 34, &periph_h_regs,
@@ -1234,9 +1242,6 @@ static __initdata struct tegra_clk_init_table init_table[] = {
        {uartc, pll_p, 0, 0},
        {uartd, pll_p, 0, 0},
        {uarte, pll_p, 0, 0},
-       {usbd, clk_max, 12000000, 0},
-       {usb2, clk_max, 12000000, 0},
-       {usb3, clk_max, 12000000, 0},
        {pll_a, clk_max, 56448000, 1},
        {pll_a_out0, clk_max, 11289600, 1},
        {cdev1, clk_max, 0, 1},
index bc7e9bd..e364c9d 100644 (file)
@@ -145,7 +145,13 @@ static struct clk *clk_reg_sysctrl(struct device *dev,
                return ERR_PTR(-ENOMEM);
        }
 
-       for (i = 0; i < num_parents; i++) {
+       /* set main clock registers */
+       clk->reg_sel[0] = reg_sel[0];
+       clk->reg_bits[0] = reg_bits[0];
+       clk->reg_mask[0] = reg_mask[0];
+
+       /* handle clocks with more than one parent */
+       for (i = 1; i < num_parents; i++) {
                clk->reg_sel[i] = reg_sel[i];
                clk->reg_bits[i] = reg_bits[i];
                clk->reg_mask[i] = reg_mask[i];
index 0b4f35a..80069c3 100644 (file)
@@ -325,7 +325,7 @@ void u8500_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base,
        clk = clk_reg_prcc_pclk("p3_pclk0", "per3clk", clkrst3_base,
                                BIT(0), 0);
        clk_register_clkdev(clk, "fsmc", NULL);
-       clk_register_clkdev(clk, NULL, "smsc911x");
+       clk_register_clkdev(clk, NULL, "smsc911x.0");
 
        clk = clk_reg_prcc_pclk("p3_pclk1", "per3clk", clkrst3_base,
                                BIT(1), 0);
index 5cf4f46..4f45eee 100644 (file)
 #include <linux/clk-provider.h>
 #include <linux/err.h>
 #include <linux/module.h>
+#include <linux/platform_data/clk-lpss.h>
 #include <linux/platform_device.h>
 
 #define PRV_CLOCK_PARAMS 0x800
 
 static int lpt_clk_probe(struct platform_device *pdev)
 {
+       struct lpss_clk_data *drvdata;
        struct clk *clk;
 
+       drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
+       if (!drvdata)
+               return -ENOMEM;
+
        /* LPSS free running clock */
-       clk = clk_register_fixed_rate(&pdev->dev, "lpss_clk", NULL, CLK_IS_ROOT,
-                                     100000000);
+       drvdata->name = "lpss_clk";
+       clk = clk_register_fixed_rate(&pdev->dev, drvdata->name, NULL,
+                                     CLK_IS_ROOT, 100000000);
        if (IS_ERR(clk))
                return PTR_ERR(clk);
 
-       /* Shared DMA clock */
-       clk_register_clkdev(clk, "hclk", "INTL9C60.0.auto");
+       drvdata->clk = clk;
+       platform_set_drvdata(pdev, drvdata);
        return 0;
 }
 
index a1488f5..534fcb8 100644 (file)
@@ -47,7 +47,7 @@ config CPU_FREQ_STAT_DETAILS
 
 choice
        prompt "Default CPUFreq governor"
-       default CPU_FREQ_DEFAULT_GOV_USERSPACE if CPU_FREQ_SA1100 || CPU_FREQ_SA1110
+       default CPU_FREQ_DEFAULT_GOV_USERSPACE if ARM_SA1100_CPUFREQ || ARM_SA1110_CPUFREQ
        default CPU_FREQ_DEFAULT_GOV_PERFORMANCE
        help
          This option sets which CPUFreq governor shall be loaded at
index f3af18b..6e57543 100644 (file)
@@ -3,16 +3,17 @@
 #
 
 config ARM_BIG_LITTLE_CPUFREQ
-       tristate
-       depends on ARM_CPU_TOPOLOGY
+       tristate "Generic ARM big LITTLE CPUfreq driver"
+       depends on ARM_CPU_TOPOLOGY && PM_OPP && HAVE_CLK
+       help
+         This enables the Generic CPUfreq driver for ARM big.LITTLE platforms.
 
 config ARM_DT_BL_CPUFREQ
-       tristate "Generic ARM big LITTLE CPUfreq driver probed via DT"
-       select ARM_BIG_LITTLE_CPUFREQ
-       depends on OF && HAVE_CLK
+       tristate "Generic probing via DT for ARM big LITTLE CPUfreq driver"
+       depends on ARM_BIG_LITTLE_CPUFREQ && OF
        help
-         This enables the Generic CPUfreq driver for ARM big.LITTLE platform.
-         This gets frequency tables from DT.
+         This enables probing via DT for Generic CPUfreq driver for ARM
+         big.LITTLE platform. This gets frequency tables from DT.
 
 config ARM_EXYNOS_CPUFREQ
        bool "SAMSUNG EXYNOS SoCs"
index 2b8a8c3..6bd63d6 100644 (file)
@@ -272,7 +272,7 @@ config X86_LONGHAUL
 config X86_E_POWERSAVER
        tristate "VIA C7 Enhanced PowerSaver (DANGEROUS)"
        select CPU_FREQ_TABLE
-       depends on X86_32
+       depends on X86_32 && ACPI_PROCESSOR
        help
          This adds the CPUFreq driver for VIA C7 processors.  However, this driver
          does not have any safeguards to prevent operating the CPU out of spec
index 11b8b4b..edc089e 100644 (file)
@@ -347,11 +347,11 @@ static u32 get_cur_val(const struct cpumask *mask)
        switch (per_cpu(acfreq_data, cpumask_first(mask))->cpu_feature) {
        case SYSTEM_INTEL_MSR_CAPABLE:
                cmd.type = SYSTEM_INTEL_MSR_CAPABLE;
-               cmd.addr.msr.reg = MSR_IA32_PERF_STATUS;
+               cmd.addr.msr.reg = MSR_IA32_PERF_CTL;
                break;
        case SYSTEM_AMD_MSR_CAPABLE:
                cmd.type = SYSTEM_AMD_MSR_CAPABLE;
-               cmd.addr.msr.reg = MSR_AMD_PERF_STATUS;
+               cmd.addr.msr.reg = MSR_AMD_PERF_CTL;
                break;
        case SYSTEM_IO_CAPABLE:
                cmd.type = SYSTEM_IO_CAPABLE;
index dbdf677..5d7f53f 100644 (file)
@@ -40,11 +40,6 @@ static struct clk *clk[MAX_CLUSTERS];
 static struct cpufreq_frequency_table *freq_table[MAX_CLUSTERS];
 static atomic_t cluster_usage[MAX_CLUSTERS] = {ATOMIC_INIT(0), ATOMIC_INIT(0)};
 
-static int cpu_to_cluster(int cpu)
-{
-       return topology_physical_package_id(cpu);
-}
-
 static unsigned int bL_cpufreq_get(unsigned int cpu)
 {
        u32 cur_cluster = cpu_to_cluster(cpu);
@@ -192,7 +187,7 @@ static int bL_cpufreq_init(struct cpufreq_policy *policy)
 
        cpumask_copy(policy->cpus, topology_core_cpumask(policy->cpu));
 
-       dev_info(cpu_dev, "CPU %d initialized\n", policy->cpu);
+       dev_info(cpu_dev, "%s: CPU %d initialized\n", __func__, policy->cpu);
        return 0;
 }
 
index 70f18fc..79b2ce1 100644 (file)
@@ -34,6 +34,11 @@ struct cpufreq_arm_bL_ops {
        int (*init_opp_table)(struct device *cpu_dev);
 };
 
+static inline int cpu_to_cluster(int cpu)
+{
+       return topology_physical_package_id(cpu);
+}
+
 int bL_cpufreq_register(struct cpufreq_arm_bL_ops *ops);
 void bL_cpufreq_unregister(struct cpufreq_arm_bL_ops *ops);
 
index 44be311..fd9e3ea 100644 (file)
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <linux/cpu.h>
 #include <linux/cpufreq.h>
 #include <linux/device.h>
 #include <linux/export.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/opp.h>
+#include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/types.h>
 #include "arm_big_little.h"
 
-static int dt_init_opp_table(struct device *cpu_dev)
+/* get cpu node with valid operating-points */
+static struct device_node *get_cpu_node_with_valid_op(int cpu)
 {
-       struct device_node *np, *parent;
-       int count = 0, ret;
+       struct device_node *np = NULL, *parent;
+       int count = 0;
 
        parent = of_find_node_by_path("/cpus");
        if (!parent) {
                pr_err("failed to find OF /cpus\n");
-               return -ENOENT;
+               return NULL;
        }
 
        for_each_child_of_node(parent, np) {
-               if (count++ != cpu_dev->id)
+               if (count++ != cpu)
                        continue;
                if (!of_get_property(np, "operating-points", NULL)) {
-                       ret = -ENODATA;
-               } else {
-                       cpu_dev->of_node = np;
-                       ret = of_init_opp_table(cpu_dev);
+                       of_node_put(np);
+                       np = NULL;
                }
-               of_node_put(np);
-               of_node_put(parent);
 
-               return ret;
+               break;
        }
 
-       return -ENODEV;
+       of_node_put(parent);
+       return np;
 }
 
-static int dt_get_transition_latency(struct device *cpu_dev)
+static int dt_init_opp_table(struct device *cpu_dev)
 {
-       struct device_node *np, *parent;
-       u32 transition_latency = CPUFREQ_ETERNAL;
-       int count = 0;
+       struct device_node *np;
+       int ret;
 
-       parent = of_find_node_by_path("/cpus");
-       if (!parent) {
-               pr_err("failed to find OF /cpus\n");
-               return -ENOENT;
-       }
+       np = get_cpu_node_with_valid_op(cpu_dev->id);
+       if (!np)
+               return -ENODATA;
 
-       for_each_child_of_node(parent, np) {
-               if (count++ != cpu_dev->id)
-                       continue;
+       cpu_dev->of_node = np;
+       ret = of_init_opp_table(cpu_dev);
+       of_node_put(np);
 
-               of_property_read_u32(np, "clock-latency", &transition_latency);
-               of_node_put(np);
-               of_node_put(parent);
+       return ret;
+}
 
-               return 0;
-       }
+static int dt_get_transition_latency(struct device *cpu_dev)
+{
+       struct device_node *np;
+       u32 transition_latency = CPUFREQ_ETERNAL;
+
+       np = get_cpu_node_with_valid_op(cpu_dev->id);
+       if (!np)
+               return CPUFREQ_ETERNAL;
 
-       return -ENODEV;
+       of_property_read_u32(np, "clock-latency", &transition_latency);
+       of_node_put(np);
+
+       pr_debug("%s: clock-latency: %d\n", __func__, transition_latency);
+       return transition_latency;
 }
 
 static struct cpufreq_arm_bL_ops dt_bL_ops = {
@@ -90,17 +96,33 @@ static struct cpufreq_arm_bL_ops dt_bL_ops = {
        .init_opp_table = dt_init_opp_table,
 };
 
-static int generic_bL_init(void)
+static int generic_bL_probe(struct platform_device *pdev)
 {
+       struct device_node *np;
+
+       np = get_cpu_node_with_valid_op(0);
+       if (!np)
+               return -ENODEV;
+
+       of_node_put(np);
        return bL_cpufreq_register(&dt_bL_ops);
 }
-module_init(generic_bL_init);
 
-static void generic_bL_exit(void)
+static int generic_bL_remove(struct platform_device *pdev)
 {
-       return bL_cpufreq_unregister(&dt_bL_ops);
+       bL_cpufreq_unregister(&dt_bL_ops);
+       return 0;
 }
-module_exit(generic_bL_exit);
+
+static struct platform_driver generic_bL_platdrv = {
+       .driver = {
+               .name   = "arm-bL-cpufreq-dt",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = generic_bL_probe,
+       .remove         = generic_bL_remove,
+};
+module_platform_driver(generic_bL_platdrv);
 
 MODULE_AUTHOR("Viresh Kumar <viresh.kumar@linaro.org>");
 MODULE_DESCRIPTION("Generic ARM big LITTLE cpufreq driver via DT");
index 3ab8294..ad1fde2 100644 (file)
@@ -45,7 +45,7 @@ static int cpu0_set_target(struct cpufreq_policy *policy,
        struct cpufreq_freqs freqs;
        struct opp *opp;
        unsigned long volt = 0, volt_old = 0, tol = 0;
-       long freq_Hz;
+       long freq_Hz, freq_exact;
        unsigned int index;
        int ret;
 
@@ -60,6 +60,7 @@ static int cpu0_set_target(struct cpufreq_policy *policy,
        freq_Hz = clk_round_rate(cpu_clk, freq_table[index].frequency * 1000);
        if (freq_Hz < 0)
                freq_Hz = freq_table[index].frequency * 1000;
+       freq_exact = freq_Hz;
        freqs.new = freq_Hz / 1000;
        freqs.old = clk_get_rate(cpu_clk) / 1000;
 
@@ -98,7 +99,7 @@ static int cpu0_set_target(struct cpufreq_policy *policy,
                }
        }
 
-       ret = clk_set_rate(cpu_clk, freqs.new * 1000);
+       ret = clk_set_rate(cpu_clk, freq_exact);
        if (ret) {
                pr_err("failed to set clock rate: %d\n", ret);
                if (cpu_reg)
@@ -189,12 +190,29 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev)
 
        if (!np) {
                pr_err("failed to find cpu0 node\n");
-               return -ENOENT;
+               ret = -ENOENT;
+               goto out_put_parent;
        }
 
        cpu_dev = &pdev->dev;
        cpu_dev->of_node = np;
 
+       cpu_reg = devm_regulator_get(cpu_dev, "cpu0");
+       if (IS_ERR(cpu_reg)) {
+               /*
+                * If cpu0 regulator supply node is present, but regulator is
+                * not yet registered, we should try defering probe.
+                */
+               if (PTR_ERR(cpu_reg) == -EPROBE_DEFER) {
+                       dev_err(cpu_dev, "cpu0 regulator not ready, retry\n");
+                       ret = -EPROBE_DEFER;
+                       goto out_put_node;
+               }
+               pr_warn("failed to get cpu0 regulator: %ld\n",
+                       PTR_ERR(cpu_reg));
+               cpu_reg = NULL;
+       }
+
        cpu_clk = devm_clk_get(cpu_dev, NULL);
        if (IS_ERR(cpu_clk)) {
                ret = PTR_ERR(cpu_clk);
@@ -202,12 +220,6 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev)
                goto out_put_node;
        }
 
-       cpu_reg = devm_regulator_get(cpu_dev, "cpu0");
-       if (IS_ERR(cpu_reg)) {
-               pr_warn("failed to get cpu0 regulator\n");
-               cpu_reg = NULL;
-       }
-
        ret = of_init_opp_table(cpu_dev);
        if (ret) {
                pr_err("failed to init OPP table: %d\n", ret);
@@ -264,6 +276,8 @@ out_free_table:
        opp_free_cpufreq_table(cpu_dev, &freq_table);
 out_put_node:
        of_node_put(np);
+out_put_parent:
+       of_node_put(parent);
        return ret;
 }
 
index 1b8a48e..2d53f47 100644 (file)
@@ -1075,14 +1075,14 @@ static int __cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif
                                __func__, cpu_dev->id, cpu);
        }
 
+       if ((cpus == 1) && (cpufreq_driver->target))
+               __cpufreq_governor(data, CPUFREQ_GOV_POLICY_EXIT);
+
        pr_debug("%s: removing link, cpu: %d\n", __func__, cpu);
        cpufreq_cpu_put(data);
 
        /* If cpu is last user of policy, free policy */
        if (cpus == 1) {
-               if (cpufreq_driver->target)
-                       __cpufreq_governor(data, CPUFREQ_GOV_POLICY_EXIT);
-
                lock_policy_rwsem_read(cpu);
                kobj = &data->kobj;
                cmp = &data->kobj_unregister;
@@ -1729,18 +1729,23 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data,
                        /* end old governor */
                        if (data->governor) {
                                __cpufreq_governor(data, CPUFREQ_GOV_STOP);
+                               unlock_policy_rwsem_write(policy->cpu);
                                __cpufreq_governor(data,
                                                CPUFREQ_GOV_POLICY_EXIT);
+                               lock_policy_rwsem_write(policy->cpu);
                        }
 
                        /* start new governor */
                        data->governor = policy->governor;
                        if (!__cpufreq_governor(data, CPUFREQ_GOV_POLICY_INIT)) {
-                               if (!__cpufreq_governor(data, CPUFREQ_GOV_START))
+                               if (!__cpufreq_governor(data, CPUFREQ_GOV_START)) {
                                        failed = 0;
-                               else
+                               } else {
+                                       unlock_policy_rwsem_write(policy->cpu);
                                        __cpufreq_governor(data,
                                                        CPUFREQ_GOV_POLICY_EXIT);
+                                       lock_policy_rwsem_write(policy->cpu);
+                               }
                        }
 
                        if (failed) {
@@ -1832,15 +1837,13 @@ static int __cpuinit cpufreq_cpu_callback(struct notifier_block *nfb,
        if (dev) {
                switch (action) {
                case CPU_ONLINE:
-               case CPU_ONLINE_FROZEN:
                        cpufreq_add_dev(dev, NULL);
                        break;
                case CPU_DOWN_PREPARE:
-               case CPU_DOWN_PREPARE_FROZEN:
+               case CPU_UP_CANCELED_FROZEN:
                        __cpufreq_remove_dev(dev, NULL);
                        break;
                case CPU_DOWN_FAILED:
-               case CPU_DOWN_FAILED_FROZEN:
                        cpufreq_add_dev(dev, NULL);
                        break;
                }
index 443442d..dc9b72e 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/tick.h>
 #include <linux/types.h>
 #include <linux/workqueue.h>
+#include <linux/cpu.h>
 
 #include "cpufreq_governor.h"
 
@@ -180,8 +181,10 @@ void gov_queue_work(struct dbs_data *dbs_data, struct cpufreq_policy *policy,
        if (!all_cpus) {
                __gov_queue_work(smp_processor_id(), dbs_data, delay);
        } else {
+               get_online_cpus();
                for_each_cpu(i, policy->cpus)
                        __gov_queue_work(i, dbs_data, delay);
+               put_online_cpus();
        }
 }
 EXPORT_SYMBOL_GPL(gov_queue_work);
@@ -255,6 +258,7 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy,
                if (have_governor_per_policy()) {
                        WARN_ON(dbs_data);
                } else if (dbs_data) {
+                       dbs_data->usage_count++;
                        policy->governor_data = dbs_data;
                        return 0;
                }
@@ -266,6 +270,7 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy,
                }
 
                dbs_data->cdata = cdata;
+               dbs_data->usage_count = 1;
                rc = cdata->init(dbs_data);
                if (rc) {
                        pr_err("%s: POLICY_INIT: init() failed\n", __func__);
@@ -294,7 +299,8 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy,
                set_sampling_rate(dbs_data, max(dbs_data->min_sampling_rate,
                                        latency * LATENCY_MULTIPLIER));
 
-               if (dbs_data->cdata->governor == GOV_CONSERVATIVE) {
+               if ((cdata->governor == GOV_CONSERVATIVE) &&
+                               (!policy->governor->initialized)) {
                        struct cs_ops *cs_ops = dbs_data->cdata->gov_ops;
 
                        cpufreq_register_notifier(cs_ops->notifier_block,
@@ -306,12 +312,12 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy,
 
                return 0;
        case CPUFREQ_GOV_POLICY_EXIT:
-               if ((policy->governor->initialized == 1) ||
-                               have_governor_per_policy()) {
+               if (!--dbs_data->usage_count) {
                        sysfs_remove_group(get_governor_parent_kobj(policy),
                                        get_sysfs_attr(dbs_data));
 
-                       if (dbs_data->cdata->governor == GOV_CONSERVATIVE) {
+                       if ((dbs_data->cdata->governor == GOV_CONSERVATIVE) &&
+                               (policy->governor->initialized == 1)) {
                                struct cs_ops *cs_ops = dbs_data->cdata->gov_ops;
 
                                cpufreq_unregister_notifier(cs_ops->notifier_block,
index 8ac3353..e16a961 100644 (file)
@@ -211,6 +211,7 @@ struct common_dbs_data {
 struct dbs_data {
        struct common_dbs_data *cdata;
        unsigned int min_sampling_rate;
+       int usage_count;
        void *tuners;
 
        /* dbs_mutex protects dbs_enable in governor start/stop */
index b0ffef9..4b9bb5d 100644 (file)
@@ -547,7 +547,6 @@ static int od_init(struct dbs_data *dbs_data)
        tuners->io_is_busy = should_io_be_busy();
 
        dbs_data->tuners = tuners;
-       pr_info("%s: tuners %p\n", __func__, tuners);
        mutex_init(&dbs_data->mutex);
        return 0;
 }
index bfd6273..fb65dec 100644 (file)
@@ -349,15 +349,16 @@ static int __cpuinit cpufreq_stat_cpu_callback(struct notifier_block *nfb,
 
        switch (action) {
        case CPU_ONLINE:
-       case CPU_ONLINE_FROZEN:
                cpufreq_update_policy(cpu);
                break;
        case CPU_DOWN_PREPARE:
-       case CPU_DOWN_PREPARE_FROZEN:
                cpufreq_stats_free_sysfs(cpu);
                break;
        case CPU_DEAD:
-       case CPU_DEAD_FROZEN:
+               cpufreq_stats_free_table(cpu);
+               break;
+       case CPU_UP_CANCELED_FROZEN:
+               cpufreq_stats_free_sysfs(cpu);
                cpufreq_stats_free_table(cpu);
                break;
        }
index cc3a8e6..07f2840 100644 (file)
@@ -48,12 +48,7 @@ static inline int32_t div_fp(int32_t x, int32_t y)
 }
 
 struct sample {
-       ktime_t start_time;
-       ktime_t end_time;
        int core_pct_busy;
-       int pstate_pct_busy;
-       u64 duration_us;
-       u64 idletime_us;
        u64 aperf;
        u64 mperf;
        int freq;
@@ -86,13 +81,9 @@ struct cpudata {
        struct pstate_adjust_policy *pstate_policy;
        struct pstate_data pstate;
        struct _pid pid;
-       struct _pid idle_pid;
 
        int min_pstate_count;
-       int idle_mode;
 
-       ktime_t prev_sample;
-       u64     prev_idle_time_us;
        u64     prev_aperf;
        u64     prev_mperf;
        int     sample_ptr;
@@ -124,6 +115,8 @@ struct perf_limits {
        int min_perf_pct;
        int32_t max_perf;
        int32_t min_perf;
+       int max_policy_pct;
+       int max_sysfs_pct;
 };
 
 static struct perf_limits limits = {
@@ -132,6 +125,8 @@ static struct perf_limits limits = {
        .max_perf = int_tofp(1),
        .min_perf_pct = 0,
        .min_perf = 0,
+       .max_policy_pct = 100,
+       .max_sysfs_pct = 100,
 };
 
 static inline void pid_reset(struct _pid *pid, int setpoint, int busy,
@@ -202,19 +197,6 @@ static inline void intel_pstate_busy_pid_reset(struct cpudata *cpu)
                0);
 }
 
-static inline void intel_pstate_idle_pid_reset(struct cpudata *cpu)
-{
-       pid_p_gain_set(&cpu->idle_pid, cpu->pstate_policy->p_gain_pct);
-       pid_d_gain_set(&cpu->idle_pid, cpu->pstate_policy->d_gain_pct);
-       pid_i_gain_set(&cpu->idle_pid, cpu->pstate_policy->i_gain_pct);
-
-       pid_reset(&cpu->idle_pid,
-               75,
-               50,
-               cpu->pstate_policy->deadband,
-               0);
-}
-
 static inline void intel_pstate_reset_all_pid(void)
 {
        unsigned int cpu;
@@ -302,7 +284,8 @@ static ssize_t store_max_perf_pct(struct kobject *a, struct attribute *b,
        if (ret != 1)
                return -EINVAL;
 
-       limits.max_perf_pct = clamp_t(int, input, 0 , 100);
+       limits.max_sysfs_pct = clamp_t(int, input, 0 , 100);
+       limits.max_perf_pct = min(limits.max_policy_pct, limits.max_sysfs_pct);
        limits.max_perf = div_fp(int_tofp(limits.max_perf_pct), int_tofp(100));
        return count;
 }
@@ -408,9 +391,8 @@ static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate)
        if (pstate == cpu->pstate.current_pstate)
                return;
 
-#ifndef MODULE
        trace_cpu_frequency(pstate * 100000, cpu->cpu);
-#endif
+
        cpu->pstate.current_pstate = pstate;
        wrmsrl(MSR_IA32_PERF_CTL, pstate << 8);
 
@@ -450,48 +432,26 @@ static inline void intel_pstate_calc_busy(struct cpudata *cpu,
                                        struct sample *sample)
 {
        u64 core_pct;
-       sample->pstate_pct_busy = 100 - div64_u64(
-                                       sample->idletime_us * 100,
-                                       sample->duration_us);
        core_pct = div64_u64(sample->aperf * 100, sample->mperf);
        sample->freq = cpu->pstate.max_pstate * core_pct * 1000;
 
-       sample->core_pct_busy = div_s64((sample->pstate_pct_busy * core_pct),
-                                       100);
+       sample->core_pct_busy = core_pct;
 }
 
 static inline void intel_pstate_sample(struct cpudata *cpu)
 {
-       ktime_t now;
-       u64 idle_time_us;
        u64 aperf, mperf;
 
-       now = ktime_get();
-       idle_time_us = get_cpu_idle_time_us(cpu->cpu, NULL);
-
        rdmsrl(MSR_IA32_APERF, aperf);
        rdmsrl(MSR_IA32_MPERF, mperf);
-       /* for the first sample, don't actually record a sample, just
-        * set the baseline */
-       if (cpu->prev_idle_time_us > 0) {
-               cpu->sample_ptr = (cpu->sample_ptr + 1) % SAMPLE_COUNT;
-               cpu->samples[cpu->sample_ptr].start_time = cpu->prev_sample;
-               cpu->samples[cpu->sample_ptr].end_time = now;
-               cpu->samples[cpu->sample_ptr].duration_us =
-                       ktime_us_delta(now, cpu->prev_sample);
-               cpu->samples[cpu->sample_ptr].idletime_us =
-                       idle_time_us - cpu->prev_idle_time_us;
-
-               cpu->samples[cpu->sample_ptr].aperf = aperf;
-               cpu->samples[cpu->sample_ptr].mperf = mperf;
-               cpu->samples[cpu->sample_ptr].aperf -= cpu->prev_aperf;
-               cpu->samples[cpu->sample_ptr].mperf -= cpu->prev_mperf;
-
-               intel_pstate_calc_busy(cpu, &cpu->samples[cpu->sample_ptr]);
-       }
+       cpu->sample_ptr = (cpu->sample_ptr + 1) % SAMPLE_COUNT;
+       cpu->samples[cpu->sample_ptr].aperf = aperf;
+       cpu->samples[cpu->sample_ptr].mperf = mperf;
+       cpu->samples[cpu->sample_ptr].aperf -= cpu->prev_aperf;
+       cpu->samples[cpu->sample_ptr].mperf -= cpu->prev_mperf;
+
+       intel_pstate_calc_busy(cpu, &cpu->samples[cpu->sample_ptr]);
 
-       cpu->prev_sample = now;
-       cpu->prev_idle_time_us = idle_time_us;
        cpu->prev_aperf = aperf;
        cpu->prev_mperf = mperf;
 }
@@ -505,16 +465,6 @@ static inline void intel_pstate_set_sample_time(struct cpudata *cpu)
        mod_timer_pinned(&cpu->timer, jiffies + delay);
 }
 
-static inline void intel_pstate_idle_mode(struct cpudata *cpu)
-{
-       cpu->idle_mode = 1;
-}
-
-static inline void intel_pstate_normal_mode(struct cpudata *cpu)
-{
-       cpu->idle_mode = 0;
-}
-
 static inline int intel_pstate_get_scaled_busy(struct cpudata *cpu)
 {
        int32_t busy_scaled;
@@ -547,50 +497,21 @@ static inline void intel_pstate_adjust_busy_pstate(struct cpudata *cpu)
                intel_pstate_pstate_decrease(cpu, steps);
 }
 
-static inline void intel_pstate_adjust_idle_pstate(struct cpudata *cpu)
-{
-       int busy_scaled;
-       struct _pid *pid;
-       int ctl = 0;
-       int steps;
-
-       pid = &cpu->idle_pid;
-
-       busy_scaled = intel_pstate_get_scaled_busy(cpu);
-
-       ctl = pid_calc(pid, 100 - busy_scaled);
-
-       steps = abs(ctl);
-       if (ctl < 0)
-               intel_pstate_pstate_decrease(cpu, steps);
-       else
-               intel_pstate_pstate_increase(cpu, steps);
-
-       if (cpu->pstate.current_pstate == cpu->pstate.min_pstate)
-               intel_pstate_normal_mode(cpu);
-}
-
 static void intel_pstate_timer_func(unsigned long __data)
 {
        struct cpudata *cpu = (struct cpudata *) __data;
 
        intel_pstate_sample(cpu);
+       intel_pstate_adjust_busy_pstate(cpu);
 
-       if (!cpu->idle_mode)
-               intel_pstate_adjust_busy_pstate(cpu);
-       else
-               intel_pstate_adjust_idle_pstate(cpu);
-
-#if defined(XPERF_FIX)
        if (cpu->pstate.current_pstate == cpu->pstate.min_pstate) {
                cpu->min_pstate_count++;
                if (!(cpu->min_pstate_count % 5)) {
                        intel_pstate_set_pstate(cpu, cpu->pstate.max_pstate);
-                       intel_pstate_idle_mode(cpu);
                }
        } else
                cpu->min_pstate_count = 0;
-#endif
+
        intel_pstate_set_sample_time(cpu);
 }
 
@@ -600,6 +521,7 @@ static void intel_pstate_timer_func(unsigned long __data)
 static const struct x86_cpu_id intel_pstate_cpu_ids[] = {
        ICPU(0x2a, default_policy),
        ICPU(0x2d, default_policy),
+       ICPU(0x3a, default_policy),
        {}
 };
 MODULE_DEVICE_TABLE(x86cpu, intel_pstate_cpu_ids);
@@ -631,7 +553,6 @@ static int intel_pstate_init_cpu(unsigned int cpunum)
                (unsigned long)cpu;
        cpu->timer.expires = jiffies + HZ/100;
        intel_pstate_busy_pid_reset(cpu);
-       intel_pstate_idle_pid_reset(cpu);
        intel_pstate_sample(cpu);
        intel_pstate_set_pstate(cpu, cpu->pstate.max_pstate);
 
@@ -675,8 +596,9 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy)
        limits.min_perf_pct = clamp_t(int, limits.min_perf_pct, 0 , 100);
        limits.min_perf = div_fp(int_tofp(limits.min_perf_pct), int_tofp(100));
 
-       limits.max_perf_pct = policy->max * 100 / policy->cpuinfo.max_freq;
-       limits.max_perf_pct = clamp_t(int, limits.max_perf_pct, 0 , 100);
+       limits.max_policy_pct = policy->max * 100 / policy->cpuinfo.max_freq;
+       limits.max_policy_pct = clamp_t(int, limits.max_policy_pct, 0 , 100);
+       limits.max_perf_pct = min(limits.max_policy_pct, limits.max_sysfs_pct);
        limits.max_perf = div_fp(int_tofp(limits.max_perf_pct), int_tofp(100));
 
        return 0;
@@ -788,10 +710,9 @@ static int __init intel_pstate_init(void)
 
        pr_info("Intel P-state driver initializing.\n");
 
-       all_cpu_data = vmalloc(sizeof(void *) * num_possible_cpus());
+       all_cpu_data = vzalloc(sizeof(void *) * num_possible_cpus());
        if (!all_cpu_data)
                return -ENOMEM;
-       memset(all_cpu_data, 0, sizeof(void *) * num_possible_cpus());
 
        rc = cpufreq_register_driver(&intel_pstate_driver);
        if (rc)
index d36ea8d..b2644af 100644 (file)
@@ -171,10 +171,6 @@ static int kirkwood_cpufreq_probe(struct platform_device *pdev)
        priv.dev = &pdev->dev;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(&pdev->dev, "Cannot get memory resource\n");
-               return -ENODEV;
-       }
        priv.base = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(priv.base))
                return PTR_ERR(priv.base);
index 8488957..d539127 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/platform_device.h>
 
 #include <asm/clock.h>
+#include <asm/idle.h>
 
 #include <asm/mach-loongson/loongson.h>
 
@@ -200,6 +201,7 @@ static void loongson2_cpu_wait(void)
        LOONGSON_CHIPCFG0 &= ~0x7;      /* Put CPU into wait mode */
        LOONGSON_CHIPCFG0 = cpu_freq;   /* Restore CPU state */
        spin_unlock_irqrestore(&loongson2_wait_lock, flags);
+       local_irq_enable();
 }
 
 static int __init cpufreq_init(void)
index 765fdf5..bf416a8 100644 (file)
@@ -1154,7 +1154,7 @@ static struct aead_edesc *aead_edesc_alloc(struct aead_request *req,
                dst_nents = sg_count(req->dst, req->cryptlen, &dst_chained);
 
        sgc = dma_map_sg_chained(jrdev, req->assoc, assoc_nents ? : 1,
-                                DMA_BIDIRECTIONAL, assoc_chained);
+                                DMA_TO_DEVICE, assoc_chained);
        if (likely(req->src == req->dst)) {
                sgc = dma_map_sg_chained(jrdev, req->src, src_nents ? : 1,
                                         DMA_BIDIRECTIONAL, src_chained);
@@ -1336,7 +1336,7 @@ static struct aead_edesc *aead_giv_edesc_alloc(struct aead_givcrypt_request
                dst_nents = sg_count(req->dst, req->cryptlen, &dst_chained);
 
        sgc = dma_map_sg_chained(jrdev, req->assoc, assoc_nents ? : 1,
-                                DMA_BIDIRECTIONAL, assoc_chained);
+                                DMA_TO_DEVICE, assoc_chained);
        if (likely(req->src == req->dst)) {
                sgc = dma_map_sg_chained(jrdev, req->src, src_nents ? : 1,
                                         DMA_BIDIRECTIONAL, src_chained);
index a76d4c4..35d483f 100644 (file)
@@ -126,6 +126,7 @@ struct crypto_alg nx_cbc_aes_alg = {
        .cra_blocksize   = AES_BLOCK_SIZE,
        .cra_ctxsize     = sizeof(struct nx_crypto_ctx),
        .cra_type        = &crypto_blkcipher_type,
+       .cra_alignmask   = 0xf,
        .cra_module      = THIS_MODULE,
        .cra_init        = nx_crypto_ctx_aes_cbc_init,
        .cra_exit        = nx_crypto_ctx_exit,
index ba5f161..7bbc9a8 100644 (file)
@@ -123,6 +123,7 @@ struct crypto_alg nx_ecb_aes_alg = {
        .cra_priority    = 300,
        .cra_flags       = CRYPTO_ALG_TYPE_BLKCIPHER,
        .cra_blocksize   = AES_BLOCK_SIZE,
+       .cra_alignmask   = 0xf,
        .cra_ctxsize     = sizeof(struct nx_crypto_ctx),
        .cra_type        = &crypto_blkcipher_type,
        .cra_module      = THIS_MODULE,
index c8109ed..6cca6c3 100644 (file)
@@ -219,7 +219,7 @@ static int gcm_aes_nx_crypt(struct aead_request *req, int enc)
        if (enc)
                NX_CPB_FDM(csbcpb) |= NX_FDM_ENDE_ENCRYPT;
        else
-               nbytes -= AES_BLOCK_SIZE;
+               nbytes -= crypto_aead_authsize(crypto_aead_reqtfm(req));
 
        csbcpb->cpb.aes_gcm.bit_length_data = nbytes * 8;
 
index 9767315..67024f2 100644 (file)
@@ -69,7 +69,7 @@ static int nx_sha256_update(struct shash_desc *desc, const u8 *data,
         *  1: <= SHA256_BLOCK_SIZE: copy into state, return 0
         *  2: > SHA256_BLOCK_SIZE: process X blocks, copy in leftover
         */
-       if (len + sctx->count <= SHA256_BLOCK_SIZE) {
+       if (len + sctx->count < SHA256_BLOCK_SIZE) {
                memcpy(sctx->buf + sctx->count, data, len);
                sctx->count += len;
                goto out;
@@ -110,7 +110,8 @@ static int nx_sha256_update(struct shash_desc *desc, const u8 *data,
        atomic_inc(&(nx_ctx->stats->sha256_ops));
 
        /* copy the leftover back into the state struct */
-       memcpy(sctx->buf, data + len - leftover, leftover);
+       if (leftover)
+               memcpy(sctx->buf, data + len - leftover, leftover);
        sctx->count = leftover;
 
        csbcpb->cpb.sha256.message_bit_length += (u64)
@@ -130,6 +131,7 @@ static int nx_sha256_final(struct shash_desc *desc, u8 *out)
        struct nx_sg *in_sg, *out_sg;
        int rc;
 
+
        if (NX_CPB_FDM(csbcpb) & NX_FDM_CONTINUATION) {
                /* we've hit the nx chip previously, now we're finalizing,
                 * so copy over the partial digest */
@@ -162,7 +164,7 @@ static int nx_sha256_final(struct shash_desc *desc, u8 *out)
 
        atomic_inc(&(nx_ctx->stats->sha256_ops));
 
-       atomic64_add(csbcpb->cpb.sha256.message_bit_length,
+       atomic64_add(csbcpb->cpb.sha256.message_bit_length / 8,
                     &(nx_ctx->stats->sha256_bytes));
        memcpy(out, csbcpb->cpb.sha256.message_digest, SHA256_DIGEST_SIZE);
 out:
index 3177b8c..08eee11 100644 (file)
@@ -69,7 +69,7 @@ static int nx_sha512_update(struct shash_desc *desc, const u8 *data,
         *  1: <= SHA512_BLOCK_SIZE: copy into state, return 0
         *  2: > SHA512_BLOCK_SIZE: process X blocks, copy in leftover
         */
-       if ((u64)len + sctx->count[0] <= SHA512_BLOCK_SIZE) {
+       if ((u64)len + sctx->count[0] < SHA512_BLOCK_SIZE) {
                memcpy(sctx->buf + sctx->count[0], data, len);
                sctx->count[0] += len;
                goto out;
@@ -110,7 +110,8 @@ static int nx_sha512_update(struct shash_desc *desc, const u8 *data,
        atomic_inc(&(nx_ctx->stats->sha512_ops));
 
        /* copy the leftover back into the state struct */
-       memcpy(sctx->buf, data + len - leftover, leftover);
+       if (leftover)
+               memcpy(sctx->buf, data + len - leftover, leftover);
        sctx->count[0] = leftover;
 
        spbc_bits = csbcpb->cpb.sha512.spbc * 8;
@@ -168,7 +169,7 @@ static int nx_sha512_final(struct shash_desc *desc, u8 *out)
                goto out;
 
        atomic_inc(&(nx_ctx->stats->sha512_ops));
-       atomic64_add(csbcpb->cpb.sha512.message_bit_length_lo,
+       atomic64_add(csbcpb->cpb.sha512.message_bit_length_lo / 8,
                     &(nx_ctx->stats->sha512_bytes));
 
        memcpy(out, csbcpb->cpb.sha512.message_digest, SHA512_DIGEST_SIZE);
index c767f23..bbdab6e 100644 (file)
@@ -211,44 +211,20 @@ int nx_build_sg_lists(struct nx_crypto_ctx  *nx_ctx,
 {
        struct nx_sg *nx_insg = nx_ctx->in_sg;
        struct nx_sg *nx_outsg = nx_ctx->out_sg;
-       struct blkcipher_walk walk;
-       int rc;
-
-       blkcipher_walk_init(&walk, dst, src, nbytes);
-       rc = blkcipher_walk_virt_block(desc, &walk, AES_BLOCK_SIZE);
-       if (rc)
-               goto out;
 
        if (iv)
-               memcpy(iv, walk.iv, AES_BLOCK_SIZE);
+               memcpy(iv, desc->info, AES_BLOCK_SIZE);
 
-       while (walk.nbytes) {
-               nx_insg = nx_build_sg_list(nx_insg, walk.src.virt.addr,
-                                          walk.nbytes, nx_ctx->ap->sglen);
-               nx_outsg = nx_build_sg_list(nx_outsg, walk.dst.virt.addr,
-                                           walk.nbytes, nx_ctx->ap->sglen);
-
-               rc = blkcipher_walk_done(desc, &walk, 0);
-               if (rc)
-                       break;
-       }
-
-       if (walk.nbytes) {
-               nx_insg = nx_build_sg_list(nx_insg, walk.src.virt.addr,
-                                          walk.nbytes, nx_ctx->ap->sglen);
-               nx_outsg = nx_build_sg_list(nx_outsg, walk.dst.virt.addr,
-                                           walk.nbytes, nx_ctx->ap->sglen);
-
-               rc = 0;
-       }
+       nx_insg = nx_walk_and_build(nx_insg, nx_ctx->ap->sglen, src, 0, nbytes);
+       nx_outsg = nx_walk_and_build(nx_outsg, nx_ctx->ap->sglen, dst, 0, nbytes);
 
        /* these lengths should be negative, which will indicate to phyp that
         * the input and output parameters are scatterlists, not linear
         * buffers */
        nx_ctx->op.inlen = (nx_ctx->in_sg - nx_insg) * sizeof(struct nx_sg);
        nx_ctx->op.outlen = (nx_ctx->out_sg - nx_outsg) * sizeof(struct nx_sg);
-out:
-       return rc;
+
+       return 0;
 }
 
 /**
@@ -454,6 +430,8 @@ static int nx_register_algs(void)
        if (rc)
                goto out;
 
+       nx_driver.of.status = NX_OKAY;
+
        rc = crypto_register_alg(&nx_ecb_aes_alg);
        if (rc)
                goto out;
@@ -498,8 +476,6 @@ static int nx_register_algs(void)
        if (rc)
                goto out_unreg_s512;
 
-       nx_driver.of.status = NX_OKAY;
-
        goto out;
 
 out_unreg_s512:
index a97bb6c..c3dc1c0 100644 (file)
@@ -863,7 +863,7 @@ static struct of_device_id sahara_dt_ids[] = {
        { .compatible = "fsl,imx27-sahara" },
        { /* sentinel */ }
 };
-MODULE_DEVICE_TABLE(platform, sahara_dt_ids);
+MODULE_DEVICE_TABLE(of, sahara_dt_ids);
 
 static int sahara_probe(struct platform_device *pdev)
 {
index ba6fc62..5a18f82 100644 (file)
@@ -4,7 +4,8 @@
  * Based on of-dma.c
  *
  * Copyright (C) 2013, Intel Corporation
- * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+ * Authors: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+ *         Mika Westerberg <mika.westerberg@linux.intel.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
 #include <linux/list.h>
 #include <linux/mutex.h>
 #include <linux/slab.h>
+#include <linux/ioport.h>
 #include <linux/acpi.h>
 #include <linux/acpi_dma.h>
 
 static LIST_HEAD(acpi_dma_list);
 static DEFINE_MUTEX(acpi_dma_lock);
 
+/**
+ * acpi_dma_parse_resource_group - match device and parse resource group
+ * @grp:       CSRT resource group
+ * @adev:      ACPI device to match with
+ * @adma:      struct acpi_dma of the given DMA controller
+ *
+ * Returns 1 on success, 0 when no information is available, or appropriate
+ * errno value on error.
+ *
+ * In order to match a device from DSDT table to the corresponding CSRT device
+ * we use MMIO address and IRQ.
+ */
+static int acpi_dma_parse_resource_group(const struct acpi_csrt_group *grp,
+               struct acpi_device *adev, struct acpi_dma *adma)
+{
+       const struct acpi_csrt_shared_info *si;
+       struct list_head resource_list;
+       struct resource_list_entry *rentry;
+       resource_size_t mem = 0, irq = 0;
+       u32 vendor_id;
+       int ret;
+
+       if (grp->shared_info_length != sizeof(struct acpi_csrt_shared_info))
+               return -ENODEV;
+
+       INIT_LIST_HEAD(&resource_list);
+       ret = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
+       if (ret <= 0)
+               return 0;
+
+       list_for_each_entry(rentry, &resource_list, node) {
+               if (resource_type(&rentry->res) == IORESOURCE_MEM)
+                       mem = rentry->res.start;
+               else if (resource_type(&rentry->res) == IORESOURCE_IRQ)
+                       irq = rentry->res.start;
+       }
+
+       acpi_dev_free_resource_list(&resource_list);
+
+       /* Consider initial zero values as resource not found */
+       if (mem == 0 && irq == 0)
+               return 0;
+
+       si = (const struct acpi_csrt_shared_info *)&grp[1];
+
+       /* Match device by MMIO and IRQ */
+       if (si->mmio_base_low != mem || si->gsi_interrupt != irq)
+               return 0;
+
+       vendor_id = le32_to_cpu(grp->vendor_id);
+       dev_dbg(&adev->dev, "matches with %.4s%04X (rev %u)\n",
+               (char *)&vendor_id, grp->device_id, grp->revision);
+
+       /* Check if the request line range is available */
+       if (si->base_request_line == 0 && si->num_handshake_signals == 0)
+               return 0;
+
+       adma->base_request_line = si->base_request_line;
+       adma->end_request_line = si->base_request_line +
+                                si->num_handshake_signals - 1;
+
+       dev_dbg(&adev->dev, "request line base: 0x%04x end: 0x%04x\n",
+               adma->base_request_line, adma->end_request_line);
+
+       return 1;
+}
+
+/**
+ * acpi_dma_parse_csrt - parse CSRT to exctract additional DMA resources
+ * @adev:      ACPI device to match with
+ * @adma:      struct acpi_dma of the given DMA controller
+ *
+ * CSRT or Core System Resources Table is a proprietary ACPI table
+ * introduced by Microsoft. This table can contain devices that are not in
+ * the system DSDT table. In particular DMA controllers might be described
+ * here.
+ *
+ * We are using this table to get the request line range of the specific DMA
+ * controller to be used later.
+ *
+ */
+static void acpi_dma_parse_csrt(struct acpi_device *adev, struct acpi_dma *adma)
+{
+       struct acpi_csrt_group *grp, *end;
+       struct acpi_table_csrt *csrt;
+       acpi_status status;
+       int ret;
+
+       status = acpi_get_table(ACPI_SIG_CSRT, 0,
+                               (struct acpi_table_header **)&csrt);
+       if (ACPI_FAILURE(status)) {
+               if (status != AE_NOT_FOUND)
+                       dev_warn(&adev->dev, "failed to get the CSRT table\n");
+               return;
+       }
+
+       grp = (struct acpi_csrt_group *)(csrt + 1);
+       end = (struct acpi_csrt_group *)((void *)csrt + csrt->header.length);
+
+       while (grp < end) {
+               ret = acpi_dma_parse_resource_group(grp, adev, adma);
+               if (ret < 0) {
+                       dev_warn(&adev->dev,
+                                "error in parsing resource group\n");
+                       return;
+               }
+
+               grp = (struct acpi_csrt_group *)((void *)grp + grp->length);
+       }
+}
+
 /**
  * acpi_dma_controller_register - Register a DMA controller to ACPI DMA helpers
  * @dev:               struct device of DMA controller
@@ -61,6 +174,8 @@ int acpi_dma_controller_register(struct device *dev,
        adma->acpi_dma_xlate = acpi_dma_xlate;
        adma->data = data;
 
+       acpi_dma_parse_csrt(adev, adma);
+
        /* Now queue acpi_dma controller structure in list */
        mutex_lock(&acpi_dma_lock);
        list_add_tail(&adma->dma_controllers, &acpi_dma_list);
@@ -149,6 +264,45 @@ void devm_acpi_dma_controller_free(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(devm_acpi_dma_controller_free);
 
+/**
+ * acpi_dma_update_dma_spec - prepare dma specifier to pass to translation function
+ * @adma:      struct acpi_dma of DMA controller
+ * @dma_spec:  dma specifier to update
+ *
+ * Returns 0, if no information is avaiable, -1 on mismatch, and 1 otherwise.
+ *
+ * Accordingly to ACPI 5.0 Specification Table 6-170 "Fixed DMA Resource
+ * Descriptor":
+ *     DMA Request Line bits is a platform-relative number uniquely
+ *     identifying the request line assigned. Request line-to-Controller
+ *     mapping is done in a controller-specific OS driver.
+ * That's why we can safely adjust slave_id when the appropriate controller is
+ * found.
+ */
+static int acpi_dma_update_dma_spec(struct acpi_dma *adma,
+               struct acpi_dma_spec *dma_spec)
+{
+       /* Set link to the DMA controller device */
+       dma_spec->dev = adma->dev;
+
+       /* Check if the request line range is available */
+       if (adma->base_request_line == 0 && adma->end_request_line == 0)
+               return 0;
+
+       /* Check if slave_id falls to the range */
+       if (dma_spec->slave_id < adma->base_request_line ||
+           dma_spec->slave_id > adma->end_request_line)
+               return -1;
+
+       /*
+        * Here we adjust slave_id. It should be a relative number to the base
+        * request line.
+        */
+       dma_spec->slave_id -= adma->base_request_line;
+
+       return 1;
+}
+
 struct acpi_dma_parser_data {
        struct acpi_dma_spec dma_spec;
        size_t index;
@@ -193,6 +347,7 @@ struct dma_chan *acpi_dma_request_slave_chan_by_index(struct device *dev,
        struct acpi_device *adev;
        struct acpi_dma *adma;
        struct dma_chan *chan = NULL;
+       int found;
 
        /* Check if the device was enumerated by ACPI */
        if (!dev || !ACPI_HANDLE(dev))
@@ -219,9 +374,20 @@ struct dma_chan *acpi_dma_request_slave_chan_by_index(struct device *dev,
        mutex_lock(&acpi_dma_lock);
 
        list_for_each_entry(adma, &acpi_dma_list, dma_controllers) {
-               dma_spec->dev = adma->dev;
+               /*
+                * We are not going to call translation function if slave_id
+                * doesn't fall to the request range.
+                */
+               found = acpi_dma_update_dma_spec(adma, dma_spec);
+               if (found < 0)
+                       continue;
                chan = adma->acpi_dma_xlate(dma_spec, adma);
-               if (chan)
+               /*
+                * Try to get a channel only from the DMA controller that
+                * matches the slave_id. See acpi_dma_update_dma_spec()
+                * description for the details.
+                */
+               if (found > 0 || chan)
                        break;
        }
 
index d8ce4ec..e88ded2 100644 (file)
@@ -716,8 +716,7 @@ static int dmatest_func(void *data)
                }
                dma_async_issue_pending(chan);
 
-               wait_event_freezable_timeout(done_wait,
-                                            done.done || kthread_should_stop(),
+               wait_event_freezable_timeout(done_wait, done.done,
                                             msecs_to_jiffies(params->timeout));
 
                status = dma_async_is_tx_complete(chan, cookie, NULL, NULL);
@@ -997,7 +996,6 @@ static void stop_threaded_test(struct dmatest_info *info)
 static int __restart_threaded_test(struct dmatest_info *info, bool run)
 {
        struct dmatest_params *params = &info->params;
-       int ret;
 
        /* Stop any running test first */
        __stop_threaded_test(info);
@@ -1012,13 +1010,23 @@ static int __restart_threaded_test(struct dmatest_info *info, bool run)
        memcpy(params, &info->dbgfs_params, sizeof(*params));
 
        /* Run test with new parameters */
-       ret = __run_threaded_test(info);
-       if (ret) {
-               __stop_threaded_test(info);
-               pr_err("dmatest: Can't run test\n");
+       return __run_threaded_test(info);
+}
+
+static bool __is_threaded_test_run(struct dmatest_info *info)
+{
+       struct dmatest_chan *dtc;
+
+       list_for_each_entry(dtc, &info->channels, node) {
+               struct dmatest_thread *thread;
+
+               list_for_each_entry(thread, &dtc->threads, node) {
+                       if (!thread->done)
+                               return true;
+               }
        }
 
-       return ret;
+       return false;
 }
 
 static ssize_t dtf_write_string(void *to, size_t available, loff_t *ppos,
@@ -1091,22 +1099,10 @@ static ssize_t dtf_read_run(struct file *file, char __user *user_buf,
 {
        struct dmatest_info *info = file->private_data;
        char buf[3];
-       struct dmatest_chan *dtc;
-       bool alive = false;
 
        mutex_lock(&info->lock);
-       list_for_each_entry(dtc, &info->channels, node) {
-               struct dmatest_thread *thread;
-
-               list_for_each_entry(thread, &dtc->threads, node) {
-                       if (!thread->done) {
-                               alive = true;
-                               break;
-                       }
-               }
-       }
 
-       if (alive) {
+       if (__is_threaded_test_run(info)) {
                buf[0] = 'Y';
        } else {
                __stop_threaded_test(info);
@@ -1132,7 +1128,12 @@ static ssize_t dtf_write_run(struct file *file, const char __user *user_buf,
 
        if (strtobool(buf, &bv) == 0) {
                mutex_lock(&info->lock);
-               ret = __restart_threaded_test(info, bv);
+
+               if (__is_threaded_test_run(info))
+                       ret = -EBUSY;
+               else
+                       ret = __restart_threaded_test(info, bv);
+
                mutex_unlock(&info->lock);
        }
 
index 1734fee..71bf4ec 100644 (file)
@@ -1566,10 +1566,12 @@ static void dma_tc_handle(struct d40_chan *d40c)
                        return;
                }
 
-               if (d40_queue_start(d40c) == NULL)
+               if (d40_queue_start(d40c) == NULL) {
                        d40c->busy = false;
-               pm_runtime_mark_last_busy(d40c->base->dev);
-               pm_runtime_put_autosuspend(d40c->base->dev);
+
+                       pm_runtime_mark_last_busy(d40c->base->dev);
+                       pm_runtime_put_autosuspend(d40c->base->dev);
+               }
 
                d40_desc_remove(d40d);
                d40_desc_done(d40c, d40d);
index ce19340..33f59ec 100644 (file)
@@ -1273,11 +1273,6 @@ static int tegra_dma_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, tdma);
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(&pdev->dev, "No mem resource for DMA\n");
-               return -EINVAL;
-       }
-
        tdma->base_addr = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(tdma->base_addr))
                return PTR_ERR(tdma->base_addr);
index 8c171fa..845f047 100644 (file)
@@ -202,9 +202,9 @@ static DEVICE_ATTR(inject_word, S_IRUGO | S_IWUSR,
                   amd64_inject_word_show, amd64_inject_word_store);
 static DEVICE_ATTR(inject_ecc_vector, S_IRUGO | S_IWUSR,
                   amd64_inject_ecc_vector_show, amd64_inject_ecc_vector_store);
-static DEVICE_ATTR(inject_write, S_IRUGO | S_IWUSR,
+static DEVICE_ATTR(inject_write, S_IWUSR,
                   NULL, amd64_inject_write_store);
-static DEVICE_ATTR(inject_read, S_IRUGO | S_IWUSR,
+static DEVICE_ATTR(inject_read,  S_IWUSR,
                   NULL, amd64_inject_read_store);
 
 
index b623c59..8bd1bb6 100644 (file)
@@ -523,13 +523,11 @@ static void efivar_update_sysfs_entries(struct work_struct *work)
        struct efivar_entry *entry;
        int err;
 
-       entry = kzalloc(sizeof(*entry), GFP_KERNEL);
-       if (!entry)
-               return;
-
        /* Add new sysfs entries */
        while (1) {
-               memset(entry, 0, sizeof(*entry));
+               entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+               if (!entry)
+                       return;
 
                err = efivar_init(efivar_update_sysfs_entry, entry,
                                  true, false, &efivar_sysfs_list);
index 87d5670..573c449 100644 (file)
@@ -636,7 +636,7 @@ config GPIO_MAX7301
 
 config GPIO_MCP23S08
        tristate "Microchip MCP23xxx I/O expander"
-       depends on SPI_MASTER || I2C
+       depends on (SPI_MASTER && !I2C) || I2C
        help
          SPI/I2C driver for Microchip MCP23S08/MCP23S17/MCP23008/MCP23017
          I/O expanders.
index 634c3d3..62ef10a 100644 (file)
@@ -324,6 +324,7 @@ static int lnw_gpio_probe(struct pci_dev *pdev,
        resource_size_t start, len;
        struct lnw_gpio *lnw;
        u32 gpio_base;
+       u32 irq_base;
        int retval;
        int ngpio = id->driver_data;
 
@@ -345,6 +346,7 @@ static int lnw_gpio_probe(struct pci_dev *pdev,
                retval = -EFAULT;
                goto err_ioremap;
        }
+       irq_base = *(u32 *)base;
        gpio_base = *((u32 *)base + 1);
        /* release the IO mapping, since we already get the info from bar1 */
        iounmap(base);
@@ -365,13 +367,6 @@ static int lnw_gpio_probe(struct pci_dev *pdev,
                goto err_ioremap;
        }
 
-       lnw->domain = irq_domain_add_linear(pdev->dev.of_node, ngpio,
-                                           &lnw_gpio_irq_ops, lnw);
-       if (!lnw->domain) {
-               retval = -ENOMEM;
-               goto err_ioremap;
-       }
-
        lnw->reg_base = base;
        lnw->chip.label = dev_name(&pdev->dev);
        lnw->chip.request = lnw_gpio_request;
@@ -384,6 +379,14 @@ static int lnw_gpio_probe(struct pci_dev *pdev,
        lnw->chip.ngpio = ngpio;
        lnw->chip.can_sleep = 0;
        lnw->pdev = pdev;
+
+       lnw->domain = irq_domain_add_simple(pdev->dev.of_node, ngpio, irq_base,
+                                           &lnw_gpio_irq_ops, lnw);
+       if (!lnw->domain) {
+               retval = -ENOMEM;
+               goto err_ioremap;
+       }
+
        pci_set_drvdata(pdev, lnw);
        retval = gpiochip_add(&lnw->chip);
        if (retval) {
index b733665..0966f26 100644 (file)
@@ -496,8 +496,7 @@ err_irq_alloc_descs:
 err_gpiochip_add:
        while (--i >= 0) {
                chip--;
-               ret = gpiochip_remove(&chip->gpio);
-               if (ret)
+               if (gpiochip_remove(&chip->gpio))
                        dev_err(&pdev->dev, "Failed gpiochip_remove(%d)\n", i);
        }
        kfree(chip_save);
index bf69a7e..3a4816a 100644 (file)
@@ -619,11 +619,6 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
         * per-CPU registers */
        if (soc_variant == MVEBU_GPIO_SOC_VARIANT_ARMADAXP) {
                res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-               if (!res) {
-                       dev_err(&pdev->dev, "Cannot get memory resource\n");
-                       return -ENODEV;
-               }
-
                mvchip->percpu_membase = devm_ioremap_resource(&pdev->dev,
                                                               res);
                if (IS_ERR(mvchip->percpu_membase))
index 25000b0..f8e6af2 100644 (file)
@@ -326,7 +326,8 @@ static int mxs_gpio_probe(struct platform_device *pdev)
 
        err = bgpio_init(&port->bgc, &pdev->dev, 4,
                         port->base + PINCTRL_DIN(port),
-                        port->base + PINCTRL_DOUT(port), NULL,
+                        port->base + PINCTRL_DOUT(port) + MXS_SET,
+                        port->base + PINCTRL_DOUT(port) + MXS_CLR,
                         port->base + PINCTRL_DOE(port), NULL, 0);
        if (err)
                goto out_irqdesc_free;
index 2050891..d3f7d2d 100644 (file)
@@ -69,6 +69,7 @@ struct gpio_bank {
        bool is_mpuio;
        bool dbck_flag;
        bool loses_context;
+       bool context_valid;
        int stride;
        u32 width;
        int context_loss_count;
@@ -1128,6 +1129,10 @@ static int omap_gpio_probe(struct platform_device *pdev)
                        bank->loses_context = true;
        } else {
                bank->loses_context = pdata->loses_context;
+
+               if (bank->loses_context)
+                       bank->get_context_loss_count =
+                               pdata->get_context_loss_count;
        }
 
 
@@ -1178,9 +1183,6 @@ static int omap_gpio_probe(struct platform_device *pdev)
        omap_gpio_chip_init(bank);
        omap_gpio_show_rev(bank);
 
-       if (bank->loses_context)
-               bank->get_context_loss_count = pdata->get_context_loss_count;
-
        pm_runtime_put(bank->dev);
 
        list_add_tail(&bank->node, &omap_gpio_list);
@@ -1259,6 +1261,8 @@ update_gpio_context_count:
        return 0;
 }
 
+static void omap_gpio_init_context(struct gpio_bank *p);
+
 static int omap_gpio_runtime_resume(struct device *dev)
 {
        struct platform_device *pdev = to_platform_device(dev);
@@ -1268,6 +1272,20 @@ static int omap_gpio_runtime_resume(struct device *dev)
        int c;
 
        spin_lock_irqsave(&bank->lock, flags);
+
+       /*
+        * On the first resume during the probe, the context has not
+        * been initialised and so initialise it now. Also initialise
+        * the context loss count.
+        */
+       if (bank->loses_context && !bank->context_valid) {
+               omap_gpio_init_context(bank);
+
+               if (bank->get_context_loss_count)
+                       bank->context_loss_count =
+                               bank->get_context_loss_count(bank->dev);
+       }
+
        _gpio_dbck_enable(bank);
 
        /*
@@ -1384,6 +1402,29 @@ void omap2_gpio_resume_after_idle(void)
 }
 
 #if defined(CONFIG_PM_RUNTIME)
+static void omap_gpio_init_context(struct gpio_bank *p)
+{
+       struct omap_gpio_reg_offs *regs = p->regs;
+       void __iomem *base = p->base;
+
+       p->context.ctrl         = __raw_readl(base + regs->ctrl);
+       p->context.oe           = __raw_readl(base + regs->direction);
+       p->context.wake_en      = __raw_readl(base + regs->wkup_en);
+       p->context.leveldetect0 = __raw_readl(base + regs->leveldetect0);
+       p->context.leveldetect1 = __raw_readl(base + regs->leveldetect1);
+       p->context.risingdetect = __raw_readl(base + regs->risingdetect);
+       p->context.fallingdetect = __raw_readl(base + regs->fallingdetect);
+       p->context.irqenable1   = __raw_readl(base + regs->irqenable);
+       p->context.irqenable2   = __raw_readl(base + regs->irqenable2);
+
+       if (regs->set_dataout && p->regs->clr_dataout)
+               p->context.dataout = __raw_readl(base + regs->set_dataout);
+       else
+               p->context.dataout = __raw_readl(base + regs->dataout);
+
+       p->context_valid = true;
+}
+
 static void omap_gpio_restore_context(struct gpio_bank *bank)
 {
        __raw_writel(bank->context.wake_en,
@@ -1421,6 +1462,7 @@ static void omap_gpio_restore_context(struct gpio_bank *bank)
 #else
 #define omap_gpio_runtime_suspend NULL
 #define omap_gpio_runtime_resume NULL
+static void omap_gpio_init_context(struct gpio_bank *p) {}
 #endif
 
 static const struct dev_pm_ops gpio_pm_ops = {
index cdf5996..0fec097 100644 (file)
@@ -424,8 +424,7 @@ end:
 err_request_irq:
        irq_free_descs(irq_base, gpio_pins[chip->ioh]);
 
-       ret = gpiochip_remove(&chip->gpio);
-       if (ret)
+       if (gpiochip_remove(&chip->gpio))
                dev_err(&pdev->dev, "%s gpiochip_remove failed\n", __func__);
 
 err_gpiochip_add:
index 1e4de16..5af6571 100644 (file)
@@ -272,10 +272,8 @@ static int sch_gpio_probe(struct platform_device *pdev)
        return 0;
 
 err_sch_gpio_resume:
-       err = gpiochip_remove(&sch_gpio_core);
-       if (err)
-               dev_err(&pdev->dev, "%s failed, %d\n",
-                               "gpiochip_remove()", err);
+       if (gpiochip_remove(&sch_gpio_core))
+               dev_err(&pdev->dev, "%s gpiochip_remove failed\n", __func__);
 
 err_sch_gpio_core:
        release_region(res->start, resource_size(res));
index da4cb5b..9a62672 100644 (file)
@@ -463,11 +463,6 @@ static int tegra_gpio_probe(struct platform_device *pdev)
        }
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(&pdev->dev, "Missing MEM resource\n");
-               return -ENODEV;
-       }
-
        regs = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(regs))
                return PTR_ERR(regs);
index 095ab14..5ac2919 100644 (file)
@@ -446,7 +446,8 @@ static int vprbrd_gpio_probe(struct platform_device *pdev)
        return ret;
 
 err_gpiob:
-       ret = gpiochip_remove(&vb_gpio->gpioa);
+       if (gpiochip_remove(&vb_gpio->gpioa))
+               dev_err(&pdev->dev, "%s gpiochip_remove failed\n", __func__);
 
 err_gpioa:
        return ret;
index 3a8f7e6..e7e9242 100644 (file)
@@ -78,6 +78,10 @@ void drm_warn_on_modeset_not_all_locked(struct drm_device *dev)
 {
        struct drm_crtc *crtc;
 
+       /* Locking is currently fubar in the panic handler. */
+       if (oops_in_progress)
+               return;
+
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
                WARN_ON(!mutex_is_locked(&crtc->mutex));
 
@@ -246,6 +250,7 @@ char *drm_get_connector_status_name(enum drm_connector_status status)
        else
                return "unknown";
 }
+EXPORT_SYMBOL(drm_get_connector_status_name);
 
 /**
  * drm_mode_object_get - allocate a new modeset identifier
index e974f93..ed1334e 100644 (file)
@@ -121,6 +121,7 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
                connector->helper_private;
        int count = 0;
        int mode_flags = 0;
+       bool verbose_prune = true;
 
        DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id,
                        drm_get_connector_name(connector));
@@ -149,6 +150,7 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
                DRM_DEBUG_KMS("[CONNECTOR:%d:%s] disconnected\n",
                        connector->base.id, drm_get_connector_name(connector));
                drm_mode_connector_update_edid_property(connector, NULL);
+               verbose_prune = false;
                goto prune;
        }
 
@@ -182,7 +184,7 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
        }
 
 prune:
-       drm_mode_prune_invalid(dev, &connector->modes, true);
+       drm_mode_prune_invalid(dev, &connector->modes, verbose_prune);
 
        if (list_empty(&connector->modes))
                return 0;
@@ -1005,12 +1007,20 @@ static void output_poll_execute(struct work_struct *work)
                        continue;
 
                connector->status = connector->funcs->detect(connector, false);
-               DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %d to %d\n",
-                             connector->base.id,
-                             drm_get_connector_name(connector),
-                             old_status, connector->status);
-               if (old_status != connector->status)
+               if (old_status != connector->status) {
+                       const char *old, *new;
+
+                       old = drm_get_connector_status_name(old_status);
+                       new = drm_get_connector_status_name(connector->status);
+
+                       DRM_DEBUG_KMS("[CONNECTOR:%d:%s] "
+                                     "status updated from %s to %s\n",
+                                     connector->base.id,
+                                     drm_get_connector_name(connector),
+                                     old, new);
+
                        changed = true;
+               }
        }
 
        mutex_unlock(&dev->mode_config.mutex);
@@ -1083,10 +1093,11 @@ void drm_helper_hpd_irq_event(struct drm_device *dev)
                old_status = connector->status;
 
                connector->status = connector->funcs->detect(connector, false);
-               DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %d to %d\n",
+               DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %s to %s\n",
                              connector->base.id,
                              drm_get_connector_name(connector),
-                             old_status, connector->status);
+                             drm_get_connector_status_name(old_status),
+                             drm_get_connector_status_name(connector->status));
                if (old_status != connector->status)
                        changed = true;
        }
index 8d4f290..9cc247f 100644 (file)
@@ -57,7 +57,7 @@ static int drm_version(struct drm_device *dev, void *data,
                       struct drm_file *file_priv);
 
 #define DRM_IOCTL_DEF(ioctl, _func, _flags) \
-       [DRM_IOCTL_NR(ioctl)] = {.cmd = ioctl, .func = _func, .flags = _flags, .cmd_drv = 0}
+       [DRM_IOCTL_NR(ioctl)] = {.cmd = ioctl, .func = _func, .flags = _flags, .cmd_drv = 0, .name = #ioctl}
 
 /** Ioctl table */
 static const struct drm_ioctl_desc drm_ioctls[] = {
@@ -375,7 +375,7 @@ long drm_ioctl(struct file *filp,
 {
        struct drm_file *file_priv = filp->private_data;
        struct drm_device *dev;
-       const struct drm_ioctl_desc *ioctl;
+       const struct drm_ioctl_desc *ioctl = NULL;
        drm_ioctl_t *func;
        unsigned int nr = DRM_IOCTL_NR(cmd);
        int retcode = -EINVAL;
@@ -392,11 +392,6 @@ long drm_ioctl(struct file *filp,
        atomic_inc(&dev->counts[_DRM_STAT_IOCTLS]);
        ++file_priv->ioctl_count;
 
-       DRM_DEBUG("pid=%d, cmd=0x%02x, nr=0x%02x, dev 0x%lx, auth=%d\n",
-                 task_pid_nr(current), cmd, nr,
-                 (long)old_encode_dev(file_priv->minor->device),
-                 file_priv->authenticated);
-
        if ((nr >= DRM_CORE_IOCTL_COUNT) &&
            ((nr < DRM_COMMAND_BASE) || (nr >= DRM_COMMAND_END)))
                goto err_i1;
@@ -417,6 +412,11 @@ long drm_ioctl(struct file *filp,
        } else
                goto err_i1;
 
+       DRM_DEBUG("pid=%d, dev=0x%lx, auth=%d, %s\n",
+                 task_pid_nr(current),
+                 (long)old_encode_dev(file_priv->minor->device),
+                 file_priv->authenticated, ioctl->name);
+
        /* Do not trust userspace, use our own definition */
        func = ioctl->func;
        /* is there a local override? */
@@ -471,6 +471,12 @@ long drm_ioctl(struct file *filp,
        }
 
       err_i1:
+       if (!ioctl)
+               DRM_DEBUG("invalid iotcl: pid=%d, dev=0x%lx, auth=%d, cmd=0x%02x, nr=0x%02x\n",
+                         task_pid_nr(current),
+                         (long)old_encode_dev(file_priv->minor->device),
+                         file_priv->authenticated, cmd, nr);
+
        if (kdata != stack_kdata)
                kfree(kdata);
        atomic_dec(&dev->ioctl_count);
index 48c52f7..0cfb60f 100644 (file)
@@ -54,16 +54,12 @@ int drm_i2c_encoder_init(struct drm_device *dev,
                         struct i2c_adapter *adap,
                         const struct i2c_board_info *info)
 {
-       char modalias[sizeof(I2C_MODULE_PREFIX)
-                     + I2C_NAME_SIZE];
        struct module *module = NULL;
        struct i2c_client *client;
        struct drm_i2c_encoder_driver *encoder_drv;
        int err = 0;
 
-       snprintf(modalias, sizeof(modalias),
-                "%s%s", I2C_MODULE_PREFIX, info->type);
-       request_module(modalias);
+       request_module("%s%s", I2C_MODULE_PREFIX, info->type);
 
        client = i2c_new_device(adap, info);
        if (!client) {
index a6a8643..8bcce78 100644 (file)
@@ -1054,7 +1054,7 @@ EXPORT_SYMBOL(drm_vblank_off);
  */
 void drm_vblank_pre_modeset(struct drm_device *dev, int crtc)
 {
-       /* vblank is not initialized (IRQ not installed ?) */
+       /* vblank is not initialized (IRQ not installed ?), or has been freed */
        if (!dev->num_crtcs)
                return;
        /*
@@ -1076,6 +1076,10 @@ void drm_vblank_post_modeset(struct drm_device *dev, int crtc)
 {
        unsigned long irqflags;
 
+       /* vblank is not initialized (IRQ not installed ?), or has been freed */
+       if (!dev->num_crtcs)
+               return;
+
        if (dev->vblank_inmodeset[crtc]) {
                spin_lock_irqsave(&dev->vbl_lock, irqflags);
                dev->vblank_disable_allowed = 1;
index db1e2d6..07cf99c 100644 (file)
@@ -755,33 +755,35 @@ void drm_mm_debug_table(struct drm_mm *mm, const char *prefix)
 EXPORT_SYMBOL(drm_mm_debug_table);
 
 #if defined(CONFIG_DEBUG_FS)
-int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm)
+static unsigned long drm_mm_dump_hole(struct seq_file *m, struct drm_mm_node *entry)
 {
-       struct drm_mm_node *entry;
-       unsigned long total_used = 0, total_free = 0, total = 0;
        unsigned long hole_start, hole_end, hole_size;
 
-       hole_start = drm_mm_hole_node_start(&mm->head_node);
-       hole_end = drm_mm_hole_node_end(&mm->head_node);
-       hole_size = hole_end - hole_start;
-       if (hole_size)
+       if (entry->hole_follows) {
+               hole_start = drm_mm_hole_node_start(entry);
+               hole_end = drm_mm_hole_node_end(entry);
+               hole_size = hole_end - hole_start;
                seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: free\n",
                                hole_start, hole_end, hole_size);
-       total_free += hole_size;
+               return hole_size;
+       }
+
+       return 0;
+}
+
+int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm)
+{
+       struct drm_mm_node *entry;
+       unsigned long total_used = 0, total_free = 0, total = 0;
+
+       total_free += drm_mm_dump_hole(m, &mm->head_node);
 
        drm_mm_for_each_node(entry, mm) {
                seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: used\n",
                                entry->start, entry->start + entry->size,
                                entry->size);
                total_used += entry->size;
-               if (entry->hole_follows) {
-                       hole_start = drm_mm_hole_node_start(entry);
-                       hole_end = drm_mm_hole_node_end(entry);
-                       hole_size = hole_end - hole_start;
-                       seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: free\n",
-                                       hole_start, hole_end, hole_size);
-                       total_free += hole_size;
-               }
+               total_free += drm_mm_dump_hole(m, entry);
        }
        total = total_free + total_used;
 
index faa79df..a371ff8 100644 (file)
@@ -1143,6 +1143,7 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
                                was_digit = false;
                        } else
                                goto done;
+                       break;
                case '0' ... '9':
                        was_digit = true;
                        break;
index e8894bc..c200e4d 100644 (file)
@@ -48,6 +48,8 @@ struct exynos_drm_crtc {
        unsigned int                    pipe;
        unsigned int                    dpms;
        enum exynos_crtc_mode           mode;
+       wait_queue_head_t               pending_flip_queue;
+       atomic_t                        pending_flip;
 };
 
 static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
@@ -61,6 +63,13 @@ static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
                return;
        }
 
+       if (mode > DRM_MODE_DPMS_ON) {
+               /* wait for the completion of page flip. */
+               wait_event(exynos_crtc->pending_flip_queue,
+                               atomic_read(&exynos_crtc->pending_flip) == 0);
+               drm_vblank_off(crtc->dev, exynos_crtc->pipe);
+       }
+
        exynos_drm_fn_encoder(crtc, &mode, exynos_drm_encoder_crtc_dpms);
        exynos_crtc->dpms = mode;
 }
@@ -217,7 +226,6 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,
                ret = drm_vblank_get(dev, exynos_crtc->pipe);
                if (ret) {
                        DRM_DEBUG("failed to acquire vblank counter\n");
-                       list_del(&event->base.link);
 
                        goto out;
                }
@@ -225,6 +233,7 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,
                spin_lock_irq(&dev->event_lock);
                list_add_tail(&event->base.link,
                                &dev_priv->pageflip_event_list);
+               atomic_set(&exynos_crtc->pending_flip, 1);
                spin_unlock_irq(&dev->event_lock);
 
                crtc->fb = fb;
@@ -344,6 +353,8 @@ int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr)
 
        exynos_crtc->pipe = nr;
        exynos_crtc->dpms = DRM_MODE_DPMS_OFF;
+       init_waitqueue_head(&exynos_crtc->pending_flip_queue);
+       atomic_set(&exynos_crtc->pending_flip, 0);
        exynos_crtc->plane = exynos_plane_init(dev, 1 << nr, true);
        if (!exynos_crtc->plane) {
                kfree(exynos_crtc);
@@ -398,7 +409,8 @@ void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int crtc)
 {
        struct exynos_drm_private *dev_priv = dev->dev_private;
        struct drm_pending_vblank_event *e, *t;
-       struct timeval now;
+       struct drm_crtc *drm_crtc = dev_priv->crtc[crtc];
+       struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(drm_crtc);
        unsigned long flags;
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
@@ -411,14 +423,11 @@ void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int crtc)
                if (crtc != e->pipe)
                        continue;
 
-               do_gettimeofday(&now);
-               e->event.sequence = 0;
-               e->event.tv_sec = now.tv_sec;
-               e->event.tv_usec = now.tv_usec;
-
-               list_move_tail(&e->base.link, &e->base.file_priv->event_list);
-               wake_up_interruptible(&e->base.file_priv->event_wait);
+               list_del(&e->base.link);
+               drm_send_vblank_event(dev, -1, e);
                drm_vblank_put(dev, crtc);
+               atomic_set(&exynos_crtc->pending_flip, 0);
+               wake_up(&exynos_crtc->pending_flip_queue);
        }
 
        spin_unlock_irqrestore(&dev->event_lock, flags);
index 68f0045..8f007aa 100644 (file)
@@ -182,7 +182,7 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,
 
        helper->fb = exynos_drm_framebuffer_init(dev, &mode_cmd,
                        &exynos_gem_obj->base);
-       if (IS_ERR_OR_NULL(helper->fb)) {
+       if (IS_ERR(helper->fb)) {
                DRM_ERROR("failed to create drm framebuffer.\n");
                ret = PTR_ERR(helper->fb);
                goto err_destroy_gem;
index 773f583..4a1616a 100644 (file)
@@ -12,9 +12,9 @@
  *
  */
 #include <linux/kernel.h>
-#include <linux/mfd/syscon.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
+#include <linux/mfd/syscon.h>
 #include <linux/regmap.h>
 #include <linux/clk.h>
 #include <linux/pm_runtime.h>
@@ -1845,7 +1845,7 @@ static int fimc_probe(struct platform_device *pdev)
        }
 
        ctx->irq = res->start;
-       ret = request_threaded_irq(ctx->irq, NULL, fimc_irq_handler,
+       ret = devm_request_threaded_irq(dev, ctx->irq, NULL, fimc_irq_handler,
                IRQF_ONESHOT, "drm_fimc", ctx);
        if (ret < 0) {
                dev_err(dev, "failed to request irq.\n");
@@ -1854,7 +1854,7 @@ static int fimc_probe(struct platform_device *pdev)
 
        ret = fimc_setup_clocks(ctx);
        if (ret < 0)
-               goto err_free_irq;
+               return ret;
 
        ippdrv = &ctx->ippdrv;
        ippdrv->ops[EXYNOS_DRM_OPS_SRC] = &fimc_src_ops;
@@ -1884,7 +1884,7 @@ static int fimc_probe(struct platform_device *pdev)
                goto err_pm_dis;
        }
 
-       dev_info(&pdev->dev, "drm fimc registered successfully.\n");
+       dev_info(dev, "drm fimc registered successfully.\n");
 
        return 0;
 
@@ -1892,8 +1892,6 @@ err_pm_dis:
        pm_runtime_disable(dev);
 err_put_clk:
        fimc_put_clocks(ctx);
-err_free_irq:
-       free_irq(ctx->irq, ctx);
 
        return ret;
 }
@@ -1911,8 +1909,6 @@ static int fimc_remove(struct platform_device *pdev)
        pm_runtime_set_suspended(dev);
        pm_runtime_disable(dev);
 
-       free_irq(ctx->irq, ctx);
-
        return 0;
 }
 
index 746b282..97c61db 100644 (file)
@@ -885,7 +885,7 @@ static int fimd_probe(struct platform_device *pdev)
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
-       if (pdev->dev.of_node) {
+       if (dev->of_node) {
                pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
                if (!pdata) {
                        DRM_ERROR("memory allocation for pdata failed\n");
@@ -899,7 +899,7 @@ static int fimd_probe(struct platform_device *pdev)
                        return ret;
                }
        } else {
-               pdata = pdev->dev.platform_data;
+               pdata = dev->platform_data;
                if (!pdata) {
                        DRM_ERROR("no platform data specified\n");
                        return -EINVAL;
@@ -912,7 +912,7 @@ static int fimd_probe(struct platform_device *pdev)
                return -EINVAL;
        }
 
-       ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
+       ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
        if (!ctx)
                return -ENOMEM;
 
@@ -930,7 +930,7 @@ static int fimd_probe(struct platform_device *pdev)
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
-       ctx->regs = devm_ioremap_resource(&pdev->dev, res);
+       ctx->regs = devm_ioremap_resource(dev, res);
        if (IS_ERR(ctx->regs))
                return PTR_ERR(ctx->regs);
 
@@ -942,7 +942,7 @@ static int fimd_probe(struct platform_device *pdev)
 
        ctx->irq = res->start;
 
-       ret = devm_request_irq(&pdev->dev, ctx->irq, fimd_irq_handler,
+       ret = devm_request_irq(dev, ctx->irq, fimd_irq_handler,
                                                        0, "drm_fimd", ctx);
        if (ret) {
                dev_err(dev, "irq request failed.\n");
index 47a493c..af75434 100644 (file)
@@ -1379,7 +1379,7 @@ static int g2d_probe(struct platform_device *pdev)
        struct exynos_drm_subdrv *subdrv;
        int ret;
 
-       g2d = devm_kzalloc(&pdev->dev, sizeof(*g2d), GFP_KERNEL);
+       g2d = devm_kzalloc(dev, sizeof(*g2d), GFP_KERNEL);
        if (!g2d) {
                dev_err(dev, "failed to allocate driver data\n");
                return -ENOMEM;
@@ -1417,7 +1417,7 @@ static int g2d_probe(struct platform_device *pdev)
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
-       g2d->regs = devm_ioremap_resource(&pdev->dev, res);
+       g2d->regs = devm_ioremap_resource(dev, res);
        if (IS_ERR(g2d->regs)) {
                ret = PTR_ERR(g2d->regs);
                goto err_put_clk;
@@ -1430,7 +1430,7 @@ static int g2d_probe(struct platform_device *pdev)
                goto err_put_clk;
        }
 
-       ret = devm_request_irq(&pdev->dev, g2d->irq, g2d_irq_handler, 0,
+       ret = devm_request_irq(dev, g2d->irq, g2d_irq_handler, 0,
                                                                "drm_g2d", g2d);
        if (ret < 0) {
                dev_err(dev, "irq request failed\n");
index 7841c3b..762f40d 100644 (file)
@@ -1704,7 +1704,7 @@ static int gsc_probe(struct platform_device *pdev)
        }
 
        ctx->irq = res->start;
-       ret = request_threaded_irq(ctx->irq, NULL, gsc_irq_handler,
+       ret = devm_request_threaded_irq(dev, ctx->irq, NULL, gsc_irq_handler,
                IRQF_ONESHOT, "drm_gsc", ctx);
        if (ret < 0) {
                dev_err(dev, "failed to request irq.\n");
@@ -1725,7 +1725,7 @@ static int gsc_probe(struct platform_device *pdev)
        ret = gsc_init_prop_list(ippdrv);
        if (ret < 0) {
                dev_err(dev, "failed to init property list.\n");
-               goto err_get_irq;
+               return ret;
        }
 
        DRM_DEBUG_KMS("%s:id[%d]ippdrv[0x%x]\n", __func__, ctx->id,
@@ -1743,15 +1743,12 @@ static int gsc_probe(struct platform_device *pdev)
                goto err_ippdrv_register;
        }
 
-       dev_info(&pdev->dev, "drm gsc registered successfully.\n");
+       dev_info(dev, "drm gsc registered successfully.\n");
 
        return 0;
 
 err_ippdrv_register:
-       devm_kfree(dev, ippdrv->prop_list);
        pm_runtime_disable(dev);
-err_get_irq:
-       free_irq(ctx->irq, ctx);
        return ret;
 }
 
@@ -1761,15 +1758,12 @@ static int gsc_remove(struct platform_device *pdev)
        struct gsc_context *ctx = get_gsc_context(dev);
        struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
 
-       devm_kfree(dev, ippdrv->prop_list);
        exynos_drm_ippdrv_unregister(ippdrv);
        mutex_destroy(&ctx->lock);
 
        pm_runtime_set_suspended(dev);
        pm_runtime_disable(dev);
 
-       free_irq(ctx->irq, ctx);
-
        return 0;
 }
 
index ba2f0f1..437fb94 100644 (file)
@@ -442,7 +442,7 @@ static int exynos_drm_hdmi_probe(struct platform_device *pdev)
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
-       ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
+       ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
        if (!ctx) {
                DRM_LOG_KMS("failed to alloc common hdmi context.\n");
                return -ENOMEM;
index 29d2ad3..be1e884 100644 (file)
@@ -222,7 +222,7 @@ static struct exynos_drm_ippdrv *ipp_find_driver(struct ipp_context *ctx,
                /* find ipp driver using idr */
                ippdrv = ipp_find_obj(&ctx->ipp_idr, &ctx->ipp_lock,
                        ipp_id);
-               if (IS_ERR_OR_NULL(ippdrv)) {
+               if (IS_ERR(ippdrv)) {
                        DRM_ERROR("not found ipp%d driver.\n", ipp_id);
                        return ippdrv;
                }
@@ -388,7 +388,7 @@ static int ipp_find_and_set_property(struct drm_exynos_ipp_property *property)
        DRM_DEBUG_KMS("%s:prop_id[%d]\n", __func__, prop_id);
 
        ippdrv = ipp_find_drv_by_handle(prop_id);
-       if (IS_ERR_OR_NULL(ippdrv)) {
+       if (IS_ERR(ippdrv)) {
                DRM_ERROR("failed to get ipp driver.\n");
                return -EINVAL;
        }
@@ -492,7 +492,7 @@ int exynos_drm_ipp_set_property(struct drm_device *drm_dev, void *data,
 
        /* find ipp driver using ipp id */
        ippdrv = ipp_find_driver(ctx, property);
-       if (IS_ERR_OR_NULL(ippdrv)) {
+       if (IS_ERR(ippdrv)) {
                DRM_ERROR("failed to get ipp driver.\n");
                return -EINVAL;
        }
@@ -521,19 +521,19 @@ int exynos_drm_ipp_set_property(struct drm_device *drm_dev, void *data,
        c_node->state = IPP_STATE_IDLE;
 
        c_node->start_work = ipp_create_cmd_work();
-       if (IS_ERR_OR_NULL(c_node->start_work)) {
+       if (IS_ERR(c_node->start_work)) {
                DRM_ERROR("failed to create start work.\n");
                goto err_clear;
        }
 
        c_node->stop_work = ipp_create_cmd_work();
-       if (IS_ERR_OR_NULL(c_node->stop_work)) {
+       if (IS_ERR(c_node->stop_work)) {
                DRM_ERROR("failed to create stop work.\n");
                goto err_free_start;
        }
 
        c_node->event_work = ipp_create_event_work();
-       if (IS_ERR_OR_NULL(c_node->event_work)) {
+       if (IS_ERR(c_node->event_work)) {
                DRM_ERROR("failed to create event work.\n");
                goto err_free_stop;
        }
@@ -915,7 +915,7 @@ static int ipp_queue_buf_with_run(struct device *dev,
        DRM_DEBUG_KMS("%s\n", __func__);
 
        ippdrv = ipp_find_drv_by_handle(qbuf->prop_id);
-       if (IS_ERR_OR_NULL(ippdrv)) {
+       if (IS_ERR(ippdrv)) {
                DRM_ERROR("failed to get ipp driver.\n");
                return -EFAULT;
        }
@@ -1909,7 +1909,7 @@ static int ipp_probe(struct platform_device *pdev)
        struct exynos_drm_subdrv *subdrv;
        int ret;
 
-       ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
+       ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
        if (!ctx)
                return -ENOMEM;
 
@@ -1963,7 +1963,7 @@ static int ipp_probe(struct platform_device *pdev)
                goto err_cmd_workq;
        }
 
-       dev_info(&pdev->dev, "drm ipp registered successfully.\n");
+       dev_info(dev, "drm ipp registered successfully.\n");
 
        return 0;
 
index 947f09f..9b6c709 100644 (file)
@@ -666,8 +666,8 @@ static int rotator_probe(struct platform_device *pdev)
                return rot->irq;
        }
 
-       ret = request_threaded_irq(rot->irq, NULL, rotator_irq_handler,
-                       IRQF_ONESHOT, "drm_rotator", rot);
+       ret = devm_request_threaded_irq(dev, rot->irq, NULL,
+                       rotator_irq_handler, IRQF_ONESHOT, "drm_rotator", rot);
        if (ret < 0) {
                dev_err(dev, "failed to request irq\n");
                return ret;
@@ -676,8 +676,7 @@ static int rotator_probe(struct platform_device *pdev)
        rot->clock = devm_clk_get(dev, "rotator");
        if (IS_ERR(rot->clock)) {
                dev_err(dev, "failed to get clock\n");
-               ret = PTR_ERR(rot->clock);
-               goto err_clk_get;
+               return PTR_ERR(rot->clock);
        }
 
        pm_runtime_enable(dev);
@@ -709,10 +708,7 @@ static int rotator_probe(struct platform_device *pdev)
        return 0;
 
 err_ippdrv_register:
-       devm_kfree(dev, ippdrv->prop_list);
        pm_runtime_disable(dev);
-err_clk_get:
-       free_irq(rot->irq, rot);
        return ret;
 }
 
@@ -722,13 +718,10 @@ static int rotator_remove(struct platform_device *pdev)
        struct rot_context *rot = dev_get_drvdata(dev);
        struct exynos_drm_ippdrv *ippdrv = &rot->ippdrv;
 
-       devm_kfree(dev, ippdrv->prop_list);
        exynos_drm_ippdrv_unregister(ippdrv);
 
        pm_runtime_disable(dev);
 
-       free_irq(rot->irq, rot);
-
        return 0;
 }
 
index 9504b0c..24376c1 100644 (file)
@@ -594,7 +594,7 @@ static int vidi_probe(struct platform_device *pdev)
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
-       ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
+       ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
        if (!ctx)
                return -ENOMEM;
 
@@ -612,7 +612,7 @@ static int vidi_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, ctx);
 
-       ret = device_create_file(&pdev->dev, &dev_attr_connection);
+       ret = device_create_file(dev, &dev_attr_connection);
        if (ret < 0)
                DRM_INFO("failed to create connection sysfs.\n");
 
index bbfc384..fd1426d 100644 (file)
@@ -1946,14 +1946,14 @@ static int hdmi_probe(struct platform_device *pdev)
 
        DRM_DEBUG_KMS("[%d]\n", __LINE__);
 
-       if (pdev->dev.of_node) {
+       if (dev->of_node) {
                pdata = drm_hdmi_dt_parse_pdata(dev);
                if (IS_ERR(pdata)) {
                        DRM_ERROR("failed to parse dt\n");
                        return PTR_ERR(pdata);
                }
        } else {
-               pdata = pdev->dev.platform_data;
+               pdata = dev->platform_data;
        }
 
        if (!pdata) {
@@ -1961,14 +1961,14 @@ static int hdmi_probe(struct platform_device *pdev)
                return -EINVAL;
        }
 
-       drm_hdmi_ctx = devm_kzalloc(&pdev->dev, sizeof(*drm_hdmi_ctx),
+       drm_hdmi_ctx = devm_kzalloc(dev, sizeof(*drm_hdmi_ctx),
                                                                GFP_KERNEL);
        if (!drm_hdmi_ctx) {
                DRM_ERROR("failed to allocate common hdmi context.\n");
                return -ENOMEM;
        }
 
-       hdata = devm_kzalloc(&pdev->dev, sizeof(struct hdmi_context),
+       hdata = devm_kzalloc(dev, sizeof(struct hdmi_context),
                                                                GFP_KERNEL);
        if (!hdata) {
                DRM_ERROR("out of memory\n");
@@ -1985,7 +1985,7 @@ static int hdmi_probe(struct platform_device *pdev)
        if (dev->of_node) {
                const struct of_device_id *match;
                match = of_match_node(of_match_ptr(hdmi_match_types),
-                                       pdev->dev.of_node);
+                                       dev->of_node);
                if (match == NULL)
                        return -ENODEV;
                hdata->type = (enum hdmi_type)match->data;
@@ -2005,16 +2005,11 @@ static int hdmi_probe(struct platform_device *pdev)
        }
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               DRM_ERROR("failed to find registers\n");
-               return -ENOENT;
-       }
-
-       hdata->regs = devm_ioremap_resource(&pdev->dev, res);
+       hdata->regs = devm_ioremap_resource(dev, res);
        if (IS_ERR(hdata->regs))
                return PTR_ERR(hdata->regs);
 
-       ret = devm_gpio_request(&pdev->dev, hdata->hpd_gpio, "HPD");
+       ret = devm_gpio_request(dev, hdata->hpd_gpio, "HPD");
        if (ret) {
                DRM_ERROR("failed to request HPD gpio\n");
                return ret;
@@ -2046,7 +2041,7 @@ static int hdmi_probe(struct platform_device *pdev)
 
        hdata->hpd = gpio_get_value(hdata->hpd_gpio);
 
-       ret = request_threaded_irq(hdata->irq, NULL,
+       ret = devm_request_threaded_irq(dev, hdata->irq, NULL,
                        hdmi_irq_thread, IRQF_TRIGGER_RISING |
                        IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
                        "hdmi", drm_hdmi_ctx);
@@ -2075,16 +2070,11 @@ err_ddc:
 static int hdmi_remove(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
-       struct exynos_drm_hdmi_context *ctx = platform_get_drvdata(pdev);
-       struct hdmi_context *hdata = ctx->ctx;
 
        DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
 
        pm_runtime_disable(dev);
 
-       free_irq(hdata->irq, hdata);
-
-
        /* hdmiphy i2c driver */
        i2c_del_driver(&hdmiphy_driver);
        /* DDC i2c driver */
index ec3e376..7c197d3 100644 (file)
@@ -1061,7 +1061,7 @@ static int mixer_resources_init(struct exynos_drm_hdmi_context *ctx,
                return -ENXIO;
        }
 
-       mixer_res->mixer_regs = devm_ioremap(&pdev->dev, res->start,
+       mixer_res->mixer_regs = devm_ioremap(dev, res->start,
                                                        resource_size(res));
        if (mixer_res->mixer_regs == NULL) {
                dev_err(dev, "register mapping failed.\n");
@@ -1074,7 +1074,7 @@ static int mixer_resources_init(struct exynos_drm_hdmi_context *ctx,
                return -ENXIO;
        }
 
-       ret = devm_request_irq(&pdev->dev, res->start, mixer_irq_handler,
+       ret = devm_request_irq(dev, res->start, mixer_irq_handler,
                                                        0, "drm_mixer", ctx);
        if (ret) {
                dev_err(dev, "request interrupt failed.\n");
@@ -1118,7 +1118,7 @@ static int vp_resources_init(struct exynos_drm_hdmi_context *ctx,
                return -ENXIO;
        }
 
-       mixer_res->vp_regs = devm_ioremap(&pdev->dev, res->start,
+       mixer_res->vp_regs = devm_ioremap(dev, res->start,
                                                        resource_size(res));
        if (mixer_res->vp_regs == NULL) {
                dev_err(dev, "register mapping failed.\n");
@@ -1169,14 +1169,14 @@ static int mixer_probe(struct platform_device *pdev)
 
        dev_info(dev, "probe start\n");
 
-       drm_hdmi_ctx = devm_kzalloc(&pdev->dev, sizeof(*drm_hdmi_ctx),
+       drm_hdmi_ctx = devm_kzalloc(dev, sizeof(*drm_hdmi_ctx),
                                                                GFP_KERNEL);
        if (!drm_hdmi_ctx) {
                DRM_ERROR("failed to allocate common hdmi context.\n");
                return -ENOMEM;
        }
 
-       ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
+       ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
        if (!ctx) {
                DRM_ERROR("failed to alloc mixer context.\n");
                return -ENOMEM;
@@ -1187,14 +1187,14 @@ static int mixer_probe(struct platform_device *pdev)
        if (dev->of_node) {
                const struct of_device_id *match;
                match = of_match_node(of_match_ptr(mixer_match_types),
-                                                         pdev->dev.of_node);
+                                                         dev->of_node);
                drv = (struct mixer_drv_data *)match->data;
        } else {
                drv = (struct mixer_drv_data *)
                        platform_get_device_id(pdev)->driver_data;
        }
 
-       ctx->dev = &pdev->dev;
+       ctx->dev = dev;
        ctx->parent_ctx = (void *)drm_hdmi_ctx;
        drm_hdmi_ctx->ctx = (void *)ctx;
        ctx->vp_enabled = drv->is_vp_enabled;
index 3cfd093..82430ad 100644 (file)
@@ -1462,7 +1462,7 @@ static int cdv_intel_crtc_cursor_set(struct drm_crtc *crtc,
        size_t addr = 0;
        struct gtt_range *gt;
        struct drm_gem_object *obj;
-       int ret;
+       int ret = 0;
 
        /* if we want to turn of the cursor ignore width and height */
        if (!handle) {
@@ -1499,7 +1499,8 @@ static int cdv_intel_crtc_cursor_set(struct drm_crtc *crtc,
 
        if (obj->size < width * height * 4) {
                dev_dbg(dev->dev, "buffer is to small\n");
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto unref_cursor;
        }
 
        gt = container_of(obj, struct gtt_range, gem);
@@ -1508,7 +1509,7 @@ static int cdv_intel_crtc_cursor_set(struct drm_crtc *crtc,
        ret = psb_gtt_pin(gt);
        if (ret) {
                dev_err(dev->dev, "Can not pin down handle 0x%x\n", handle);
-               return ret;
+               goto unref_cursor;
        }
 
        addr = gt->offset;      /* Or resource.start ??? */
@@ -1532,9 +1533,14 @@ static int cdv_intel_crtc_cursor_set(struct drm_crtc *crtc,
                                                        struct gtt_range, gem);
                psb_gtt_unpin(gt);
                drm_gem_object_unreference(psb_intel_crtc->cursor_obj);
-               psb_intel_crtc->cursor_obj = obj;
        }
-       return 0;
+
+       psb_intel_crtc->cursor_obj = obj;
+       return ret;
+
+unref_cursor:
+       drm_gem_object_unreference(obj);
+       return ret;
 }
 
 static int cdv_intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
@@ -1750,6 +1756,19 @@ static void cdv_intel_crtc_destroy(struct drm_crtc *crtc)
        kfree(psb_intel_crtc);
 }
 
+static void cdv_intel_crtc_disable(struct drm_crtc *crtc)
+{
+       struct gtt_range *gt;
+       struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
+
+       crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
+
+       if (crtc->fb) {
+               gt = to_psb_fb(crtc->fb)->gtt;
+               psb_gtt_unpin(gt);
+       }
+}
+
 const struct drm_crtc_helper_funcs cdv_intel_helper_funcs = {
        .dpms = cdv_intel_crtc_dpms,
        .mode_fixup = cdv_intel_crtc_mode_fixup,
@@ -1757,6 +1776,7 @@ const struct drm_crtc_helper_funcs cdv_intel_helper_funcs = {
        .mode_set_base = cdv_intel_pipe_set_base,
        .prepare = cdv_intel_crtc_prepare,
        .commit = cdv_intel_crtc_commit,
+       .disable = cdv_intel_crtc_disable,
 };
 
 const struct drm_crtc_funcs cdv_intel_crtc_funcs = {
index 1534e22..8b1b6d9 100644 (file)
@@ -121,8 +121,8 @@ static int psbfb_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
        unsigned long address;
        int ret;
        unsigned long pfn;
-       /* FIXME: assumes fb at stolen base which may not be true */
-       unsigned long phys_addr = (unsigned long)dev_priv->stolen_base;
+       unsigned long phys_addr = (unsigned long)dev_priv->stolen_base +
+                                 psbfb->gtt->offset;
 
        page_num = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
        address = (unsigned long)vmf->virtual_address - (vmf->pgoff << PAGE_SHIFT);
index 6e8f42b..6666493 100644 (file)
@@ -843,7 +843,7 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc,
        struct gtt_range *cursor_gt = psb_intel_crtc->cursor_gt;
        struct drm_gem_object *obj;
        void *tmp_dst, *tmp_src;
-       int ret, i, cursor_pages;
+       int ret = 0, i, cursor_pages;
 
        /* if we want to turn of the cursor ignore width and height */
        if (!handle) {
@@ -880,7 +880,8 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc,
 
        if (obj->size < width * height * 4) {
                dev_dbg(dev->dev, "buffer is to small\n");
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto unref_cursor;
        }
 
        gt = container_of(obj, struct gtt_range, gem);
@@ -889,13 +890,14 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc,
        ret = psb_gtt_pin(gt);
        if (ret) {
                dev_err(dev->dev, "Can not pin down handle 0x%x\n", handle);
-               return ret;
+               goto unref_cursor;
        }
 
        if (dev_priv->ops->cursor_needs_phys) {
                if (cursor_gt == NULL) {
                        dev_err(dev->dev, "No hardware cursor mem available");
-                       return -ENOMEM;
+                       ret = -ENOMEM;
+                       goto unref_cursor;
                }
 
                /* Prevent overflow */
@@ -936,9 +938,14 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc,
                                                        struct gtt_range, gem);
                psb_gtt_unpin(gt);
                drm_gem_object_unreference(psb_intel_crtc->cursor_obj);
-               psb_intel_crtc->cursor_obj = obj;
        }
-       return 0;
+
+       psb_intel_crtc->cursor_obj = obj;
+       return ret;
+
+unref_cursor:
+       drm_gem_object_unreference(obj);
+       return ret;
 }
 
 static int psb_intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
@@ -1150,6 +1157,19 @@ static void psb_intel_crtc_destroy(struct drm_crtc *crtc)
        kfree(psb_intel_crtc);
 }
 
+static void psb_intel_crtc_disable(struct drm_crtc *crtc)
+{
+       struct gtt_range *gt;
+       struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
+
+       crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
+
+       if (crtc->fb) {
+               gt = to_psb_fb(crtc->fb)->gtt;
+               psb_gtt_unpin(gt);
+       }
+}
+
 const struct drm_crtc_helper_funcs psb_intel_helper_funcs = {
        .dpms = psb_intel_crtc_dpms,
        .mode_fixup = psb_intel_crtc_mode_fixup,
@@ -1157,6 +1177,7 @@ const struct drm_crtc_helper_funcs psb_intel_helper_funcs = {
        .mode_set_base = psb_intel_pipe_set_base,
        .prepare = psb_intel_crtc_prepare,
        .commit = psb_intel_crtc_commit,
+       .disable = psb_intel_crtc_disable,
 };
 
 const struct drm_crtc_funcs psb_intel_crtc_funcs = {
index 9ebe895..a2e4953 100644 (file)
@@ -364,40 +364,64 @@ static const struct pci_device_id pciidlist[] = {         /* aka */
        INTEL_VGA_DEVICE(0x016a, &intel_ivybridge_d_info), /* GT2 server */
        INTEL_VGA_DEVICE(0x0402, &intel_haswell_d_info), /* GT1 desktop */
        INTEL_VGA_DEVICE(0x0412, &intel_haswell_d_info), /* GT2 desktop */
-       INTEL_VGA_DEVICE(0x0422, &intel_haswell_d_info), /* GT2 desktop */
+       INTEL_VGA_DEVICE(0x0422, &intel_haswell_d_info), /* GT3 desktop */
        INTEL_VGA_DEVICE(0x040a, &intel_haswell_d_info), /* GT1 server */
        INTEL_VGA_DEVICE(0x041a, &intel_haswell_d_info), /* GT2 server */
-       INTEL_VGA_DEVICE(0x042a, &intel_haswell_d_info), /* GT2 server */
+       INTEL_VGA_DEVICE(0x042a, &intel_haswell_d_info), /* GT3 server */
        INTEL_VGA_DEVICE(0x0406, &intel_haswell_m_info), /* GT1 mobile */
        INTEL_VGA_DEVICE(0x0416, &intel_haswell_m_info), /* GT2 mobile */
        INTEL_VGA_DEVICE(0x0426, &intel_haswell_m_info), /* GT2 mobile */
+       INTEL_VGA_DEVICE(0x040B, &intel_haswell_d_info), /* GT1 reserved */
+       INTEL_VGA_DEVICE(0x041B, &intel_haswell_d_info), /* GT2 reserved */
+       INTEL_VGA_DEVICE(0x042B, &intel_haswell_d_info), /* GT3 reserved */
+       INTEL_VGA_DEVICE(0x040E, &intel_haswell_d_info), /* GT1 reserved */
+       INTEL_VGA_DEVICE(0x041E, &intel_haswell_d_info), /* GT2 reserved */
+       INTEL_VGA_DEVICE(0x042E, &intel_haswell_d_info), /* GT3 reserved */
        INTEL_VGA_DEVICE(0x0C02, &intel_haswell_d_info), /* SDV GT1 desktop */
        INTEL_VGA_DEVICE(0x0C12, &intel_haswell_d_info), /* SDV GT2 desktop */
-       INTEL_VGA_DEVICE(0x0C22, &intel_haswell_d_info), /* SDV GT2 desktop */
+       INTEL_VGA_DEVICE(0x0C22, &intel_haswell_d_info), /* SDV GT3 desktop */
        INTEL_VGA_DEVICE(0x0C0A, &intel_haswell_d_info), /* SDV GT1 server */
        INTEL_VGA_DEVICE(0x0C1A, &intel_haswell_d_info), /* SDV GT2 server */
-       INTEL_VGA_DEVICE(0x0C2A, &intel_haswell_d_info), /* SDV GT2 server */
+       INTEL_VGA_DEVICE(0x0C2A, &intel_haswell_d_info), /* SDV GT3 server */
        INTEL_VGA_DEVICE(0x0C06, &intel_haswell_m_info), /* SDV GT1 mobile */
        INTEL_VGA_DEVICE(0x0C16, &intel_haswell_m_info), /* SDV GT2 mobile */
-       INTEL_VGA_DEVICE(0x0C26, &intel_haswell_m_info), /* SDV GT2 mobile */
+       INTEL_VGA_DEVICE(0x0C26, &intel_haswell_m_info), /* SDV GT3 mobile */
+       INTEL_VGA_DEVICE(0x0C0B, &intel_haswell_d_info), /* SDV GT1 reserved */
+       INTEL_VGA_DEVICE(0x0C1B, &intel_haswell_d_info), /* SDV GT2 reserved */
+       INTEL_VGA_DEVICE(0x0C2B, &intel_haswell_d_info), /* SDV GT3 reserved */
+       INTEL_VGA_DEVICE(0x0C0E, &intel_haswell_d_info), /* SDV GT1 reserved */
+       INTEL_VGA_DEVICE(0x0C1E, &intel_haswell_d_info), /* SDV GT2 reserved */
+       INTEL_VGA_DEVICE(0x0C2E, &intel_haswell_d_info), /* SDV GT3 reserved */
        INTEL_VGA_DEVICE(0x0A02, &intel_haswell_d_info), /* ULT GT1 desktop */
        INTEL_VGA_DEVICE(0x0A12, &intel_haswell_d_info), /* ULT GT2 desktop */
-       INTEL_VGA_DEVICE(0x0A22, &intel_haswell_d_info), /* ULT GT2 desktop */
+       INTEL_VGA_DEVICE(0x0A22, &intel_haswell_d_info), /* ULT GT3 desktop */
        INTEL_VGA_DEVICE(0x0A0A, &intel_haswell_d_info), /* ULT GT1 server */
        INTEL_VGA_DEVICE(0x0A1A, &intel_haswell_d_info), /* ULT GT2 server */
-       INTEL_VGA_DEVICE(0x0A2A, &intel_haswell_d_info), /* ULT GT2 server */
+       INTEL_VGA_DEVICE(0x0A2A, &intel_haswell_d_info), /* ULT GT3 server */
        INTEL_VGA_DEVICE(0x0A06, &intel_haswell_m_info), /* ULT GT1 mobile */
        INTEL_VGA_DEVICE(0x0A16, &intel_haswell_m_info), /* ULT GT2 mobile */
-       INTEL_VGA_DEVICE(0x0A26, &intel_haswell_m_info), /* ULT GT2 mobile */
+       INTEL_VGA_DEVICE(0x0A26, &intel_haswell_m_info), /* ULT GT3 mobile */
+       INTEL_VGA_DEVICE(0x0A0B, &intel_haswell_d_info), /* ULT GT1 reserved */
+       INTEL_VGA_DEVICE(0x0A1B, &intel_haswell_d_info), /* ULT GT2 reserved */
+       INTEL_VGA_DEVICE(0x0A2B, &intel_haswell_d_info), /* ULT GT3 reserved */
+       INTEL_VGA_DEVICE(0x0A0E, &intel_haswell_m_info), /* ULT GT1 reserved */
+       INTEL_VGA_DEVICE(0x0A1E, &intel_haswell_m_info), /* ULT GT2 reserved */
+       INTEL_VGA_DEVICE(0x0A2E, &intel_haswell_m_info), /* ULT GT3 reserved */
        INTEL_VGA_DEVICE(0x0D02, &intel_haswell_d_info), /* CRW GT1 desktop */
        INTEL_VGA_DEVICE(0x0D12, &intel_haswell_d_info), /* CRW GT2 desktop */
-       INTEL_VGA_DEVICE(0x0D22, &intel_haswell_d_info), /* CRW GT2 desktop */
+       INTEL_VGA_DEVICE(0x0D22, &intel_haswell_d_info), /* CRW GT3 desktop */
        INTEL_VGA_DEVICE(0x0D0A, &intel_haswell_d_info), /* CRW GT1 server */
        INTEL_VGA_DEVICE(0x0D1A, &intel_haswell_d_info), /* CRW GT2 server */
-       INTEL_VGA_DEVICE(0x0D2A, &intel_haswell_d_info), /* CRW GT2 server */
+       INTEL_VGA_DEVICE(0x0D2A, &intel_haswell_d_info), /* CRW GT3 server */
        INTEL_VGA_DEVICE(0x0D06, &intel_haswell_m_info), /* CRW GT1 mobile */
        INTEL_VGA_DEVICE(0x0D16, &intel_haswell_m_info), /* CRW GT2 mobile */
-       INTEL_VGA_DEVICE(0x0D26, &intel_haswell_m_info), /* CRW GT2 mobile */
+       INTEL_VGA_DEVICE(0x0D26, &intel_haswell_m_info), /* CRW GT3 mobile */
+       INTEL_VGA_DEVICE(0x0D0B, &intel_haswell_d_info), /* CRW GT1 reserved */
+       INTEL_VGA_DEVICE(0x0D1B, &intel_haswell_d_info), /* CRW GT2 reserved */
+       INTEL_VGA_DEVICE(0x0D2B, &intel_haswell_d_info), /* CRW GT3 reserved */
+       INTEL_VGA_DEVICE(0x0D0E, &intel_haswell_d_info), /* CRW GT1 reserved */
+       INTEL_VGA_DEVICE(0x0D1E, &intel_haswell_d_info), /* CRW GT2 reserved */
+       INTEL_VGA_DEVICE(0x0D2E, &intel_haswell_d_info), /* CRW GT3 reserved */
        INTEL_VGA_DEVICE(0x0f30, &intel_valleyview_m_info),
        INTEL_VGA_DEVICE(0x0f31, &intel_valleyview_m_info),
        INTEL_VGA_DEVICE(0x0f32, &intel_valleyview_m_info),
index d5dcf7f..b9d00dc 100644 (file)
@@ -1943,4 +1943,19 @@ static inline void __user *to_user_ptr(u64 address)
        return (void __user *)(uintptr_t)address;
 }
 
+static inline unsigned long msecs_to_jiffies_timeout(const unsigned int m)
+{
+       unsigned long j = msecs_to_jiffies(m);
+
+       return min_t(unsigned long, MAX_JIFFY_OFFSET, j + 1);
+}
+
+static inline unsigned long
+timespec_to_jiffies_timeout(const struct timespec *value)
+{
+       unsigned long j = timespec_to_jiffies(value);
+
+       return min_t(unsigned long, MAX_JIFFY_OFFSET, j + 1);
+}
+
 #endif
index 6be940e..970ad17 100644 (file)
@@ -91,14 +91,11 @@ i915_gem_wait_for_error(struct i915_gpu_error *error)
 {
        int ret;
 
-#define EXIT_COND (!i915_reset_in_progress(error))
+#define EXIT_COND (!i915_reset_in_progress(error) || \
+                  i915_terminally_wedged(error))
        if (EXIT_COND)
                return 0;
 
-       /* GPU is already declared terminally dead, give up. */
-       if (i915_terminally_wedged(error))
-               return -EIO;
-
        /*
         * Only wait 10 seconds for the gpu reset to complete to avoid hanging
         * userspace. If it takes that long something really bad is going on and
@@ -1003,7 +1000,7 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno,
                wait_forever = false;
        }
 
-       timeout_jiffies = timespec_to_jiffies(&wait_time);
+       timeout_jiffies = timespec_to_jiffies_timeout(&wait_time);
 
        if (WARN_ON(!ring->irq_get(ring)))
                return -ENODEV;
@@ -1045,6 +1042,8 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno,
        if (timeout) {
                struct timespec sleep_time = timespec_sub(now, before);
                *timeout = timespec_sub(*timeout, sleep_time);
+               if (!timespec_valid(timeout)) /* i.e. negative time remains */
+                       set_normalized_timespec(timeout, 0, 0);
        }
 
        switch (end) {
@@ -1053,8 +1052,6 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno,
        case -ERESTARTSYS: /* Signal */
                return (int)end;
        case 0: /* Timeout */
-               if (timeout)
-                       set_normalized_timespec(timeout, 0, 0);
                return -ETIME;
        default: /* Completed */
                WARN_ON(end < 0); /* We're not aware of other errors */
@@ -2377,10 +2374,8 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
        mutex_unlock(&dev->struct_mutex);
 
        ret = __wait_seqno(ring, seqno, reset_counter, true, timeout);
-       if (timeout) {
-               WARN_ON(!timespec_valid(timeout));
+       if (timeout)
                args->timeout_ns = timespec_to_ns(timeout);
-       }
        return ret;
 
 out:
index dca614d..bdb0d77 100644 (file)
@@ -709,15 +709,6 @@ static inline size_t gen6_get_stolen_size(u16 snb_gmch_ctl)
        return snb_gmch_ctl << 25; /* 32 MB units */
 }
 
-static inline size_t gen7_get_stolen_size(u16 snb_gmch_ctl)
-{
-       static const int stolen_decoder[] = {
-               0, 0, 0, 0, 0, 32, 48, 64, 128, 256, 96, 160, 224, 352};
-       snb_gmch_ctl >>= IVB_GMCH_GMS_SHIFT;
-       snb_gmch_ctl &= IVB_GMCH_GMS_MASK;
-       return stolen_decoder[snb_gmch_ctl] << 20;
-}
-
 static int gen6_gmch_probe(struct drm_device *dev,
                           size_t *gtt_total,
                           size_t *stolen,
@@ -747,11 +738,7 @@ static int gen6_gmch_probe(struct drm_device *dev,
        pci_read_config_word(dev->pdev, SNB_GMCH_CTRL, &snb_gmch_ctl);
        gtt_size = gen6_get_total_gtt_size(snb_gmch_ctl);
 
-       if (IS_GEN7(dev) && !IS_VALLEYVIEW(dev))
-               *stolen = gen7_get_stolen_size(snb_gmch_ctl);
-       else
-               *stolen = gen6_get_stolen_size(snb_gmch_ctl);
-
+       *stolen = gen6_get_stolen_size(snb_gmch_ctl);
        *gtt_total = (gtt_size / sizeof(gen6_gtt_pte_t)) << PAGE_SHIFT;
 
        /* For Modern GENs the PTEs and register space are split in the BAR */
index 83f9c26..2d6b62e 100644 (file)
@@ -46,8 +46,6 @@
 #define    SNB_GMCH_GGMS_MASK  0x3
 #define    SNB_GMCH_GMS_SHIFT   3 /* Graphics Mode Select */
 #define    SNB_GMCH_GMS_MASK    0x1f
-#define    IVB_GMCH_GMS_SHIFT   4
-#define    IVB_GMCH_GMS_MASK    0xf
 
 
 /* PCI config space */
index 26a0a57..fb961bb 100644 (file)
@@ -1265,6 +1265,8 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)
                intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
                intel_dp_start_link_train(intel_dp);
                intel_dp_complete_link_train(intel_dp);
+               if (port != PORT_A)
+                       intel_dp_stop_link_train(intel_dp);
        }
 }
 
@@ -1326,6 +1328,9 @@ static void intel_enable_ddi(struct intel_encoder *intel_encoder)
        } else if (type == INTEL_OUTPUT_EDP) {
                struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
 
+               if (port == PORT_A)
+                       intel_dp_stop_link_train(intel_dp);
+
                ironlake_edp_backlight_on(intel_dp);
        }
 
index efe8299..56746dc 100644 (file)
@@ -7937,6 +7937,11 @@ intel_modeset_check_state(struct drm_device *dev)
                memset(&pipe_config, 0, sizeof(pipe_config));
                active = dev_priv->display.get_pipe_config(crtc,
                                                           &pipe_config);
+
+               /* hw state is inconsistent with the pipe A quirk */
+               if (crtc->pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE)
+                       active = crtc->active;
+
                WARN(crtc->active != active,
                     "crtc active state doesn't match with hw state "
                     "(expected %i, found %i)\n", crtc->active, active);
@@ -8140,6 +8145,21 @@ static void intel_set_config_restore_state(struct drm_device *dev,
        }
 }
 
+static bool
+is_crtc_connector_off(struct drm_crtc *crtc, struct drm_connector *connectors,
+                     int num_connectors)
+{
+       int i;
+
+       for (i = 0; i < num_connectors; i++)
+               if (connectors[i].encoder &&
+                   connectors[i].encoder->crtc == crtc &&
+                   connectors[i].dpms != DRM_MODE_DPMS_ON)
+                       return true;
+
+       return false;
+}
+
 static void
 intel_set_config_compute_mode_changes(struct drm_mode_set *set,
                                      struct intel_set_config *config)
@@ -8147,7 +8167,11 @@ intel_set_config_compute_mode_changes(struct drm_mode_set *set,
 
        /* We should be able to check here if the fb has the same properties
         * and then just flip_or_move it */
-       if (set->crtc->fb != set->fb) {
+       if (set->connectors != NULL &&
+           is_crtc_connector_off(set->crtc, *set->connectors,
+                                 set->num_connectors)) {
+                       config->mode_changed = true;
+       } else if (set->crtc->fb != set->fb) {
                /* If we have no fb then treat it as a full mode set */
                if (set->crtc->fb == NULL) {
                        DRM_DEBUG_KMS("crtc has no fb, full mode set\n");
@@ -8157,8 +8181,9 @@ intel_set_config_compute_mode_changes(struct drm_mode_set *set,
                } else if (set->fb->pixel_format !=
                           set->crtc->fb->pixel_format) {
                        config->mode_changed = true;
-               } else
+               } else {
                        config->fb_changed = true;
+               }
        }
 
        if (set->fb && (set->x != set->crtc->x || set->y != set->crtc->y))
@@ -8332,11 +8357,6 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
 
                ret = intel_set_mode(set->crtc, set->mode,
                                     set->x, set->y, set->fb);
-               if (ret) {
-                       DRM_ERROR("failed to set mode on [CRTC:%d], err = %d\n",
-                                 set->crtc->base.id, ret);
-                       goto fail;
-               }
        } else if (config->fb_changed) {
                intel_crtc_wait_for_pending_flips(set->crtc);
 
@@ -8344,18 +8364,18 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
                                          set->x, set->y, set->fb);
        }
 
-       intel_set_config_free(config);
-
-       return 0;
-
+       if (ret) {
+               DRM_ERROR("failed to set mode on [CRTC:%d], err = %d\n",
+                         set->crtc->base.id, ret);
 fail:
-       intel_set_config_restore_state(dev, config);
+               intel_set_config_restore_state(dev, config);
 
-       /* Try to restore the config */
-       if (config->mode_changed &&
-           intel_set_mode(save_set.crtc, save_set.mode,
-                          save_set.x, save_set.y, save_set.fb))
-               DRM_ERROR("failed to restore config after modeset failure\n");
+               /* Try to restore the config */
+               if (config->mode_changed &&
+                   intel_set_mode(save_set.crtc, save_set.mode,
+                                  save_set.x, save_set.y, save_set.fb))
+                       DRM_ERROR("failed to restore config after modeset failure\n");
+       }
 
 out_config:
        intel_set_config_free(config);
index fb2fbc1..70789b1 100644 (file)
@@ -303,7 +303,7 @@ intel_dp_aux_wait_done(struct intel_dp *intel_dp, bool has_aux_irq)
 #define C (((status = I915_READ_NOTRACE(ch_ctl)) & DP_AUX_CH_CTL_SEND_BUSY) == 0)
        if (has_aux_irq)
                done = wait_event_timeout(dev_priv->gmbus_wait_queue, C,
-                                         msecs_to_jiffies(10));
+                                         msecs_to_jiffies_timeout(10));
        else
                done = wait_for_atomic(C, 10) == 0;
        if (!done)
@@ -702,6 +702,9 @@ intel_dp_compute_config(struct intel_encoder *encoder,
        /* Walk through all bpp values. Luckily they're all nicely spaced with 2
         * bpc in between. */
        bpp = min_t(int, 8*3, pipe_config->pipe_bpp);
+       if (is_edp(intel_dp) && dev_priv->edp.bpp)
+               bpp = min_t(int, bpp, dev_priv->edp.bpp);
+
        for (; bpp >= 6*3; bpp -= 2*3) {
                mode_rate = intel_dp_link_required(target_clock, bpp);
 
@@ -739,6 +742,7 @@ found:
        intel_dp->link_bw = bws[clock];
        intel_dp->lane_count = lane_count;
        adjusted_mode->clock = drm_dp_bw_code_to_link_rate(intel_dp->link_bw);
+       pipe_config->pipe_bpp = bpp;
        pipe_config->pixel_target_clock = target_clock;
 
        DRM_DEBUG_KMS("DP link bw %02x lane count %d clock %d bpp %d\n",
@@ -751,20 +755,6 @@ found:
                               target_clock, adjusted_mode->clock,
                               &pipe_config->dp_m_n);
 
-       /*
-        * XXX: We have a strange regression where using the vbt edp bpp value
-        * for the link bw computation results in black screens, the panel only
-        * works when we do the computation at the usual 24bpp (but still
-        * requires us to use 18bpp). Until that's fully debugged, stay
-        * bug-for-bug compatible with the old code.
-        */
-       if (is_edp(intel_dp) && dev_priv->edp.bpp) {
-               DRM_DEBUG_KMS("clamping display bpc (was %d) to eDP (%d)\n",
-                             bpp, dev_priv->edp.bpp);
-               bpp = min_t(int, bpp, dev_priv->edp.bpp);
-       }
-       pipe_config->pipe_bpp = bpp;
-
        return true;
 }
 
@@ -1389,6 +1379,7 @@ static void intel_enable_dp(struct intel_encoder *encoder)
        ironlake_edp_panel_on(intel_dp);
        ironlake_edp_panel_vdd_off(intel_dp, true);
        intel_dp_complete_link_train(intel_dp);
+       intel_dp_stop_link_train(intel_dp);
        ironlake_edp_backlight_on(intel_dp);
 }
 
@@ -1711,10 +1702,9 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,
        struct drm_i915_private *dev_priv = dev->dev_private;
        enum port port = intel_dig_port->port;
        int ret;
-       uint32_t temp;
 
        if (HAS_DDI(dev)) {
-               temp = I915_READ(DP_TP_CTL(port));
+               uint32_t temp = I915_READ(DP_TP_CTL(port));
 
                if (dp_train_pat & DP_LINK_SCRAMBLING_DISABLE)
                        temp |= DP_TP_CTL_SCRAMBLE_DISABLE;
@@ -1724,18 +1714,6 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,
                temp &= ~DP_TP_CTL_LINK_TRAIN_MASK;
                switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) {
                case DP_TRAINING_PATTERN_DISABLE:
-
-                       if (port != PORT_A) {
-                               temp |= DP_TP_CTL_LINK_TRAIN_IDLE;
-                               I915_WRITE(DP_TP_CTL(port), temp);
-
-                               if (wait_for((I915_READ(DP_TP_STATUS(port)) &
-                                             DP_TP_STATUS_IDLE_DONE), 1))
-                                       DRM_ERROR("Timed out waiting for DP idle patterns\n");
-
-                               temp &= ~DP_TP_CTL_LINK_TRAIN_MASK;
-                       }
-
                        temp |= DP_TP_CTL_LINK_TRAIN_NORMAL;
 
                        break;
@@ -1811,6 +1789,37 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,
        return true;
 }
 
+static void intel_dp_set_idle_link_train(struct intel_dp *intel_dp)
+{
+       struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+       struct drm_device *dev = intel_dig_port->base.base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       enum port port = intel_dig_port->port;
+       uint32_t val;
+
+       if (!HAS_DDI(dev))
+               return;
+
+       val = I915_READ(DP_TP_CTL(port));
+       val &= ~DP_TP_CTL_LINK_TRAIN_MASK;
+       val |= DP_TP_CTL_LINK_TRAIN_IDLE;
+       I915_WRITE(DP_TP_CTL(port), val);
+
+       /*
+        * On PORT_A we can have only eDP in SST mode. There the only reason
+        * we need to set idle transmission mode is to work around a HW issue
+        * where we enable the pipe while not in idle link-training mode.
+        * In this case there is requirement to wait for a minimum number of
+        * idle patterns to be sent.
+        */
+       if (port == PORT_A)
+               return;
+
+       if (wait_for((I915_READ(DP_TP_STATUS(port)) & DP_TP_STATUS_IDLE_DONE),
+                    1))
+               DRM_ERROR("Timed out waiting for DP idle patterns\n");
+}
+
 /* Enable corresponding port and start training pattern 1 */
 void
 intel_dp_start_link_train(struct intel_dp *intel_dp)
@@ -1953,10 +1962,19 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
                ++tries;
        }
 
+       intel_dp_set_idle_link_train(intel_dp);
+
+       intel_dp->DP = DP;
+
        if (channel_eq)
                DRM_DEBUG_KMS("Channel EQ done. DP Training successful\n");
 
-       intel_dp_set_link_train(intel_dp, DP, DP_TRAINING_PATTERN_DISABLE);
+}
+
+void intel_dp_stop_link_train(struct intel_dp *intel_dp)
+{
+       intel_dp_set_link_train(intel_dp, intel_dp->DP,
+                               DP_TRAINING_PATTERN_DISABLE);
 }
 
 static void
@@ -2164,6 +2182,7 @@ intel_dp_check_link_status(struct intel_dp *intel_dp)
                              drm_get_encoder_name(&intel_encoder->base));
                intel_dp_start_link_train(intel_dp);
                intel_dp_complete_link_train(intel_dp);
+               intel_dp_stop_link_train(intel_dp);
        }
 }
 
index b5b6d19..624a9e6 100644 (file)
@@ -499,6 +499,7 @@ extern void intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 extern void intel_dp_init_link_config(struct intel_dp *intel_dp);
 extern void intel_dp_start_link_train(struct intel_dp *intel_dp);
 extern void intel_dp_complete_link_train(struct intel_dp *intel_dp);
+extern void intel_dp_stop_link_train(struct intel_dp *intel_dp);
 extern void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode);
 extern void intel_dp_encoder_destroy(struct drm_encoder *encoder);
 extern void intel_dp_check_link_status(struct intel_dp *intel_dp);
index 0e19e57..6b7c3ca 100644 (file)
@@ -262,10 +262,22 @@ void intel_fbdev_fini(struct drm_device *dev)
 void intel_fbdev_set_suspend(struct drm_device *dev, int state)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
-       if (!dev_priv->fbdev)
+       struct intel_fbdev *ifbdev = dev_priv->fbdev;
+       struct fb_info *info;
+
+       if (!ifbdev)
                return;
 
-       fb_set_suspend(dev_priv->fbdev->helper.fbdev, state);
+       info = ifbdev->helper.fbdev;
+
+       /* On resume from hibernation: If the object is shmemfs backed, it has
+        * been restored from swap. If the object is stolen however, it will be
+        * full of whatever garbage was left in there.
+        */
+       if (!state && ifbdev->ifb.obj->stolen)
+               memset_io(info->screen_base, 0, info->screen_size);
+
+       fb_set_suspend(info, state);
 }
 
 MODULE_LICENSE("GPL and additional rights");
index 5d24503..639fe19 100644 (file)
@@ -228,7 +228,7 @@ gmbus_wait_hw_status(struct drm_i915_private *dev_priv,
         * need to wake up periodically and check that ourselves. */
        I915_WRITE(GMBUS4 + reg_offset, gmbus4_irq_en);
 
-       for (i = 0; i < msecs_to_jiffies(50) + 1; i++) {
+       for (i = 0; i < msecs_to_jiffies_timeout(50); i++) {
                prepare_to_wait(&dev_priv->gmbus_wait_queue, &wait,
                                TASK_UNINTERRUPTIBLE);
 
@@ -263,7 +263,8 @@ gmbus_wait_idle(struct drm_i915_private *dev_priv)
        /* Important: The hw handles only the first bit, so set only one! */
        I915_WRITE(GMBUS4 + reg_offset, GMBUS_IDLE_EN);
 
-       ret = wait_event_timeout(dev_priv->gmbus_wait_queue, C, 10);
+       ret = wait_event_timeout(dev_priv->gmbus_wait_queue, C,
+                                msecs_to_jiffies_timeout(10));
 
        I915_WRITE(GMBUS4 + reg_offset, 0);
 
index f36f1ba..29412cc 100644 (file)
@@ -815,10 +815,10 @@ static const struct dmi_system_id intel_no_lvds[] = {
        },
        {
                .callback = intel_no_lvds_dmi_callback,
-               .ident = "Hewlett-Packard HP t5740e Thin Client",
+               .ident = "Hewlett-Packard HP t5740",
                .matches = {
                        DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "HP t5740e Thin Client"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, " t5740"),
                },
        },
        {
index de3b0dc..aa01128 100644 (file)
@@ -1301,17 +1301,17 @@ static void valleyview_update_wm(struct drm_device *dev)
 
        vlv_update_drain_latency(dev);
 
-       if (g4x_compute_wm0(dev, 0,
+       if (g4x_compute_wm0(dev, PIPE_A,
                            &valleyview_wm_info, latency_ns,
                            &valleyview_cursor_wm_info, latency_ns,
                            &planea_wm, &cursora_wm))
-               enabled |= 1;
+               enabled |= 1 << PIPE_A;
 
-       if (g4x_compute_wm0(dev, 1,
+       if (g4x_compute_wm0(dev, PIPE_B,
                            &valleyview_wm_info, latency_ns,
                            &valleyview_cursor_wm_info, latency_ns,
                            &planeb_wm, &cursorb_wm))
-               enabled |= 2;
+               enabled |= 1 << PIPE_B;
 
        if (single_plane_enabled(enabled) &&
            g4x_compute_srwm(dev, ffs(enabled) - 1,
@@ -1357,17 +1357,17 @@ static void g4x_update_wm(struct drm_device *dev)
        int plane_sr, cursor_sr;
        unsigned int enabled = 0;
 
-       if (g4x_compute_wm0(dev, 0,
+       if (g4x_compute_wm0(dev, PIPE_A,
                            &g4x_wm_info, latency_ns,
                            &g4x_cursor_wm_info, latency_ns,
                            &planea_wm, &cursora_wm))
-               enabled |= 1;
+               enabled |= 1 << PIPE_A;
 
-       if (g4x_compute_wm0(dev, 1,
+       if (g4x_compute_wm0(dev, PIPE_B,
                            &g4x_wm_info, latency_ns,
                            &g4x_cursor_wm_info, latency_ns,
                            &planeb_wm, &cursorb_wm))
-               enabled |= 2;
+               enabled |= 1 << PIPE_B;
 
        if (single_plane_enabled(enabled) &&
            g4x_compute_srwm(dev, ffs(enabled) - 1,
@@ -1716,7 +1716,7 @@ static void ironlake_update_wm(struct drm_device *dev)
        unsigned int enabled;
 
        enabled = 0;
-       if (g4x_compute_wm0(dev, 0,
+       if (g4x_compute_wm0(dev, PIPE_A,
                            &ironlake_display_wm_info,
                            ILK_LP0_PLANE_LATENCY,
                            &ironlake_cursor_wm_info,
@@ -1727,10 +1727,10 @@ static void ironlake_update_wm(struct drm_device *dev)
                DRM_DEBUG_KMS("FIFO watermarks For pipe A -"
                              " plane %d, " "cursor: %d\n",
                              plane_wm, cursor_wm);
-               enabled |= 1;
+               enabled |= 1 << PIPE_A;
        }
 
-       if (g4x_compute_wm0(dev, 1,
+       if (g4x_compute_wm0(dev, PIPE_B,
                            &ironlake_display_wm_info,
                            ILK_LP0_PLANE_LATENCY,
                            &ironlake_cursor_wm_info,
@@ -1741,7 +1741,7 @@ static void ironlake_update_wm(struct drm_device *dev)
                DRM_DEBUG_KMS("FIFO watermarks For pipe B -"
                              " plane %d, cursor: %d\n",
                              plane_wm, cursor_wm);
-               enabled |= 2;
+               enabled |= 1 << PIPE_B;
        }
 
        /*
@@ -1801,7 +1801,7 @@ static void sandybridge_update_wm(struct drm_device *dev)
        unsigned int enabled;
 
        enabled = 0;
-       if (g4x_compute_wm0(dev, 0,
+       if (g4x_compute_wm0(dev, PIPE_A,
                            &sandybridge_display_wm_info, latency,
                            &sandybridge_cursor_wm_info, latency,
                            &plane_wm, &cursor_wm)) {
@@ -1812,10 +1812,10 @@ static void sandybridge_update_wm(struct drm_device *dev)
                DRM_DEBUG_KMS("FIFO watermarks For pipe A -"
                              " plane %d, " "cursor: %d\n",
                              plane_wm, cursor_wm);
-               enabled |= 1;
+               enabled |= 1 << PIPE_A;
        }
 
-       if (g4x_compute_wm0(dev, 1,
+       if (g4x_compute_wm0(dev, PIPE_B,
                            &sandybridge_display_wm_info, latency,
                            &sandybridge_cursor_wm_info, latency,
                            &plane_wm, &cursor_wm)) {
@@ -1826,7 +1826,7 @@ static void sandybridge_update_wm(struct drm_device *dev)
                DRM_DEBUG_KMS("FIFO watermarks For pipe B -"
                              " plane %d, cursor: %d\n",
                              plane_wm, cursor_wm);
-               enabled |= 2;
+               enabled |= 1 << PIPE_B;
        }
 
        /*
@@ -1904,7 +1904,7 @@ static void ivybridge_update_wm(struct drm_device *dev)
        unsigned int enabled;
 
        enabled = 0;
-       if (g4x_compute_wm0(dev, 0,
+       if (g4x_compute_wm0(dev, PIPE_A,
                            &sandybridge_display_wm_info, latency,
                            &sandybridge_cursor_wm_info, latency,
                            &plane_wm, &cursor_wm)) {
@@ -1915,10 +1915,10 @@ static void ivybridge_update_wm(struct drm_device *dev)
                DRM_DEBUG_KMS("FIFO watermarks For pipe A -"
                              " plane %d, " "cursor: %d\n",
                              plane_wm, cursor_wm);
-               enabled |= 1;
+               enabled |= 1 << PIPE_A;
        }
 
-       if (g4x_compute_wm0(dev, 1,
+       if (g4x_compute_wm0(dev, PIPE_B,
                            &sandybridge_display_wm_info, latency,
                            &sandybridge_cursor_wm_info, latency,
                            &plane_wm, &cursor_wm)) {
@@ -1929,10 +1929,10 @@ static void ivybridge_update_wm(struct drm_device *dev)
                DRM_DEBUG_KMS("FIFO watermarks For pipe B -"
                              " plane %d, cursor: %d\n",
                              plane_wm, cursor_wm);
-               enabled |= 2;
+               enabled |= 1 << PIPE_B;
        }
 
-       if (g4x_compute_wm0(dev, 2,
+       if (g4x_compute_wm0(dev, PIPE_C,
                            &sandybridge_display_wm_info, latency,
                            &sandybridge_cursor_wm_info, latency,
                            &plane_wm, &cursor_wm)) {
@@ -1943,7 +1943,7 @@ static void ivybridge_update_wm(struct drm_device *dev)
                DRM_DEBUG_KMS("FIFO watermarks For pipe C -"
                              " plane %d, cursor: %d\n",
                              plane_wm, cursor_wm);
-               enabled |= 3;
+               enabled |= 1 << PIPE_C;
        }
 
        /*
index d154284..d4ea6c2 100644 (file)
@@ -1776,11 +1776,14 @@ static void intel_sdvo_get_lvds_modes(struct drm_connector *connector)
         * Assume that the preferred modes are
         * arranged in priority order.
         */
-       intel_ddc_get_modes(connector, intel_sdvo->i2c);
-       if (list_empty(&connector->probed_modes) == false)
-               goto end;
+       intel_ddc_get_modes(connector, &intel_sdvo->ddc);
 
-       /* Fetch modes from VBT */
+       /*
+        * Fetch modes from VBT. For SDVO prefer the VBT mode since some
+        * SDVO->LVDS transcoders can't cope with the EDID mode. Since
+        * drm_mode_probed_add adds the mode at the head of the list we add it
+        * last.
+        */
        if (dev_priv->sdvo_lvds_vbt_mode != NULL) {
                newmode = drm_mode_duplicate(connector->dev,
                                             dev_priv->sdvo_lvds_vbt_mode);
@@ -1792,7 +1795,6 @@ static void intel_sdvo_get_lvds_modes(struct drm_connector *connector)
                }
        }
 
-end:
        list_for_each_entry(newmode, &connector->probed_modes, head) {
                if (newmode->type & DRM_MODE_TYPE_PREFERRED) {
                        intel_sdvo->sdvo_lvds_fixed_mode =
@@ -2790,12 +2792,6 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)
                        SDVOB_HOTPLUG_INT_STATUS_I915 : SDVOC_HOTPLUG_INT_STATUS_I915;
        }
 
-       /* Only enable the hotplug irq if we need it, to work around noisy
-        * hotplug lines.
-        */
-       if (intel_sdvo->hotplug_active)
-               intel_encoder->hpd_pin = HPD_SDVO_B ? HPD_SDVO_B : HPD_SDVO_C;
-
        intel_encoder->compute_config = intel_sdvo_compute_config;
        intel_encoder->disable = intel_disable_sdvo;
        intel_encoder->mode_set = intel_sdvo_mode_set;
@@ -2814,6 +2810,14 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)
                goto err_output;
        }
 
+       /* Only enable the hotplug irq if we need it, to work around noisy
+        * hotplug lines.
+        */
+       if (intel_sdvo->hotplug_active) {
+               intel_encoder->hpd_pin =
+                       intel_sdvo->is_sdvob ?  HPD_SDVO_B : HPD_SDVO_C;
+       }
+
        /*
         * Cloning SDVO with anything is often impossible, since the SDVO
         * encoder can request a special input timing mode. And even if that's
index f988965..ee66bad 100644 (file)
@@ -46,29 +46,26 @@ static void mga_crtc_load_lut(struct drm_crtc *crtc)
 
 static inline void mga_wait_vsync(struct mga_device *mdev)
 {
-       unsigned int count = 0;
+       unsigned long timeout = jiffies + HZ/10;
        unsigned int status = 0;
 
        do {
                status = RREG32(MGAREG_Status);
-               count++;
-       } while ((status & 0x08) && (count < 250000));
-       count = 0;
+       } while ((status & 0x08) && time_before(jiffies, timeout));
+       timeout = jiffies + HZ/10;
        status = 0;
        do {
                status = RREG32(MGAREG_Status);
-               count++;
-       } while (!(status & 0x08) && (count < 250000));
+       } while (!(status & 0x08) && time_before(jiffies, timeout));
 }
 
 static inline void mga_wait_busy(struct mga_device *mdev)
 {
-       unsigned int count = 0;
+       unsigned long timeout = jiffies + HZ;
        unsigned int status = 0;
        do {
                status = RREG8(MGAREG_Status + 2);
-               count++;
-       } while ((status & 0x01) && (count < 500000));
+       } while ((status & 0x01) && time_before(jiffies, timeout));
 }
 
 /*
@@ -189,12 +186,12 @@ static int mga_g200wb_set_plls(struct mga_device *mdev, long clock)
                WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
                tmp = RREG8(DAC_DATA);
                tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
-               WREG_DAC(MGA1064_PIX_CLK_CTL_CLK_DIS, tmp);
+               WREG8(DAC_DATA, tmp);
 
                WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
                tmp = RREG8(DAC_DATA);
                tmp |= MGA1064_REMHEADCTL_CLKDIS;
-               WREG_DAC(MGA1064_REMHEADCTL, tmp);
+               WREG8(DAC_DATA, tmp);
 
                /* select PLL Set C */
                tmp = RREG8(MGAREG_MEM_MISC_READ);
@@ -204,7 +201,7 @@ static int mga_g200wb_set_plls(struct mga_device *mdev, long clock)
                WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
                tmp = RREG8(DAC_DATA);
                tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN | 0x80;
-               WREG_DAC(MGA1064_PIX_CLK_CTL, tmp);
+               WREG8(DAC_DATA, tmp);
 
                udelay(500);
 
@@ -212,7 +209,7 @@ static int mga_g200wb_set_plls(struct mga_device *mdev, long clock)
                WREG8(DAC_INDEX, MGA1064_VREF_CTL);
                tmp = RREG8(DAC_DATA);
                tmp &= ~0x04;
-               WREG_DAC(MGA1064_VREF_CTL, tmp);
+               WREG8(DAC_DATA, tmp);
 
                udelay(50);
 
@@ -236,13 +233,13 @@ static int mga_g200wb_set_plls(struct mga_device *mdev, long clock)
                tmp = RREG8(DAC_DATA);
                tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;
                tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL;
-               WREG_DAC(MGA1064_PIX_CLK_CTL, tmp);
+               WREG8(DAC_DATA, tmp);
 
                WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
                tmp = RREG8(DAC_DATA);
                tmp &= ~MGA1064_REMHEADCTL_CLKSL_MSK;
                tmp |= MGA1064_REMHEADCTL_CLKSL_PLL;
-               WREG_DAC(MGA1064_REMHEADCTL, tmp);
+               WREG8(DAC_DATA, tmp);
 
                /* reset dotclock rate bit */
                WREG8(MGAREG_SEQ_INDEX, 1);
@@ -253,7 +250,7 @@ static int mga_g200wb_set_plls(struct mga_device *mdev, long clock)
                WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
                tmp = RREG8(DAC_DATA);
                tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
-               WREG_DAC(MGA1064_PIX_CLK_CTL, tmp);
+               WREG8(DAC_DATA, tmp);
 
                vcount = RREG8(MGAREG_VCOUNT);
 
@@ -318,7 +315,7 @@ static int mga_g200ev_set_plls(struct mga_device *mdev, long clock)
        WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
        tmp = RREG8(DAC_DATA);
        tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
-       WREG_DAC(MGA1064_PIX_CLK_CTL_CLK_DIS, tmp);
+       WREG8(DAC_DATA, tmp);
 
        tmp = RREG8(MGAREG_MEM_MISC_READ);
        tmp |= 0x3 << 2;
@@ -326,12 +323,12 @@ static int mga_g200ev_set_plls(struct mga_device *mdev, long clock)
 
        WREG8(DAC_INDEX, MGA1064_PIX_PLL_STAT);
        tmp = RREG8(DAC_DATA);
-       WREG_DAC(MGA1064_PIX_PLL_STAT, tmp & ~0x40);
+       WREG8(DAC_DATA, tmp & ~0x40);
 
        WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
        tmp = RREG8(DAC_DATA);
        tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
-       WREG_DAC(MGA1064_PIX_CLK_CTL, tmp);
+       WREG8(DAC_DATA, tmp);
 
        WREG_DAC(MGA1064_EV_PIX_PLLC_M, m);
        WREG_DAC(MGA1064_EV_PIX_PLLC_N, n);
@@ -342,7 +339,7 @@ static int mga_g200ev_set_plls(struct mga_device *mdev, long clock)
        WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
        tmp = RREG8(DAC_DATA);
        tmp &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
-       WREG_DAC(MGA1064_PIX_CLK_CTL, tmp);
+       WREG8(DAC_DATA, tmp);
 
        udelay(500);
 
@@ -350,11 +347,11 @@ static int mga_g200ev_set_plls(struct mga_device *mdev, long clock)
        tmp = RREG8(DAC_DATA);
        tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;
        tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL;
-       WREG_DAC(MGA1064_PIX_CLK_CTL, tmp);
+       WREG8(DAC_DATA, tmp);
 
        WREG8(DAC_INDEX, MGA1064_PIX_PLL_STAT);
        tmp = RREG8(DAC_DATA);
-       WREG_DAC(MGA1064_PIX_PLL_STAT, tmp | 0x40);
+       WREG8(DAC_DATA, tmp | 0x40);
 
        tmp = RREG8(MGAREG_MEM_MISC_READ);
        tmp |= (0x3 << 2);
@@ -363,7 +360,7 @@ static int mga_g200ev_set_plls(struct mga_device *mdev, long clock)
        WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
        tmp = RREG8(DAC_DATA);
        tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
-       WREG_DAC(MGA1064_PIX_CLK_CTL, tmp);
+       WREG8(DAC_DATA, tmp);
 
        return 0;
 }
@@ -416,7 +413,7 @@ static int mga_g200eh_set_plls(struct mga_device *mdev, long clock)
                WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
                tmp = RREG8(DAC_DATA);
                tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
-               WREG_DAC(MGA1064_PIX_CLK_CTL_CLK_DIS, tmp);
+               WREG8(DAC_DATA, tmp);
 
                tmp = RREG8(MGAREG_MEM_MISC_READ);
                tmp |= 0x3 << 2;
@@ -425,7 +422,7 @@ static int mga_g200eh_set_plls(struct mga_device *mdev, long clock)
                WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
                tmp = RREG8(DAC_DATA);
                tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
-               WREG_DAC(MGA1064_PIX_CLK_CTL, tmp);
+               WREG8(DAC_DATA, tmp);
 
                udelay(500);
 
@@ -439,13 +436,13 @@ static int mga_g200eh_set_plls(struct mga_device *mdev, long clock)
                tmp = RREG8(DAC_DATA);
                tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;
                tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL;
-               WREG_DAC(MGA1064_PIX_CLK_CTL, tmp);
+               WREG8(DAC_DATA, tmp);
 
                WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
                tmp = RREG8(DAC_DATA);
                tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
                tmp &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
-               WREG_DAC(MGA1064_PIX_CLK_CTL, tmp);
+               WREG8(DAC_DATA, tmp);
 
                vcount = RREG8(MGAREG_VCOUNT);
 
@@ -515,12 +512,12 @@ static int mga_g200er_set_plls(struct mga_device *mdev, long clock)
        WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
        tmp = RREG8(DAC_DATA);
        tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
-       WREG_DAC(MGA1064_PIX_CLK_CTL_CLK_DIS, tmp);
+       WREG8(DAC_DATA, tmp);
 
        WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
        tmp = RREG8(DAC_DATA);
        tmp |= MGA1064_REMHEADCTL_CLKDIS;
-       WREG_DAC(MGA1064_REMHEADCTL, tmp);
+       WREG8(DAC_DATA, tmp);
 
        tmp = RREG8(MGAREG_MEM_MISC_READ);
        tmp |= (0x3<<2) | 0xc0;
@@ -530,7 +527,7 @@ static int mga_g200er_set_plls(struct mga_device *mdev, long clock)
        tmp = RREG8(DAC_DATA);
        tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
        tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
-       WREG_DAC(MGA1064_PIX_CLK_CTL, tmp);
+       WREG8(DAC_DATA, tmp);
 
        udelay(500);
 
@@ -657,12 +654,26 @@ static void mga_g200wb_commit(struct drm_crtc *crtc)
        WREG_DAC(MGA1064_GEN_IO_DATA, tmp);
 }
 
-
+/*
+   This is how the framebuffer base address is stored in g200 cards:
+   * Assume @offset is the gpu_addr variable of the framebuffer object
+   * Then addr is the number of _pixels_ (not bytes) from the start of
+     VRAM to the first pixel we want to display. (divided by 2 for 32bit
+     framebuffers)
+   * addr is stored in the CRTCEXT0, CRTCC and CRTCD registers
+   addr<20> -> CRTCEXT0<6>
+   addr<19-16> -> CRTCEXT0<3-0>
+   addr<15-8> -> CRTCC<7-0>
+   addr<7-0> -> CRTCD<7-0>
+   CRTCEXT0 has to be programmed last to trigger an update and make the
+   new addr variable take effect.
+ */
 void mga_set_start_address(struct drm_crtc *crtc, unsigned offset)
 {
        struct mga_device *mdev = crtc->dev->dev_private;
        u32 addr;
        int count;
+       u8 crtcext0;
 
        while (RREG8(0x1fda) & 0x08);
        while (!(RREG8(0x1fda) & 0x08));
@@ -670,10 +681,17 @@ void mga_set_start_address(struct drm_crtc *crtc, unsigned offset)
        count = RREG8(MGAREG_VCOUNT) + 2;
        while (RREG8(MGAREG_VCOUNT) < count);
 
-       addr = offset >> 2;
+       WREG8(MGAREG_CRTCEXT_INDEX, 0);
+       crtcext0 = RREG8(MGAREG_CRTCEXT_DATA);
+       crtcext0 &= 0xB0;
+       addr = offset / 8;
+       /* Can't store addresses any higher than that...
+          but we also don't have more than 16MB of memory, so it should be fine. */
+       WARN_ON(addr > 0x1fffff);
+       crtcext0 |= (!!(addr & (1<<20)))<<6;
        WREG_CRT(0x0d, (u8)(addr & 0xff));
        WREG_CRT(0x0c, (u8)(addr >> 8) & 0xff);
-       WREG_CRT(0xaf, (u8)(addr >> 16) & 0xf);
+       WREG_ECRT(0x0, ((u8)(addr >> 16) & 0xf) | crtcext0);
 }
 
 
@@ -829,11 +847,7 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,
 
 
        for (i = 0; i < sizeof(dacvalue); i++) {
-               if ((i <= 0x03) ||
-                   (i == 0x07) ||
-                   (i == 0x0b) ||
-                   (i == 0x0f) ||
-                   ((i >= 0x13) && (i <= 0x17)) ||
+               if ((i <= 0x17) ||
                    (i == 0x1b) ||
                    (i == 0x1c) ||
                    ((i >= 0x1f) && (i <= 0x29)) ||
@@ -1020,13 +1034,14 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,
                        else
                                hi_pri_lvl = 5;
 
-                       WREG8(0x1fde, 0x06);
-                       WREG8(0x1fdf, hi_pri_lvl);
+                       WREG8(MGAREG_CRTCEXT_INDEX, 0x06);
+                       WREG8(MGAREG_CRTCEXT_DATA, hi_pri_lvl);
                } else {
+                       WREG8(MGAREG_CRTCEXT_INDEX, 0x06);
                        if (mdev->reg_1e24 >= 0x01)
-                               WREG8(0x1fdf, 0x03);
+                               WREG8(MGAREG_CRTCEXT_DATA, 0x03);
                        else
-                               WREG8(0x1fdf, 0x04);
+                               WREG8(MGAREG_CRTCEXT_DATA, 0x04);
                }
        }
        return 0;
index 955af12..a36e64e 100644 (file)
@@ -138,7 +138,6 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_BSP    ] = &nvc0_bsp_oclass;
                device->oclass[NVDEV_ENGINE_PPP    ] = &nvc0_ppp_oclass;
                device->oclass[NVDEV_ENGINE_COPY0  ] = &nvc0_copy0_oclass;
-               device->oclass[NVDEV_ENGINE_COPY1  ] = &nvc0_copy1_oclass;
                device->oclass[NVDEV_ENGINE_DISP   ] = &nva3_disp_oclass;
                break;
        case 0xce:
@@ -225,7 +224,6 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_BSP    ] = &nvc0_bsp_oclass;
                device->oclass[NVDEV_ENGINE_PPP    ] = &nvc0_ppp_oclass;
                device->oclass[NVDEV_ENGINE_COPY0  ] = &nvc0_copy0_oclass;
-               device->oclass[NVDEV_ENGINE_COPY1  ] = &nvc0_copy1_oclass;
                device->oclass[NVDEV_ENGINE_DISP   ] = &nva3_disp_oclass;
                break;
        case 0xc8:
index d0817d9..f02fd9f 100644 (file)
@@ -50,11 +50,16 @@ nv50_dac_sense(struct nv50_disp_priv *priv, int or, u32 loadval)
 {
        const u32 doff = (or * 0x800);
        int load = -EINVAL;
+       nv_mask(priv, 0x61a004 + doff, 0x807f0000, 0x80150000);
+       nv_wait(priv, 0x61a004 + doff, 0x80000000, 0x00000000);
        nv_wr32(priv, 0x61a00c + doff, 0x00100000 | loadval);
-       udelay(9500);
+       mdelay(9);
+       udelay(500);
        nv_wr32(priv, 0x61a00c + doff, 0x80000000);
        load = (nv_rd32(priv, 0x61a00c + doff) & 0x38000000) >> 27;
        nv_wr32(priv, 0x61a00c + doff, 0x00000000);
+       nv_mask(priv, 0x61a004 + doff, 0x807f0000, 0x80550000);
+       nv_wait(priv, 0x61a004 + doff, 0x80000000, 0x00000000);
        return load;
 }
 
index 0d36bdc..7fdade6 100644 (file)
@@ -55,6 +55,10 @@ nv84_hdmi_ctrl(struct nv50_disp_priv *priv, int head, int or, u32 data)
        nv_wr32(priv, 0x616510 + hoff, 0x00000000);
        nv_mask(priv, 0x616500 + hoff, 0x00000001, 0x00000001);
 
+       nv_mask(priv, 0x6165d0 + hoff, 0x00070001, 0x00010001); /* SPARE, HW_CTS */
+       nv_mask(priv, 0x616568 + hoff, 0x00010101, 0x00000000); /* ACR_CTRL, ?? */
+       nv_mask(priv, 0x616578 + hoff, 0x80000000, 0x80000000); /* ACR_0441_ENABLE */
+
        /* ??? */
        nv_mask(priv, 0x61733c, 0x00100000, 0x00100000); /* RESETF */
        nv_mask(priv, 0x61733c, 0x10000000, 0x10000000); /* LOOKUP_EN */
index ddaeb55..e9b8217 100644 (file)
@@ -40,8 +40,8 @@
  * FIFO channel objects
  ******************************************************************************/
 
-void
-nv50_fifo_playlist_update(struct nv50_fifo_priv *priv)
+static void
+nv50_fifo_playlist_update_locked(struct nv50_fifo_priv *priv)
 {
        struct nouveau_bar *bar = nouveau_bar(priv);
        struct nouveau_gpuobj *cur;
@@ -62,6 +62,14 @@ nv50_fifo_playlist_update(struct nv50_fifo_priv *priv)
        nv_wr32(priv, 0x002500, 0x00000101);
 }
 
+void
+nv50_fifo_playlist_update(struct nv50_fifo_priv *priv)
+{
+       mutex_lock(&nv_subdev(priv)->mutex);
+       nv50_fifo_playlist_update_locked(priv);
+       mutex_unlock(&nv_subdev(priv)->mutex);
+}
+
 static int
 nv50_fifo_context_attach(struct nouveau_object *parent,
                         struct nouveau_object *object)
@@ -487,7 +495,7 @@ nv50_fifo_init(struct nouveau_object *object)
 
        for (i = 0; i < 128; i++)
                nv_wr32(priv, 0x002600 + (i * 4), 0x00000000);
-       nv50_fifo_playlist_update(priv);
+       nv50_fifo_playlist_update_locked(priv);
 
        nv_wr32(priv, 0x003200, 0x00000001);
        nv_wr32(priv, 0x003250, 0x00000001);
index 4d4a6b9..46dfa68 100644 (file)
@@ -71,6 +71,7 @@ nvc0_fifo_playlist_update(struct nvc0_fifo_priv *priv)
        struct nouveau_gpuobj *cur;
        int i, p;
 
+       mutex_lock(&nv_subdev(priv)->mutex);
        cur = priv->playlist[priv->cur_playlist];
        priv->cur_playlist = !priv->cur_playlist;
 
@@ -87,6 +88,7 @@ nvc0_fifo_playlist_update(struct nvc0_fifo_priv *priv)
        nv_wr32(priv, 0x002274, 0x01f00000 | (p >> 3));
        if (!nv_wait(priv, 0x00227c, 0x00100000, 0x00000000))
                nv_error(priv, "playlist update failed\n");
+       mutex_unlock(&nv_subdev(priv)->mutex);
 }
 
 static int
@@ -248,9 +250,17 @@ nvc0_fifo_chan_fini(struct nouveau_object *object, bool suspend)
        struct nvc0_fifo_priv *priv = (void *)object->engine;
        struct nvc0_fifo_chan *chan = (void *)object;
        u32 chid = chan->base.chid;
+       u32 mask, engine;
 
        nv_mask(priv, 0x003004 + (chid * 8), 0x00000001, 0x00000000);
        nvc0_fifo_playlist_update(priv);
+       mask = nv_rd32(priv, 0x0025a4);
+       for (engine = 0; mask && engine < 16; engine++) {
+               if (!(mask & (1 << engine)))
+                       continue;
+               nv_mask(priv, 0x0025a8 + (engine * 4), 0x00000000, 0x00000000);
+               mask &= ~(1 << engine);
+       }
        nv_wr32(priv, 0x003000 + (chid * 8), 0x00000000);
 
        return nouveau_fifo_channel_fini(&chan->base, suspend);
index 9151919..56192a7 100644 (file)
@@ -94,11 +94,13 @@ nve0_fifo_playlist_update(struct nve0_fifo_priv *priv, u32 engine)
        u32 match = (engine << 16) | 0x00000001;
        int i, p;
 
+       mutex_lock(&nv_subdev(priv)->mutex);
        cur = engn->playlist[engn->cur_playlist];
        if (unlikely(cur == NULL)) {
                int ret = nouveau_gpuobj_new(nv_object(priv), NULL,
                                             0x8000, 0x1000, 0, &cur);
                if (ret) {
+                       mutex_unlock(&nv_subdev(priv)->mutex);
                        nv_error(priv, "playlist alloc failed\n");
                        return;
                }
@@ -122,6 +124,7 @@ nve0_fifo_playlist_update(struct nve0_fifo_priv *priv, u32 engine)
        nv_wr32(priv, 0x002274, (engine << 20) | (p >> 3));
        if (!nv_wait(priv, 0x002284 + (engine * 4), 0x00100000, 0x00000000))
                nv_error(priv, "playlist %d update timeout\n", engine);
+       mutex_unlock(&nv_subdev(priv)->mutex);
 }
 
 static int
index 0a393f7..5a5961b 100644 (file)
@@ -218,7 +218,7 @@ struct nv04_display_class {
 #define NV50_DISP_DAC_PWR_STATE                                      0x00000040
 #define NV50_DISP_DAC_PWR_STATE_ON                                   0x00000000
 #define NV50_DISP_DAC_PWR_STATE_OFF                                  0x00000040
-#define NV50_DISP_DAC_LOAD                                           0x0002000c
+#define NV50_DISP_DAC_LOAD                                           0x00020100
 #define NV50_DISP_DAC_LOAD_VALUE                                     0x00000007
 
 #define NV50_DISP_PIOR_MTHD                                          0x00030000
index c300b5e..c434d39 100644 (file)
@@ -1940,8 +1940,8 @@ init_zm_mask_add(struct nvbios_init *init)
        trace("ZM_MASK_ADD\tR[0x%06x] &= 0x%08x += 0x%08x\n", addr, mask, add);
        init->offset += 13;
 
-       data  =  init_rd32(init, addr) & mask;
-       data |= ((data + add) & ~mask);
+       data =  init_rd32(init, addr);
+       data = (data & mask) | ((data + add) & ~mask);
        init_wr32(init, addr, data);
 }
 
index e4940fb..fb794e9 100644 (file)
@@ -29,7 +29,6 @@
 struct nvc0_ltcg_priv {
        struct nouveau_ltcg base;
        u32 part_nr;
-       u32 part_mask;
        u32 subp_nr;
        struct nouveau_mm tags;
        u32 num_tags;
@@ -105,8 +104,6 @@ nvc0_ltcg_tags_clear(struct nouveau_ltcg *ltcg, u32 first, u32 count)
 
        /* wait until it's finished with clearing */
        for (p = 0; p < priv->part_nr; ++p) {
-               if (!(priv->part_mask & (1 << p)))
-                       continue;
                for (i = 0; i < priv->subp_nr; ++i)
                        nv_wait(priv, 0x1410c8 + p * 0x2000 + i * 0x400, ~0, 0);
        }
@@ -121,6 +118,8 @@ nvc0_ltcg_init_tag_ram(struct nouveau_fb *pfb, struct nvc0_ltcg_priv *priv)
        int ret;
 
        nv_wr32(priv, 0x17e8d8, priv->part_nr);
+       if (nv_device(pfb)->card_type >= NV_E0)
+               nv_wr32(priv, 0x17e000, priv->part_nr);
 
        /* tags for 1/4 of VRAM should be enough (8192/4 per GiB of VRAM) */
        priv->num_tags = (pfb->ram.size >> 17) / 4;
@@ -167,16 +166,20 @@ nvc0_ltcg_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 {
        struct nvc0_ltcg_priv *priv;
        struct nouveau_fb *pfb = nouveau_fb(parent);
-       int ret;
+       u32 parts, mask;
+       int ret, i;
 
        ret = nouveau_ltcg_create(parent, engine, oclass, &priv);
        *pobject = nv_object(priv);
        if (ret)
                return ret;
 
-       priv->part_nr = nv_rd32(priv, 0x022438);
-       priv->part_mask = nv_rd32(priv, 0x022554);
-
+       parts = nv_rd32(priv, 0x022438);
+       mask = nv_rd32(priv, 0x022554);
+       for (i = 0; i < parts; i++) {
+               if (!(mask & (1 << i)))
+                       priv->part_nr++;
+       }
        priv->subp_nr = nv_rd32(priv, 0x17e8dc) >> 28;
 
        nv_mask(priv, 0x17e820, 0x00100000, 0x00000000); /* INTR_EN &= ~0x10 */
index 7bf22d4..f17dc2a 100644 (file)
@@ -638,17 +638,8 @@ nouveau_finish_page_flip(struct nouveau_channel *chan,
        }
 
        s = list_first_entry(&fctx->flip, struct nouveau_page_flip_state, head);
-       if (s->event) {
-               struct drm_pending_vblank_event *e = s->event;
-               struct timeval now;
-
-               do_gettimeofday(&now);
-               e->event.sequence = 0;
-               e->event.tv_sec = now.tv_sec;
-               e->event.tv_usec = now.tv_usec;
-               list_add_tail(&e->base.link, &e->base.file_priv->event_list);
-               wake_up_interruptible(&e->base.file_priv->event_wait);
-       }
+       if (s->event)
+               drm_send_vblank_event(dev, -1, s->event);
 
        list_del(&s->head);
        if (ps)
index 46c152f..383f4e6 100644 (file)
@@ -453,18 +453,32 @@ nouveau_do_suspend(struct drm_device *dev)
        NV_INFO(drm, "evicting buffers...\n");
        ttm_bo_evict_mm(&drm->ttm.bdev, TTM_PL_VRAM);
 
+       NV_INFO(drm, "waiting for kernel channels to go idle...\n");
+       if (drm->cechan) {
+               ret = nouveau_channel_idle(drm->cechan);
+               if (ret)
+                       return ret;
+       }
+
+       if (drm->channel) {
+               ret = nouveau_channel_idle(drm->channel);
+               if (ret)
+                       return ret;
+       }
+
+       NV_INFO(drm, "suspending client object trees...\n");
        if (drm->fence && nouveau_fence(drm)->suspend) {
                if (!nouveau_fence(drm)->suspend(drm))
                        return -ENOMEM;
        }
 
-       NV_INFO(drm, "suspending client object trees...\n");
        list_for_each_entry(cli, &drm->clients, head) {
                ret = nouveau_client_fini(&cli->base, true);
                if (ret)
                        goto fail_client;
        }
 
+       NV_INFO(drm, "suspending kernel object tree...\n");
        ret = nouveau_client_fini(&drm->client.base, true);
        if (ret)
                goto fail_client;
@@ -514,17 +528,18 @@ nouveau_do_resume(struct drm_device *dev)
 
        nouveau_agp_reset(drm);
 
-       NV_INFO(drm, "resuming client object trees...\n");
+       NV_INFO(drm, "resuming kernel object tree...\n");
        nouveau_client_init(&drm->client.base);
        nouveau_agp_init(drm);
 
+       NV_INFO(drm, "resuming client object trees...\n");
+       if (drm->fence && nouveau_fence(drm)->resume)
+               nouveau_fence(drm)->resume(drm);
+
        list_for_each_entry(cli, &drm->clients, head) {
                nouveau_client_init(&cli->base);
        }
 
-       if (drm->fence && nouveau_fence(drm)->resume)
-               nouveau_fence(drm)->resume(drm);
-
        nouveau_run_vbios_init(dev);
        nouveau_pm_resume(dev);
 
index ebf0a68..dd5e01f 100644 (file)
@@ -1554,7 +1554,9 @@ nv50_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
 {
        struct nv50_disp *disp = nv50_disp(encoder->dev);
        int ret, or = nouveau_encoder(encoder)->or;
-       u32 load = 0;
+       u32 load = nouveau_drm(encoder->dev)->vbios.dactestval;
+       if (load == 0)
+               load = 340;
 
        ret = nv_exec(disp->core, NV50_DISP_DAC_LOAD + or, &load, sizeof(load));
        if (ret || load != 7)
index 9c53c25..826586f 100644 (file)
@@ -649,6 +649,9 @@ static void pdev_shutdown(struct platform_device *device)
 
 static int pdev_probe(struct platform_device *device)
 {
+       if (omapdss_is_initialized() == false)
+               return -EPROBE_DEFER;
+
        DBG("%s", device->name);
        return drm_platform_init(&omap_drm_driver, device);
 }
index 2f1a57e..d6c1279 100644 (file)
@@ -4,6 +4,7 @@ config DRM_QXL
        select FB_SYS_FILLRECT
        select FB_SYS_COPYAREA
        select FB_SYS_IMAGEBLIT
+       select FB_DEFERRED_IO
         select DRM_KMS_HELPER
         select DRM_TTM
        help
index 08b0823..f867714 100644 (file)
@@ -277,7 +277,7 @@ out_unref:
        return 0;
 }
 
-static int wait_for_io_cmd_user(struct qxl_device *qdev, uint8_t val, long port)
+static int wait_for_io_cmd_user(struct qxl_device *qdev, uint8_t val, long port, bool intr)
 {
        int irq_num;
        long addr = qdev->io_base + port;
@@ -285,20 +285,29 @@ static int wait_for_io_cmd_user(struct qxl_device *qdev, uint8_t val, long port)
 
        mutex_lock(&qdev->async_io_mutex);
        irq_num = atomic_read(&qdev->irq_received_io_cmd);
-
-
        if (qdev->last_sent_io_cmd > irq_num) {
-               ret = wait_event_interruptible(qdev->io_cmd_event,
-                                              atomic_read(&qdev->irq_received_io_cmd) > irq_num);
-               if (ret)
+               if (intr)
+                       ret = wait_event_interruptible_timeout(qdev->io_cmd_event,
+                                                              atomic_read(&qdev->irq_received_io_cmd) > irq_num, 5*HZ);
+               else
+                       ret = wait_event_timeout(qdev->io_cmd_event,
+                                                atomic_read(&qdev->irq_received_io_cmd) > irq_num, 5*HZ);
+               /* 0 is timeout, just bail the "hw" has gone away */
+               if (ret <= 0)
                        goto out;
                irq_num = atomic_read(&qdev->irq_received_io_cmd);
        }
        outb(val, addr);
        qdev->last_sent_io_cmd = irq_num + 1;
-       ret = wait_event_interruptible(qdev->io_cmd_event,
-                                      atomic_read(&qdev->irq_received_io_cmd) > irq_num);
+       if (intr)
+               ret = wait_event_interruptible_timeout(qdev->io_cmd_event,
+                                                      atomic_read(&qdev->irq_received_io_cmd) > irq_num, 5*HZ);
+       else
+               ret = wait_event_timeout(qdev->io_cmd_event,
+                                        atomic_read(&qdev->irq_received_io_cmd) > irq_num, 5*HZ);
 out:
+       if (ret > 0)
+               ret = 0;
        mutex_unlock(&qdev->async_io_mutex);
        return ret;
 }
@@ -308,7 +317,7 @@ static void wait_for_io_cmd(struct qxl_device *qdev, uint8_t val, long port)
        int ret;
 
 restart:
-       ret = wait_for_io_cmd_user(qdev, val, port);
+       ret = wait_for_io_cmd_user(qdev, val, port, false);
        if (ret == -ERESTARTSYS)
                goto restart;
 }
@@ -340,7 +349,7 @@ int qxl_io_update_area(struct qxl_device *qdev, struct qxl_bo *surf,
        mutex_lock(&qdev->update_area_mutex);
        qdev->ram_header->update_area = *area;
        qdev->ram_header->update_surface = surface_id;
-       ret = wait_for_io_cmd_user(qdev, 0, QXL_IO_UPDATE_AREA_ASYNC);
+       ret = wait_for_io_cmd_user(qdev, 0, QXL_IO_UPDATE_AREA_ASYNC, true);
        mutex_unlock(&qdev->update_area_mutex);
        return ret;
 }
index fcfd443..823d29e 100644 (file)
@@ -428,10 +428,10 @@ static int qxl_framebuffer_surface_dirty(struct drm_framebuffer *fb,
        int inc = 1;
 
        qobj = gem_to_qxl_bo(qxl_fb->obj);
-       if (qxl_fb != qdev->active_user_framebuffer) {
-               DRM_INFO("%s: qxl_fb 0x%p != qdev->active_user_framebuffer 0x%p\n",
-                       __func__, qxl_fb, qdev->active_user_framebuffer);
-       }
+       /* if we aren't primary surface ignore this */
+       if (!qobj->is_primary)
+               return 0;
+
        if (!num_clips) {
                num_clips = 1;
                clips = &norect;
@@ -604,7 +604,6 @@ static int qxl_crtc_mode_set(struct drm_crtc *crtc,
                                               mode->hdisplay,
                                               mode->vdisplay);
        }
-       qdev->mode_set = true;
        return 0;
 }
 
@@ -893,7 +892,6 @@ qxl_user_framebuffer_create(struct drm_device *dev,
 {
        struct drm_gem_object *obj;
        struct qxl_framebuffer *qxl_fb;
-       struct qxl_device *qdev = dev->dev_private;
        int ret;
 
        obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]);
@@ -909,13 +907,6 @@ qxl_user_framebuffer_create(struct drm_device *dev,
                return NULL;
        }
 
-       if (qdev->active_user_framebuffer) {
-               DRM_INFO("%s: active_user_framebuffer %p -> %p\n",
-                        __func__,
-                        qdev->active_user_framebuffer, qxl_fb);
-       }
-       qdev->active_user_framebuffer = qxl_fb;
-
        return &qxl_fb->base;
 }
 
index 52b582c..43d06ab 100644 (file)
@@ -255,12 +255,6 @@ struct qxl_device {
        struct qxl_gem          gem;
        struct qxl_mode_info mode_info;
 
-       /*
-        * last created framebuffer with fb_create
-        * only used by debugfs dumbppm
-        */
-       struct qxl_framebuffer *active_user_framebuffer;
-
        struct fb_info                  *fbdev_info;
        struct qxl_framebuffer  *fbdev_qfb;
        void *ram_physical;
@@ -270,7 +264,6 @@ struct qxl_device {
        struct qxl_ring *cursor_ring;
 
        struct qxl_ram_header *ram_header;
-       bool mode_set;
 
        bool primary_created;
 
index 04b64f9..a4b71b2 100644 (file)
@@ -151,7 +151,7 @@ static int qxl_execbuffer_ioctl(struct drm_device *dev, void *data,
                struct qxl_bo *cmd_bo;
                int release_type;
                struct drm_qxl_command *commands =
-                       (struct drm_qxl_command *)execbuffer->commands;
+                       (struct drm_qxl_command *)(uintptr_t)execbuffer->commands;
 
                if (DRM_COPY_FROM_USER(&user_cmd, &commands[cmd_num],
                                       sizeof(user_cmd)))
@@ -193,7 +193,7 @@ static int qxl_execbuffer_ioctl(struct drm_device *dev, void *data,
 
                for (i = 0 ; i < user_cmd.relocs_num; ++i) {
                        if (DRM_COPY_FROM_USER(&reloc,
-                                              &((struct drm_qxl_reloc *)user_cmd.relocs)[i],
+                                              &((struct drm_qxl_reloc *)(uintptr_t)user_cmd.relocs)[i],
                                               sizeof(reloc))) {
                                qxl_bo_list_unreserve(&reloc_list, true);
                                qxl_release_unreserve(qdev, release);
@@ -294,6 +294,7 @@ static int qxl_update_area_ioctl(struct drm_device *dev, void *data,
                goto out;
 
        if (!qobj->pin_count) {
+               qxl_ttm_placement_from_domain(qobj, qobj->type);
                ret = ttm_bo_validate(&qobj->tbo, &qobj->placement,
                                      true, false);
                if (unlikely(ret))
index 85127ed..e27ce2a 100644 (file)
@@ -128,12 +128,13 @@ int qxl_device_init(struct qxl_device *qdev,
 
        qdev->vram_mapping = io_mapping_create_wc(qdev->vram_base, pci_resource_len(pdev, 0));
        qdev->surface_mapping = io_mapping_create_wc(qdev->surfaceram_base, qdev->surfaceram_size);
-       DRM_DEBUG_KMS("qxl: vram %p-%p(%dM %dk), surface %p-%p(%dM %dk)\n",
-                (void *)qdev->vram_base, (void *)pci_resource_end(pdev, 0),
+       DRM_DEBUG_KMS("qxl: vram %llx-%llx(%dM %dk), surface %llx-%llx(%dM %dk)\n",
+                (unsigned long long)qdev->vram_base,
+                (unsigned long long)pci_resource_end(pdev, 0),
                 (int)pci_resource_len(pdev, 0) / 1024 / 1024,
                 (int)pci_resource_len(pdev, 0) / 1024,
-                (void *)qdev->surfaceram_base,
-                (void *)pci_resource_end(pdev, 1),
+                (unsigned long long)qdev->surfaceram_base,
+                (unsigned long long)pci_resource_end(pdev, 1),
                 (int)qdev->surfaceram_size / 1024 / 1024,
                 (int)qdev->surfaceram_size / 1024);
 
index 6d6fdb3..d5df8fd 100644 (file)
@@ -1811,12 +1811,9 @@ static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc,
 
 static void atombios_crtc_prepare(struct drm_crtc *crtc)
 {
-       struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
        struct drm_device *dev = crtc->dev;
        struct radeon_device *rdev = dev->dev_private;
 
-       radeon_crtc->in_mode_set = true;
-
        /* disable crtc pair power gating before programming */
        if (ASIC_IS_DCE6(rdev))
                atombios_powergate_crtc(crtc, ATOM_DISABLE);
@@ -1827,11 +1824,8 @@ static void atombios_crtc_prepare(struct drm_crtc *crtc)
 
 static void atombios_crtc_commit(struct drm_crtc *crtc)
 {
-       struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
-
        atombios_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
        atombios_lock_crtc(crtc, ATOM_DISABLE);
-       radeon_crtc->in_mode_set = false;
 }
 
 static void atombios_crtc_disable(struct drm_crtc *crtc)
index 44a7da6..8406c82 100644 (file)
@@ -667,6 +667,8 @@ atombios_digital_setup(struct drm_encoder *encoder, int action)
 int
 atombios_get_encoder_mode(struct drm_encoder *encoder)
 {
+       struct drm_device *dev = encoder->dev;
+       struct radeon_device *rdev = dev->dev_private;
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
        struct drm_connector *connector;
        struct radeon_connector *radeon_connector;
@@ -693,7 +695,8 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
        case DRM_MODE_CONNECTOR_DVII:
        case DRM_MODE_CONNECTOR_HDMIB: /* HDMI-B is basically DL-DVI; analog works fine */
                if (drm_detect_hdmi_monitor(radeon_connector->edid) &&
-                   radeon_audio)
+                   radeon_audio &&
+                   !ASIC_IS_DCE6(rdev)) /* remove once we support DCE6 */
                        return ATOM_ENCODER_MODE_HDMI;
                else if (radeon_connector->use_digital)
                        return ATOM_ENCODER_MODE_DVI;
@@ -704,7 +707,8 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
        case DRM_MODE_CONNECTOR_HDMIA:
        default:
                if (drm_detect_hdmi_monitor(radeon_connector->edid) &&
-                   radeon_audio)
+                   radeon_audio &&
+                   !ASIC_IS_DCE6(rdev)) /* remove once we support DCE6 */
                        return ATOM_ENCODER_MODE_HDMI;
                else
                        return ATOM_ENCODER_MODE_DVI;
@@ -718,7 +722,8 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
                    (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP))
                        return ATOM_ENCODER_MODE_DP;
                else if (drm_detect_hdmi_monitor(radeon_connector->edid) &&
-                        radeon_audio)
+                        radeon_audio &&
+                        !ASIC_IS_DCE6(rdev)) /* remove once we support DCE6 */
                        return ATOM_ENCODER_MODE_HDMI;
                else
                        return ATOM_ENCODER_MODE_DVI;
index 105bafb..0f89ce3 100644 (file)
@@ -2343,11 +2343,13 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav
        u32 crtc_enabled, tmp, frame_count, blackout;
        int i, j;
 
-       save->vga_render_control = RREG32(VGA_RENDER_CONTROL);
-       save->vga_hdp_control = RREG32(VGA_HDP_CONTROL);
+       if (!ASIC_IS_NODCE(rdev)) {
+               save->vga_render_control = RREG32(VGA_RENDER_CONTROL);
+               save->vga_hdp_control = RREG32(VGA_HDP_CONTROL);
 
-       /* disable VGA render */
-       WREG32(VGA_RENDER_CONTROL, 0);
+               /* disable VGA render */
+               WREG32(VGA_RENDER_CONTROL, 0);
+       }
        /* blank the display controllers */
        for (i = 0; i < rdev->num_crtc; i++) {
                crtc_enabled = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]) & EVERGREEN_CRTC_MASTER_EN;
@@ -2438,8 +2440,11 @@ void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *s
                WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + crtc_offsets[i],
                       (u32)rdev->mc.vram_start);
        }
-       WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS_HIGH, upper_32_bits(rdev->mc.vram_start));
-       WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS, (u32)rdev->mc.vram_start);
+
+       if (!ASIC_IS_NODCE(rdev)) {
+               WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS_HIGH, upper_32_bits(rdev->mc.vram_start));
+               WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS, (u32)rdev->mc.vram_start);
+       }
 
        /* unlock regs and wait for update */
        for (i = 0; i < rdev->num_crtc; i++) {
@@ -2499,10 +2504,12 @@ void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *s
                        }
                }
        }
-       /* Unlock vga access */
-       WREG32(VGA_HDP_CONTROL, save->vga_hdp_control);
-       mdelay(1);
-       WREG32(VGA_RENDER_CONTROL, save->vga_render_control);
+       if (!ASIC_IS_NODCE(rdev)) {
+               /* Unlock vga access */
+               WREG32(VGA_HDP_CONTROL, save->vga_hdp_control);
+               mdelay(1);
+               WREG32(VGA_RENDER_CONTROL, save->vga_render_control);
+       }
 }
 
 void evergreen_mc_program(struct radeon_device *rdev)
@@ -3405,8 +3412,8 @@ int evergreen_mc_init(struct radeon_device *rdev)
                rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE);
        } else {
                /* size in MB on evergreen/cayman/tn */
-               rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024;
-               rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024;
+               rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE) * 1024ULL * 1024ULL;
+               rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024ULL * 1024ULL;
        }
        rdev->mc.visible_vram_size = rdev->mc.aper_size;
        r700_vram_gtt_location(rdev, &rdev->mc);
@@ -4747,6 +4754,12 @@ static int evergreen_startup(struct radeon_device *rdev)
                rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
 
        /* Enable IRQ */
+       if (!rdev->irq.installed) {
+               r = radeon_irq_kms_init(rdev);
+               if (r)
+                       return r;
+       }
+
        r = r600_irq_init(rdev);
        if (r) {
                DRM_ERROR("radeon: IH init failed (%d).\n", r);
@@ -4916,10 +4929,6 @@ int evergreen_init(struct radeon_device *rdev)
        if (r)
                return r;
 
-       r = radeon_irq_kms_init(rdev);
-       if (r)
-               return r;
-
        rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ring_obj = NULL;
        r600_ring_init(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX], 1024 * 1024);
 
@@ -4992,8 +5001,7 @@ void evergreen_fini(struct radeon_device *rdev)
 
 void evergreen_pcie_gen2_enable(struct radeon_device *rdev)
 {
-       u32 link_width_cntl, speed_cntl, mask;
-       int ret;
+       u32 link_width_cntl, speed_cntl;
 
        if (radeon_pcie_gen2 == 0)
                return;
@@ -5008,11 +5016,8 @@ void evergreen_pcie_gen2_enable(struct radeon_device *rdev)
        if (ASIC_IS_X2(rdev))
                return;
 
-       ret = drm_pcie_get_speed_cap_mask(rdev->ddev, &mask);
-       if (ret != 0)
-               return;
-
-       if (!(mask & DRM_PCIE_SPEED_50))
+       if ((rdev->pdev->bus->max_bus_speed != PCIE_SPEED_5_0GT) &&
+               (rdev->pdev->bus->max_bus_speed != PCIE_SPEED_8_0GT))
                return;
 
        speed_cntl = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL);
index b4ab8ce..ed7c8a7 100644 (file)
@@ -154,19 +154,18 @@ static void evergreen_audio_set_dto(struct drm_encoder *encoder, u32 clock)
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
        struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
        struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
-       u32 base_rate = 48000;
+       u32 base_rate = 24000;
 
        if (!dig || !dig->afmt)
                return;
 
-       /* XXX: properly calculate this */
        /* XXX two dtos; generally use dto0 for hdmi */
        /* Express [24MHz / target pixel clock] as an exact rational
         * number (coefficient of two integer numbers.  DCCG_AUDIO_DTOx_PHASE
         * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator
         */
-       WREG32(DCCG_AUDIO_DTO0_PHASE, (base_rate*50) & 0xffffff);
-       WREG32(DCCG_AUDIO_DTO0_MODULE, (clock*100) & 0xffffff);
+       WREG32(DCCG_AUDIO_DTO0_PHASE, base_rate * 100);
+       WREG32(DCCG_AUDIO_DTO0_MODULE, clock * 100);
        WREG32(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO0_SOURCE_SEL(radeon_crtc->crtc_id));
 }
 
index 7969c0c..8458330 100644 (file)
@@ -2025,6 +2025,12 @@ static int cayman_startup(struct radeon_device *rdev)
        }
 
        /* Enable IRQ */
+       if (!rdev->irq.installed) {
+               r = radeon_irq_kms_init(rdev);
+               if (r)
+                       return r;
+       }
+
        r = r600_irq_init(rdev);
        if (r) {
                DRM_ERROR("radeon: IH init failed (%d).\n", r);
@@ -2190,10 +2196,6 @@ int cayman_init(struct radeon_device *rdev)
        if (r)
                return r;
 
-       r = radeon_irq_kms_init(rdev);
-       if (r)
-               return r;
-
        ring->ring_obj = NULL;
        r600_ring_init(rdev, ring, 1024 * 1024);
 
index 4973bff..d0314ec 100644 (file)
@@ -3869,6 +3869,12 @@ static int r100_startup(struct radeon_device *rdev)
        }
 
        /* Enable IRQ */
+       if (!rdev->irq.installed) {
+               r = radeon_irq_kms_init(rdev);
+               if (r)
+                       return r;
+       }
+
        r100_irq_set(rdev);
        rdev->config.r100.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
        /* 1M ring buffer */
@@ -4022,9 +4028,6 @@ int r100_init(struct radeon_device *rdev)
        r100_mc_init(rdev);
        /* Fence driver */
        r = radeon_fence_driver_init(rdev);
-       if (r)
-               return r;
-       r = radeon_irq_kms_init(rdev);
        if (r)
                return r;
        /* Memory manager */
index c60350e..b9b776f 100644 (file)
@@ -1382,6 +1382,12 @@ static int r300_startup(struct radeon_device *rdev)
        }
 
        /* Enable IRQ */
+       if (!rdev->irq.installed) {
+               r = radeon_irq_kms_init(rdev);
+               if (r)
+                       return r;
+       }
+
        r100_irq_set(rdev);
        rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
        /* 1M ring buffer */
@@ -1514,9 +1520,6 @@ int r300_init(struct radeon_device *rdev)
        r300_mc_init(rdev);
        /* Fence driver */
        r = radeon_fence_driver_init(rdev);
-       if (r)
-               return r;
-       r = radeon_irq_kms_init(rdev);
        if (r)
                return r;
        /* Memory manager */
index 865e2c9..60170ea 100644 (file)
@@ -75,7 +75,7 @@ static int r300_emit_cliprects(drm_radeon_private_t *dev_priv,
                OUT_RING(CP_PACKET0(R300_RE_CLIPRECT_TL_0, nr * 2 - 1));
 
                for (i = 0; i < nr; ++i) {
-                       if (DRM_COPY_FROM_USER_UNCHECKED
+                       if (DRM_COPY_FROM_USER
                            (&box, &cmdbuf->boxes[n + i], sizeof(box))) {
                                DRM_ERROR("copy cliprect faulted\n");
                                return -EFAULT;
index 6fce2eb..4e796ec 100644 (file)
@@ -265,6 +265,12 @@ static int r420_startup(struct radeon_device *rdev)
        }
 
        /* Enable IRQ */
+       if (!rdev->irq.installed) {
+               r = radeon_irq_kms_init(rdev);
+               if (r)
+                       return r;
+       }
+
        r100_irq_set(rdev);
        rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
        /* 1M ring buffer */
@@ -411,10 +417,6 @@ int r420_init(struct radeon_device *rdev)
        if (r) {
                return r;
        }
-       r = radeon_irq_kms_init(rdev);
-       if (r) {
-               return r;
-       }
        /* Memory manager */
        r = radeon_bo_init(rdev);
        if (r) {
index f795a4e..e1aece7 100644 (file)
@@ -194,6 +194,12 @@ static int r520_startup(struct radeon_device *rdev)
        }
 
        /* Enable IRQ */
+       if (!rdev->irq.installed) {
+               r = radeon_irq_kms_init(rdev);
+               if (r)
+                       return r;
+       }
+
        rs600_irq_set(rdev);
        rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
        /* 1M ring buffer */
@@ -295,9 +301,6 @@ int r520_init(struct radeon_device *rdev)
        rv515_debugfs(rdev);
        /* Fence driver */
        r = radeon_fence_driver_init(rdev);
-       if (r)
-               return r;
-       r = radeon_irq_kms_init(rdev);
        if (r)
                return r;
        /* Memory manager */
index 1a08008..0e53416 100644 (file)
@@ -1046,6 +1046,24 @@ int r600_mc_wait_for_idle(struct radeon_device *rdev)
        return -1;
 }
 
+uint32_t rs780_mc_rreg(struct radeon_device *rdev, uint32_t reg)
+{
+       uint32_t r;
+
+       WREG32(R_0028F8_MC_INDEX, S_0028F8_MC_IND_ADDR(reg));
+       r = RREG32(R_0028FC_MC_DATA);
+       WREG32(R_0028F8_MC_INDEX, ~C_0028F8_MC_IND_ADDR);
+       return r;
+}
+
+void rs780_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
+{
+       WREG32(R_0028F8_MC_INDEX, S_0028F8_MC_IND_ADDR(reg) |
+               S_0028F8_MC_IND_WR_EN(1));
+       WREG32(R_0028FC_MC_DATA, v);
+       WREG32(R_0028F8_MC_INDEX, 0x7F);
+}
+
 static void r600_mc_program(struct radeon_device *rdev)
 {
        struct rv515_mc_save save;
@@ -1181,6 +1199,8 @@ static int r600_mc_init(struct radeon_device *rdev)
 {
        u32 tmp;
        int chansize, numchan;
+       uint32_t h_addr, l_addr;
+       unsigned long long k8_addr;
 
        /* Get VRAM informations */
        rdev->mc.vram_is_ddr = true;
@@ -1221,7 +1241,30 @@ static int r600_mc_init(struct radeon_device *rdev)
        if (rdev->flags & RADEON_IS_IGP) {
                rs690_pm_info(rdev);
                rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev);
+
+               if (rdev->family == CHIP_RS780 || rdev->family == CHIP_RS880) {
+                       /* Use K8 direct mapping for fast fb access. */
+                       rdev->fastfb_working = false;
+                       h_addr = G_000012_K8_ADDR_EXT(RREG32_MC(R_000012_MC_MISC_UMA_CNTL));
+                       l_addr = RREG32_MC(R_000011_K8_FB_LOCATION);
+                       k8_addr = ((unsigned long long)h_addr) << 32 | l_addr;
+#if defined(CONFIG_X86_32) && !defined(CONFIG_X86_PAE)
+                       if (k8_addr + rdev->mc.visible_vram_size < 0x100000000ULL)
+#endif
+                       {
+                               /* FastFB shall be used with UMA memory. Here it is simply disabled when sideport
+                               * memory is present.
+                               */
+                               if (rdev->mc.igp_sideport_enabled == false && radeon_fastfb == 1) {
+                                       DRM_INFO("Direct mapping: aper base at 0x%llx, replaced by direct mapping base 0x%llx.\n",
+                                               (unsigned long long)rdev->mc.aper_base, k8_addr);
+                                       rdev->mc.aper_base = (resource_size_t)k8_addr;
+                                       rdev->fastfb_working = true;
+                               }
+                       }
+               }
        }
+
        radeon_update_bandwidth_info(rdev);
        return 0;
 }
@@ -3202,6 +3245,12 @@ static int r600_startup(struct radeon_device *rdev)
        }
 
        /* Enable IRQ */
+       if (!rdev->irq.installed) {
+               r = radeon_irq_kms_init(rdev);
+               if (r)
+                       return r;
+       }
+
        r = r600_irq_init(rdev);
        if (r) {
                DRM_ERROR("radeon: IH init failed (%d).\n", r);
@@ -3356,10 +3405,6 @@ int r600_init(struct radeon_device *rdev)
        if (r)
                return r;
 
-       r = radeon_irq_kms_init(rdev);
-       if (r)
-               return r;
-
        rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ring_obj = NULL;
        r600_ring_init(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX], 1024 * 1024);
 
@@ -4631,8 +4676,6 @@ static void r600_pcie_gen2_enable(struct radeon_device *rdev)
 {
        u32 link_width_cntl, lanes, speed_cntl, training_cntl, tmp;
        u16 link_cntl2;
-       u32 mask;
-       int ret;
 
        if (radeon_pcie_gen2 == 0)
                return;
@@ -4651,11 +4694,8 @@ static void r600_pcie_gen2_enable(struct radeon_device *rdev)
        if (rdev->family <= CHIP_R600)
                return;
 
-       ret = drm_pcie_get_speed_cap_mask(rdev->ddev, &mask);
-       if (ret != 0)
-               return;
-
-       if (!(mask & DRM_PCIE_SPEED_50))
+       if ((rdev->pdev->bus->max_bus_speed != PCIE_SPEED_5_0GT) &&
+               (rdev->pdev->bus->max_bus_speed != PCIE_SPEED_8_0GT))
                return;
 
        speed_cntl = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL);
index 47f180a..456750a 100644 (file)
@@ -232,7 +232,7 @@ void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock)
        struct radeon_device *rdev = dev->dev_private;
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
        struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-       u32 base_rate = 48000;
+       u32 base_rate = 24000;
 
        if (!dig || !dig->afmt)
                return;
@@ -240,7 +240,6 @@ void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock)
        /* there are two DTOs selected by DCCG_AUDIO_DTO_SELECT.
         * doesn't matter which one you use.  Just use the first one.
         */
-       /* XXX: properly calculate this */
        /* XXX two dtos; generally use dto0 for hdmi */
        /* Express [24MHz / target pixel clock] as an exact rational
         * number (coefficient of two integer numbers.  DCCG_AUDIO_DTOx_PHASE
@@ -250,13 +249,13 @@ void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock)
                /* according to the reg specs, this should DCE3.2 only, but in
                 * practice it seems to cover DCE3.0 as well.
                 */
-               WREG32(DCCG_AUDIO_DTO0_PHASE, base_rate * 50);
+               WREG32(DCCG_AUDIO_DTO0_PHASE, base_rate * 100);
                WREG32(DCCG_AUDIO_DTO0_MODULE, clock * 100);
                WREG32(DCCG_AUDIO_DTO_SELECT, 0); /* select DTO0 */
        } else {
                /* according to the reg specs, this should be DCE2.0 and DCE3.0 */
-               WREG32(AUDIO_DTO, AUDIO_DTO_PHASE(base_rate * 50) |
-                      AUDIO_DTO_MODULE(clock * 100));
+               WREG32(AUDIO_DTO, AUDIO_DTO_PHASE(base_rate / 10) |
+                      AUDIO_DTO_MODULE(clock / 10));
        }
 }
 
index acb146c..79df558 100644 (file)
 #define        PACKET3_STRMOUT_BASE_UPDATE                     0x72 /* r7xx */
 #define        PACKET3_SURFACE_BASE_UPDATE                     0x73
 
+#define R_000011_K8_FB_LOCATION                 0x11
+#define R_000012_MC_MISC_UMA_CNTL               0x12
+#define   G_000012_K8_ADDR_EXT(x)               (((x) >> 0) & 0xFF)
+#define R_0028F8_MC_INDEX                      0x28F8
+#define        S_0028F8_MC_IND_ADDR(x)                 (((x) & 0x1FF) << 0)
+#define        C_0028F8_MC_IND_ADDR                    0xFFFFFE00
+#define        S_0028F8_MC_IND_WR_EN(x)                (((x) & 0x1) << 9)
+#define R_0028FC_MC_DATA                        0x28FC
 
 #define        R_008020_GRBM_SOFT_RESET                0x8020
 #define                S_008020_SOFT_RESET_CP(x)               (((x) & 1) << 0)
index 1442ce7..142ce6c 100644 (file)
@@ -1694,6 +1694,7 @@ struct radeon_device {
        int num_crtc; /* number of crtcs */
        struct mutex dc_hw_i2c_mutex; /* display controller hw i2c mutex */
        bool audio_enabled;
+       bool has_uvd;
        struct r600_audio audio_status; /* audio stuff */
        struct notifier_block acpi_nb;
        /* only one userspace can use Hyperz features or CMASK at a time */
@@ -1838,6 +1839,7 @@ void r100_pll_errata_after_index(struct radeon_device *rdev);
 #define ASIC_IS_DCE61(rdev) ((rdev->family >= CHIP_ARUBA) && \
                             (rdev->flags & RADEON_IS_IGP))
 #define ASIC_IS_DCE64(rdev) ((rdev->family == CHIP_OLAND))
+#define ASIC_IS_NODCE(rdev) ((rdev->family == CHIP_HAINAN))
 
 /*
  * BIOS helpers.
index 6417132..a2802b4 100644 (file)
@@ -122,6 +122,10 @@ static void radeon_register_accessor_init(struct radeon_device *rdev)
                rdev->mc_rreg = &rs600_mc_rreg;
                rdev->mc_wreg = &rs600_mc_wreg;
        }
+       if (rdev->family == CHIP_RS780 || rdev->family == CHIP_RS880) {
+               rdev->mc_rreg = &rs780_mc_rreg;
+               rdev->mc_wreg = &rs780_mc_wreg;
+       }
        if (rdev->family >= CHIP_R600) {
                rdev->pciep_rreg = &r600_pciep_rreg;
                rdev->pciep_wreg = &r600_pciep_wreg;
@@ -1935,6 +1939,8 @@ int radeon_asic_init(struct radeon_device *rdev)
        else
                rdev->num_crtc = 2;
 
+       rdev->has_uvd = false;
+
        switch (rdev->family) {
        case CHIP_R100:
        case CHIP_RV100:
@@ -1999,16 +2005,22 @@ int radeon_asic_init(struct radeon_device *rdev)
        case CHIP_RV635:
        case CHIP_RV670:
                rdev->asic = &r600_asic;
+               if (rdev->family == CHIP_R600)
+                       rdev->has_uvd = false;
+               else
+                       rdev->has_uvd = true;
                break;
        case CHIP_RS780:
        case CHIP_RS880:
                rdev->asic = &rs780_asic;
+               rdev->has_uvd = true;
                break;
        case CHIP_RV770:
        case CHIP_RV730:
        case CHIP_RV710:
        case CHIP_RV740:
                rdev->asic = &rv770_asic;
+               rdev->has_uvd = true;
                break;
        case CHIP_CEDAR:
        case CHIP_REDWOOD:
@@ -2021,11 +2033,13 @@ int radeon_asic_init(struct radeon_device *rdev)
                else
                        rdev->num_crtc = 6;
                rdev->asic = &evergreen_asic;
+               rdev->has_uvd = true;
                break;
        case CHIP_PALM:
        case CHIP_SUMO:
        case CHIP_SUMO2:
                rdev->asic = &sumo_asic;
+               rdev->has_uvd = true;
                break;
        case CHIP_BARTS:
        case CHIP_TURKS:
@@ -2036,27 +2050,37 @@ int radeon_asic_init(struct radeon_device *rdev)
                else
                        rdev->num_crtc = 6;
                rdev->asic = &btc_asic;
+               rdev->has_uvd = true;
                break;
        case CHIP_CAYMAN:
                rdev->asic = &cayman_asic;
                /* set num crtcs */
                rdev->num_crtc = 6;
+               rdev->has_uvd = true;
                break;
        case CHIP_ARUBA:
                rdev->asic = &trinity_asic;
                /* set num crtcs */
                rdev->num_crtc = 4;
+               rdev->has_uvd = true;
                break;
        case CHIP_TAHITI:
        case CHIP_PITCAIRN:
        case CHIP_VERDE:
        case CHIP_OLAND:
+       case CHIP_HAINAN:
                rdev->asic = &si_asic;
                /* set num crtcs */
-               if (rdev->family == CHIP_OLAND)
+               if (rdev->family == CHIP_HAINAN)
+                       rdev->num_crtc = 0;
+               else if (rdev->family == CHIP_OLAND)
                        rdev->num_crtc = 2;
                else
                        rdev->num_crtc = 6;
+               if (rdev->family == CHIP_HAINAN)
+                       rdev->has_uvd = false;
+               else
+                       rdev->has_uvd = true;
                break;
        default:
                /* FIXME: not supported yet */
index 2c87365..a72759e 100644 (file)
@@ -347,6 +347,8 @@ extern bool r600_gui_idle(struct radeon_device *rdev);
 extern void r600_pm_misc(struct radeon_device *rdev);
 extern void r600_pm_init_profile(struct radeon_device *rdev);
 extern void rs780_pm_init_profile(struct radeon_device *rdev);
+extern uint32_t rs780_mc_rreg(struct radeon_device *rdev, uint32_t reg);
+extern void rs780_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
 extern void r600_pm_get_dynpm_state(struct radeon_device *rdev);
 extern void r600_set_pcie_lanes(struct radeon_device *rdev, int lanes);
 extern int r600_get_pcie_lanes(struct radeon_device *rdev);
index fa3c56f..061b227 100644 (file)
@@ -244,24 +244,28 @@ static bool ni_read_disabled_bios(struct radeon_device *rdev)
 
        /* enable the rom */
        WREG32(R600_BUS_CNTL, (bus_cntl & ~R600_BIOS_ROM_DIS));
-       /* Disable VGA mode */
-       WREG32(AVIVO_D1VGA_CONTROL,
-              (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE |
-               AVIVO_DVGA_CONTROL_TIMING_SELECT)));
-       WREG32(AVIVO_D2VGA_CONTROL,
-              (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE |
-               AVIVO_DVGA_CONTROL_TIMING_SELECT)));
-       WREG32(AVIVO_VGA_RENDER_CONTROL,
-              (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK));
+       if (!ASIC_IS_NODCE(rdev)) {
+               /* Disable VGA mode */
+               WREG32(AVIVO_D1VGA_CONTROL,
+                      (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE |
+                                         AVIVO_DVGA_CONTROL_TIMING_SELECT)));
+               WREG32(AVIVO_D2VGA_CONTROL,
+                      (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE |
+                                         AVIVO_DVGA_CONTROL_TIMING_SELECT)));
+               WREG32(AVIVO_VGA_RENDER_CONTROL,
+                      (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK));
+       }
        WREG32(R600_ROM_CNTL, rom_cntl | R600_SCK_OVERWRITE);
 
        r = radeon_read_bios(rdev);
 
        /* restore regs */
        WREG32(R600_BUS_CNTL, bus_cntl);
-       WREG32(AVIVO_D1VGA_CONTROL, d1vga_control);
-       WREG32(AVIVO_D2VGA_CONTROL, d2vga_control);
-       WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control);
+       if (!ASIC_IS_NODCE(rdev)) {
+               WREG32(AVIVO_D1VGA_CONTROL, d1vga_control);
+               WREG32(AVIVO_D2VGA_CONTROL, d2vga_control);
+               WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control);
+       }
        WREG32(R600_ROM_CNTL, rom_cntl);
        return r;
 }
index a8f6089..1899738 100644 (file)
@@ -94,6 +94,7 @@ static const char radeon_family_name[][16] = {
        "PITCAIRN",
        "VERDE",
        "OLAND",
+       "HAINAN",
        "LAST",
 };
 
@@ -466,23 +467,27 @@ bool radeon_card_posted(struct radeon_device *rdev)
 {
        uint32_t reg;
 
+       /* required for EFI mode on macbook2,1 which uses an r5xx asic */
        if (efi_enabled(EFI_BOOT) &&
-           rdev->pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE)
+           (rdev->pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE) &&
+           (rdev->family < CHIP_R600))
                return false;
 
+       if (ASIC_IS_NODCE(rdev))
+               goto check_memsize;
+
        /* first check CRTCs */
-       if (ASIC_IS_DCE41(rdev)) {
+       if (ASIC_IS_DCE4(rdev)) {
                reg = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET) |
                        RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET);
-               if (reg & EVERGREEN_CRTC_MASTER_EN)
-                       return true;
-       } else if (ASIC_IS_DCE4(rdev)) {
-               reg = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET) |
-                       RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET) |
-                       RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET) |
-                       RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET) |
-                       RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET) |
-                       RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET);
+                       if (rdev->num_crtc >= 4) {
+                               reg |= RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET) |
+                                       RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET);
+                       }
+                       if (rdev->num_crtc >= 6) {
+                               reg |= RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET) |
+                                       RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET);
+                       }
                if (reg & EVERGREEN_CRTC_MASTER_EN)
                        return true;
        } else if (ASIC_IS_AVIVO(rdev)) {
@@ -499,6 +504,7 @@ bool radeon_card_posted(struct radeon_device *rdev)
                }
        }
 
+check_memsize:
        /* then check MEM_SIZE, in case the crtcs are off */
        if (rdev->family >= CHIP_R600)
                reg = RREG32(R600_CONFIG_MEMSIZE);
index e38fd55..eb18bb7 100644 (file)
@@ -271,8 +271,6 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id)
 {
        struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
        struct radeon_unpin_work *work;
-       struct drm_pending_vblank_event *e;
-       struct timeval now;
        unsigned long flags;
        u32 update_pending;
        int vpos, hpos;
@@ -328,14 +326,9 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id)
        radeon_crtc->unpin_work = NULL;
 
        /* wakeup userspace */
-       if (work->event) {
-               e = work->event;
-               e->event.sequence = drm_vblank_count_and_time(rdev->ddev, crtc_id, &now);
-               e->event.tv_sec = now.tv_sec;
-               e->event.tv_usec = now.tv_usec;
-               list_add_tail(&e->base.link, &e->base.file_priv->event_list);
-               wake_up_interruptible(&e->base.file_priv->event_wait);
-       }
+       if (work->event)
+               drm_send_vblank_event(rdev->ddev, crtc_id, work->event);
+
        spin_unlock_irqrestore(&rdev->ddev->event_lock, flags);
 
        drm_vblank_put(rdev->ddev, radeon_crtc->crtc_id);
index d33f484..094e7e5 100644 (file)
@@ -147,7 +147,7 @@ static inline void radeon_unregister_atpx_handler(void) {}
 #endif
 
 int radeon_no_wb;
-int radeon_modeset = 1;
+int radeon_modeset = -1;
 int radeon_dynclks = -1;
 int radeon_r4xx_atom = 0;
 int radeon_agpmode = 0;
@@ -456,6 +456,16 @@ static struct pci_driver radeon_kms_pci_driver = {
 
 static int __init radeon_init(void)
 {
+#ifdef CONFIG_VGA_CONSOLE
+       if (vgacon_text_force() && radeon_modeset == -1) {
+               DRM_INFO("VGACON disable radeon kernel modesetting.\n");
+               radeon_modeset = 0;
+       }
+#endif
+       /* set to modesetting by default if not nomodeset */
+       if (radeon_modeset == -1)
+               radeon_modeset = 1;
+
        if (radeon_modeset == 1) {
                DRM_INFO("radeon kernel modesetting enabled.\n");
                driver = &kms_driver;
index 2d91123..36e9803 100644 (file)
@@ -92,6 +92,7 @@ enum radeon_family {
        CHIP_PITCAIRN,
        CHIP_VERDE,
        CHIP_OLAND,
+       CHIP_HAINAN,
        CHIP_LAST,
 };
 
index 6857cb4..7cb178a 100644 (file)
@@ -1031,11 +1031,9 @@ static int radeon_crtc_mode_set(struct drm_crtc *crtc,
 
 static void radeon_crtc_prepare(struct drm_crtc *crtc)
 {
-       struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
        struct drm_device *dev = crtc->dev;
        struct drm_crtc *crtci;
 
-       radeon_crtc->in_mode_set = true;
        /*
        * The hardware wedges sometimes if you reconfigure one CRTC
        * whilst another is running (see fdo bug #24611).
@@ -1046,7 +1044,6 @@ static void radeon_crtc_prepare(struct drm_crtc *crtc)
 
 static void radeon_crtc_commit(struct drm_crtc *crtc)
 {
-       struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
        struct drm_device *dev = crtc->dev;
        struct drm_crtc *crtci;
 
@@ -1057,7 +1054,6 @@ static void radeon_crtc_commit(struct drm_crtc *crtc)
                if (crtci->enabled)
                        radeon_crtc_dpms(crtci, DRM_MODE_DPMS_ON);
        }
-       radeon_crtc->in_mode_set = false;
 }
 
 static const struct drm_crtc_helper_funcs legacy_helper_funcs = {
index 44e579e..69ad4fe 100644 (file)
@@ -302,7 +302,6 @@ struct radeon_crtc {
        u16 lut_r[256], lut_g[256], lut_b[256];
        bool enabled;
        bool can_tile;
-       bool in_mode_set;
        uint32_t crtc_offset;
        struct drm_gem_object *cursor_bo;
        uint64_t cursor_addr;
index 93f760e..6c0ce89 100644 (file)
@@ -726,7 +726,7 @@ int radeon_ttm_init(struct radeon_device *rdev)
                return r;
        }
        DRM_INFO("radeon: %uM of VRAM memory ready\n",
-                (unsigned)rdev->mc.real_vram_size / (1024 * 1024));
+                (unsigned) (rdev->mc.real_vram_size / (1024 * 1024)));
        r = ttm_bo_init_mm(&rdev->mman.bdev, TTM_PL_TT,
                                rdev->mc.gtt_size >> PAGE_SHIFT);
        if (r) {
index 73051ce..233a9b9 100644 (file)
@@ -417,6 +417,12 @@ static int rs400_startup(struct radeon_device *rdev)
        }
 
        /* Enable IRQ */
+       if (!rdev->irq.installed) {
+               r = radeon_irq_kms_init(rdev);
+               if (r)
+                       return r;
+       }
+
        r100_irq_set(rdev);
        rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
        /* 1M ring buffer */
@@ -533,9 +539,6 @@ int rs400_init(struct radeon_device *rdev)
        rs400_mc_init(rdev);
        /* Fence driver */
        r = radeon_fence_driver_init(rdev);
-       if (r)
-               return r;
-       r = radeon_irq_kms_init(rdev);
        if (r)
                return r;
        /* Memory manager */
index 46fa1b0..670b555 100644 (file)
@@ -923,6 +923,12 @@ static int rs600_startup(struct radeon_device *rdev)
        }
 
        /* Enable IRQ */
+       if (!rdev->irq.installed) {
+               r = radeon_irq_kms_init(rdev);
+               if (r)
+                       return r;
+       }
+
        rs600_irq_set(rdev);
        rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
        /* 1M ring buffer */
@@ -1045,9 +1051,6 @@ int rs600_init(struct radeon_device *rdev)
        rs600_debugfs(rdev);
        /* Fence driver */
        r = radeon_fence_driver_init(rdev);
-       if (r)
-               return r;
-       r = radeon_irq_kms_init(rdev);
        if (r)
                return r;
        /* Memory manager */
index ab4c86c..55880d5 100644 (file)
@@ -651,6 +651,12 @@ static int rs690_startup(struct radeon_device *rdev)
        }
 
        /* Enable IRQ */
+       if (!rdev->irq.installed) {
+               r = radeon_irq_kms_init(rdev);
+               if (r)
+                       return r;
+       }
+
        rs600_irq_set(rdev);
        rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
        /* 1M ring buffer */
@@ -774,9 +780,6 @@ int rs690_init(struct radeon_device *rdev)
        rv515_debugfs(rdev);
        /* Fence driver */
        r = radeon_fence_driver_init(rdev);
-       if (r)
-               return r;
-       r = radeon_irq_kms_init(rdev);
        if (r)
                return r;
        /* Memory manager */
index ffcba73..21c7d7b 100644 (file)
@@ -532,6 +532,12 @@ static int rv515_startup(struct radeon_device *rdev)
        }
 
        /* Enable IRQ */
+       if (!rdev->irq.installed) {
+               r = radeon_irq_kms_init(rdev);
+               if (r)
+                       return r;
+       }
+
        rs600_irq_set(rdev);
        rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
        /* 1M ring buffer */
@@ -660,9 +666,6 @@ int rv515_init(struct radeon_device *rdev)
        rv515_debugfs(rdev);
        /* Fence driver */
        r = radeon_fence_driver_init(rdev);
-       if (r)
-               return r;
-       r = radeon_irq_kms_init(rdev);
        if (r)
                return r;
        /* Memory manager */
index 83f612a..4a62ad2 100644 (file)
@@ -862,10 +862,8 @@ int rv770_uvd_resume(struct radeon_device *rdev)
                chip_id = 0x0100000b;
                break;
        case CHIP_SUMO:
-               chip_id = 0x0100000c;
-               break;
        case CHIP_SUMO2:
-               chip_id = 0x0100000d;
+               chip_id = 0x0100000c;
                break;
        case CHIP_PALM:
                chip_id = 0x0100000e;
@@ -1889,6 +1887,12 @@ static int rv770_startup(struct radeon_device *rdev)
                rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
 
        /* Enable IRQ */
+       if (!rdev->irq.installed) {
+               r = radeon_irq_kms_init(rdev);
+               if (r)
+                       return r;
+       }
+
        r = r600_irq_init(rdev);
        if (r) {
                DRM_ERROR("radeon: IH init failed (%d).\n", r);
@@ -2047,10 +2051,6 @@ int rv770_init(struct radeon_device *rdev)
        if (r)
                return r;
 
-       r = radeon_irq_kms_init(rdev);
-       if (r)
-               return r;
-
        rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ring_obj = NULL;
        r600_ring_init(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX], 1024 * 1024);
 
@@ -2113,8 +2113,6 @@ static void rv770_pcie_gen2_enable(struct radeon_device *rdev)
 {
        u32 link_width_cntl, lanes, speed_cntl, tmp;
        u16 link_cntl2;
-       u32 mask;
-       int ret;
 
        if (radeon_pcie_gen2 == 0)
                return;
@@ -2129,11 +2127,8 @@ static void rv770_pcie_gen2_enable(struct radeon_device *rdev)
        if (ASIC_IS_X2(rdev))
                return;
 
-       ret = drm_pcie_get_speed_cap_mask(rdev->ddev, &mask);
-       if (ret != 0)
-               return;
-
-       if (!(mask & DRM_PCIE_SPEED_50))
+       if ((rdev->pdev->bus->max_bus_speed != PCIE_SPEED_5_0GT) &&
+               (rdev->pdev->bus->max_bus_speed != PCIE_SPEED_8_0GT))
                return;
 
        DRM_INFO("enabling PCIE gen 2 link speeds, disable with radeon.pcie_gen2=0\n");
index f0b6c2f..a1b0da6 100644 (file)
@@ -60,6 +60,11 @@ MODULE_FIRMWARE("radeon/OLAND_me.bin");
 MODULE_FIRMWARE("radeon/OLAND_ce.bin");
 MODULE_FIRMWARE("radeon/OLAND_mc.bin");
 MODULE_FIRMWARE("radeon/OLAND_rlc.bin");
+MODULE_FIRMWARE("radeon/HAINAN_pfp.bin");
+MODULE_FIRMWARE("radeon/HAINAN_me.bin");
+MODULE_FIRMWARE("radeon/HAINAN_ce.bin");
+MODULE_FIRMWARE("radeon/HAINAN_mc.bin");
+MODULE_FIRMWARE("radeon/HAINAN_rlc.bin");
 
 extern int r600_ih_ring_alloc(struct radeon_device *rdev);
 extern void r600_ih_ring_fini(struct radeon_device *rdev);
@@ -265,6 +270,40 @@ static const u32 oland_golden_registers[] =
        0x15c0, 0x000c0fc0, 0x000c0400
 };
 
+static const u32 hainan_golden_registers[] =
+{
+       0x9a10, 0x00010000, 0x00018208,
+       0x9830, 0xffffffff, 0x00000000,
+       0x9834, 0xf00fffff, 0x00000400,
+       0x9838, 0x0002021c, 0x00020200,
+       0xd0c0, 0xff000fff, 0x00000100,
+       0xd030, 0x000300c0, 0x00800040,
+       0xd8c0, 0xff000fff, 0x00000100,
+       0xd830, 0x000300c0, 0x00800040,
+       0x2ae4, 0x00073ffe, 0x000022a2,
+       0x240c, 0x000007ff, 0x00000000,
+       0x8a14, 0xf000001f, 0x00000007,
+       0x8b24, 0xffffffff, 0x00ffffff,
+       0x8b10, 0x0000ff0f, 0x00000000,
+       0x28a4c, 0x07ffffff, 0x4e000000,
+       0x28350, 0x3f3f3fff, 0x00000000,
+       0x30, 0x000000ff, 0x0040,
+       0x34, 0x00000040, 0x00004040,
+       0x9100, 0x03e00000, 0x03600000,
+       0x9060, 0x0000007f, 0x00000020,
+       0x9508, 0x00010000, 0x00010000,
+       0xac14, 0x000003ff, 0x000000f1,
+       0xac10, 0xffffffff, 0x00000000,
+       0xac0c, 0xffffffff, 0x00003210,
+       0x88d4, 0x0000001f, 0x00000010,
+       0x15c0, 0x000c0fc0, 0x000c0400
+};
+
+static const u32 hainan_golden_registers2[] =
+{
+       0x98f8, 0xffffffff, 0x02010001
+};
+
 static const u32 tahiti_mgcg_cgcg_init[] =
 {
        0xc400, 0xffffffff, 0xfffffffc,
@@ -673,6 +712,83 @@ static const u32 oland_mgcg_cgcg_init[] =
        0xd8c0, 0xfffffff0, 0x00000100
 };
 
+static const u32 hainan_mgcg_cgcg_init[] =
+{
+       0xc400, 0xffffffff, 0xfffffffc,
+       0x802c, 0xffffffff, 0xe0000000,
+       0x9a60, 0xffffffff, 0x00000100,
+       0x92a4, 0xffffffff, 0x00000100,
+       0xc164, 0xffffffff, 0x00000100,
+       0x9774, 0xffffffff, 0x00000100,
+       0x8984, 0xffffffff, 0x06000100,
+       0x8a18, 0xffffffff, 0x00000100,
+       0x92a0, 0xffffffff, 0x00000100,
+       0xc380, 0xffffffff, 0x00000100,
+       0x8b28, 0xffffffff, 0x00000100,
+       0x9144, 0xffffffff, 0x00000100,
+       0x8d88, 0xffffffff, 0x00000100,
+       0x8d8c, 0xffffffff, 0x00000100,
+       0x9030, 0xffffffff, 0x00000100,
+       0x9034, 0xffffffff, 0x00000100,
+       0x9038, 0xffffffff, 0x00000100,
+       0x903c, 0xffffffff, 0x00000100,
+       0xad80, 0xffffffff, 0x00000100,
+       0xac54, 0xffffffff, 0x00000100,
+       0x897c, 0xffffffff, 0x06000100,
+       0x9868, 0xffffffff, 0x00000100,
+       0x9510, 0xffffffff, 0x00000100,
+       0xaf04, 0xffffffff, 0x00000100,
+       0xae04, 0xffffffff, 0x00000100,
+       0x949c, 0xffffffff, 0x00000100,
+       0x802c, 0xffffffff, 0xe0000000,
+       0x9160, 0xffffffff, 0x00010000,
+       0x9164, 0xffffffff, 0x00030002,
+       0x9168, 0xffffffff, 0x00040007,
+       0x916c, 0xffffffff, 0x00060005,
+       0x9170, 0xffffffff, 0x00090008,
+       0x9174, 0xffffffff, 0x00020001,
+       0x9178, 0xffffffff, 0x00040003,
+       0x917c, 0xffffffff, 0x00000007,
+       0x9180, 0xffffffff, 0x00060005,
+       0x9184, 0xffffffff, 0x00090008,
+       0x9188, 0xffffffff, 0x00030002,
+       0x918c, 0xffffffff, 0x00050004,
+       0x9190, 0xffffffff, 0x00000008,
+       0x9194, 0xffffffff, 0x00070006,
+       0x9198, 0xffffffff, 0x000a0009,
+       0x919c, 0xffffffff, 0x00040003,
+       0x91a0, 0xffffffff, 0x00060005,
+       0x91a4, 0xffffffff, 0x00000009,
+       0x91a8, 0xffffffff, 0x00080007,
+       0x91ac, 0xffffffff, 0x000b000a,
+       0x91b0, 0xffffffff, 0x00050004,
+       0x91b4, 0xffffffff, 0x00070006,
+       0x91b8, 0xffffffff, 0x0008000b,
+       0x91bc, 0xffffffff, 0x000a0009,
+       0x91c0, 0xffffffff, 0x000d000c,
+       0x91c4, 0xffffffff, 0x00060005,
+       0x91c8, 0xffffffff, 0x00080007,
+       0x91cc, 0xffffffff, 0x0000000b,
+       0x91d0, 0xffffffff, 0x000a0009,
+       0x91d4, 0xffffffff, 0x000d000c,
+       0x9150, 0xffffffff, 0x96940200,
+       0x8708, 0xffffffff, 0x00900100,
+       0xc478, 0xffffffff, 0x00000080,
+       0xc404, 0xffffffff, 0x0020003f,
+       0x30, 0xffffffff, 0x0000001c,
+       0x34, 0x000f0000, 0x000f0000,
+       0x160c, 0xffffffff, 0x00000100,
+       0x1024, 0xffffffff, 0x00000100,
+       0x20a8, 0xffffffff, 0x00000104,
+       0x264c, 0x000c0000, 0x000c0000,
+       0x2648, 0x000c0000, 0x000c0000,
+       0x2f50, 0x00000001, 0x00000001,
+       0x30cc, 0xc0000fff, 0x00000104,
+       0xc1e4, 0x00000001, 0x00000001,
+       0xd0c0, 0xfffffff0, 0x00000100,
+       0xd8c0, 0xfffffff0, 0x00000100
+};
+
 static u32 verde_pg_init[] =
 {
        0x353c, 0xffffffff, 0x40000,
@@ -853,6 +969,17 @@ static void si_init_golden_registers(struct radeon_device *rdev)
                                                 oland_mgcg_cgcg_init,
                                                 (const u32)ARRAY_SIZE(oland_mgcg_cgcg_init));
                break;
+       case CHIP_HAINAN:
+               radeon_program_register_sequence(rdev,
+                                                hainan_golden_registers,
+                                                (const u32)ARRAY_SIZE(hainan_golden_registers));
+               radeon_program_register_sequence(rdev,
+                                                hainan_golden_registers2,
+                                                (const u32)ARRAY_SIZE(hainan_golden_registers2));
+               radeon_program_register_sequence(rdev,
+                                                hainan_mgcg_cgcg_init,
+                                                (const u32)ARRAY_SIZE(hainan_mgcg_cgcg_init));
+               break;
        default:
                break;
        }
@@ -1062,6 +1189,45 @@ static const u32 oland_io_mc_regs[TAHITI_IO_MC_REGS_SIZE][2] = {
        {0x0000009f, 0x00a17730}
 };
 
+static const u32 hainan_io_mc_regs[TAHITI_IO_MC_REGS_SIZE][2] = {
+       {0x0000006f, 0x03044000},
+       {0x00000070, 0x0480c018},
+       {0x00000071, 0x00000040},
+       {0x00000072, 0x01000000},
+       {0x00000074, 0x000000ff},
+       {0x00000075, 0x00143400},
+       {0x00000076, 0x08ec0800},
+       {0x00000077, 0x040000cc},
+       {0x00000079, 0x00000000},
+       {0x0000007a, 0x21000409},
+       {0x0000007c, 0x00000000},
+       {0x0000007d, 0xe8000000},
+       {0x0000007e, 0x044408a8},
+       {0x0000007f, 0x00000003},
+       {0x00000080, 0x00000000},
+       {0x00000081, 0x01000000},
+       {0x00000082, 0x02000000},
+       {0x00000083, 0x00000000},
+       {0x00000084, 0xe3f3e4f4},
+       {0x00000085, 0x00052024},
+       {0x00000087, 0x00000000},
+       {0x00000088, 0x66036603},
+       {0x00000089, 0x01000000},
+       {0x0000008b, 0x1c0a0000},
+       {0x0000008c, 0xff010000},
+       {0x0000008e, 0xffffefff},
+       {0x0000008f, 0xfff3efff},
+       {0x00000090, 0xfff3efbf},
+       {0x00000094, 0x00101101},
+       {0x00000095, 0x00000fff},
+       {0x00000096, 0x00116fff},
+       {0x00000097, 0x60010000},
+       {0x00000098, 0x10010000},
+       {0x00000099, 0x00006000},
+       {0x0000009a, 0x00001000},
+       {0x0000009f, 0x00a07730}
+};
+
 /* ucode loading */
 static int si_mc_load_microcode(struct radeon_device *rdev)
 {
@@ -1095,6 +1261,11 @@ static int si_mc_load_microcode(struct radeon_device *rdev)
                ucode_size = OLAND_MC_UCODE_SIZE;
                regs_size = TAHITI_IO_MC_REGS_SIZE;
                break;
+       case CHIP_HAINAN:
+               io_mc_regs = (u32 *)&hainan_io_mc_regs;
+               ucode_size = OLAND_MC_UCODE_SIZE;
+               regs_size = TAHITI_IO_MC_REGS_SIZE;
+               break;
        }
 
        running = RREG32(MC_SEQ_SUP_CNTL) & RUN_MASK;
@@ -1198,6 +1369,15 @@ static int si_init_microcode(struct radeon_device *rdev)
                rlc_req_size = SI_RLC_UCODE_SIZE * 4;
                mc_req_size = OLAND_MC_UCODE_SIZE * 4;
                break;
+       case CHIP_HAINAN:
+               chip_name = "HAINAN";
+               rlc_chip_name = "HAINAN";
+               pfp_req_size = SI_PFP_UCODE_SIZE * 4;
+               me_req_size = SI_PM4_UCODE_SIZE * 4;
+               ce_req_size = SI_CE_UCODE_SIZE * 4;
+               rlc_req_size = SI_RLC_UCODE_SIZE * 4;
+               mc_req_size = OLAND_MC_UCODE_SIZE * 4;
+               break;
        default: BUG();
        }
 
@@ -2003,7 +2183,8 @@ static void si_tiling_mode_table_init(struct radeon_device *rdev)
                        WREG32(GB_TILE_MODE0 + (reg_offset * 4), gb_tile_moden);
                }
        } else if ((rdev->family == CHIP_VERDE) ||
-                  (rdev->family == CHIP_OLAND)) {
+                  (rdev->family == CHIP_OLAND) ||
+                  (rdev->family == CHIP_HAINAN)) {
                for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++) {
                        switch (reg_offset) {
                        case 0:  /* non-AA compressed depth or any compressed stencil */
@@ -2435,7 +2616,7 @@ static void si_gpu_init(struct radeon_device *rdev)
        default:
                rdev->config.si.max_shader_engines = 1;
                rdev->config.si.max_tile_pipes = 4;
-               rdev->config.si.max_cu_per_sh = 2;
+               rdev->config.si.max_cu_per_sh = 5;
                rdev->config.si.max_sh_per_se = 2;
                rdev->config.si.max_backends_per_se = 4;
                rdev->config.si.max_texture_channel_caches = 4;
@@ -2466,6 +2647,23 @@ static void si_gpu_init(struct radeon_device *rdev)
                rdev->config.si.sc_earlyz_tile_fifo_size = 0x130;
                gb_addr_config = VERDE_GB_ADDR_CONFIG_GOLDEN;
                break;
+       case CHIP_HAINAN:
+               rdev->config.si.max_shader_engines = 1;
+               rdev->config.si.max_tile_pipes = 4;
+               rdev->config.si.max_cu_per_sh = 5;
+               rdev->config.si.max_sh_per_se = 1;
+               rdev->config.si.max_backends_per_se = 1;
+               rdev->config.si.max_texture_channel_caches = 2;
+               rdev->config.si.max_gprs = 256;
+               rdev->config.si.max_gs_threads = 16;
+               rdev->config.si.max_hw_contexts = 8;
+
+               rdev->config.si.sc_prim_fifo_size_frontend = 0x20;
+               rdev->config.si.sc_prim_fifo_size_backend = 0x40;
+               rdev->config.si.sc_hiz_tile_fifo_size = 0x30;
+               rdev->config.si.sc_earlyz_tile_fifo_size = 0x130;
+               gb_addr_config = HAINAN_GB_ADDR_CONFIG_GOLDEN;
+               break;
        }
 
        /* Initialize HDP */
@@ -2559,9 +2757,11 @@ static void si_gpu_init(struct radeon_device *rdev)
        WREG32(HDP_ADDR_CONFIG, gb_addr_config);
        WREG32(DMA_TILING_CONFIG + DMA0_REGISTER_OFFSET, gb_addr_config);
        WREG32(DMA_TILING_CONFIG + DMA1_REGISTER_OFFSET, gb_addr_config);
-       WREG32(UVD_UDEC_ADDR_CONFIG, gb_addr_config);
-       WREG32(UVD_UDEC_DB_ADDR_CONFIG, gb_addr_config);
-       WREG32(UVD_UDEC_DBW_ADDR_CONFIG, gb_addr_config);
+       if (rdev->has_uvd) {
+               WREG32(UVD_UDEC_ADDR_CONFIG, gb_addr_config);
+               WREG32(UVD_UDEC_DB_ADDR_CONFIG, gb_addr_config);
+               WREG32(UVD_UDEC_DBW_ADDR_CONFIG, gb_addr_config);
+       }
 
        si_tiling_mode_table_init(rdev);
 
@@ -3304,8 +3504,9 @@ static void si_mc_program(struct radeon_device *rdev)
        if (radeon_mc_wait_for_idle(rdev)) {
                dev_warn(rdev->dev, "Wait for MC idle timedout !\n");
        }
-       /* Lockout access through VGA aperture*/
-       WREG32(VGA_HDP_CONTROL, VGA_MEMORY_DISABLE);
+       if (!ASIC_IS_NODCE(rdev))
+               /* Lockout access through VGA aperture*/
+               WREG32(VGA_HDP_CONTROL, VGA_MEMORY_DISABLE);
        /* Update configuration */
        WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR,
               rdev->mc.vram_start >> 12);
@@ -3327,9 +3528,11 @@ static void si_mc_program(struct radeon_device *rdev)
                dev_warn(rdev->dev, "Wait for MC idle timedout !\n");
        }
        evergreen_mc_resume(rdev, &save);
-       /* we need to own VRAM, so turn off the VGA renderer here
-        * to stop it overwriting our objects */
-       rv515_vga_render_disable(rdev);
+       if (!ASIC_IS_NODCE(rdev)) {
+               /* we need to own VRAM, so turn off the VGA renderer here
+                * to stop it overwriting our objects */
+               rv515_vga_render_disable(rdev);
+       }
 }
 
 static void si_vram_gtt_location(struct radeon_device *rdev,
@@ -3397,8 +3600,8 @@ static int si_mc_init(struct radeon_device *rdev)
        rdev->mc.aper_base = pci_resource_start(rdev->pdev, 0);
        rdev->mc.aper_size = pci_resource_len(rdev->pdev, 0);
        /* size in MB on si */
-       rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024;
-       rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024;
+       rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE) * 1024ULL * 1024ULL;
+       rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024ULL * 1024ULL;
        rdev->mc.visible_vram_size = rdev->mc.aper_size;
        si_vram_gtt_location(rdev, &rdev->mc);
        radeon_update_bandwidth_info(rdev);
@@ -4251,8 +4454,10 @@ static void si_disable_interrupt_state(struct radeon_device *rdev)
        tmp = RREG32(DMA_CNTL + DMA1_REGISTER_OFFSET) & ~TRAP_ENABLE;
        WREG32(DMA_CNTL + DMA1_REGISTER_OFFSET, tmp);
        WREG32(GRBM_INT_CNTL, 0);
-       WREG32(INT_MASK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0);
-       WREG32(INT_MASK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0);
+       if (rdev->num_crtc >= 2) {
+               WREG32(INT_MASK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0);
+               WREG32(INT_MASK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0);
+       }
        if (rdev->num_crtc >= 4) {
                WREG32(INT_MASK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0);
                WREG32(INT_MASK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0);
@@ -4262,8 +4467,10 @@ static void si_disable_interrupt_state(struct radeon_device *rdev)
                WREG32(INT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0);
        }
 
-       WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, 0);
-       WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, 0);
+       if (rdev->num_crtc >= 2) {
+               WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, 0);
+               WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, 0);
+       }
        if (rdev->num_crtc >= 4) {
                WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, 0);
                WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, 0);
@@ -4273,21 +4480,22 @@ static void si_disable_interrupt_state(struct radeon_device *rdev)
                WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, 0);
        }
 
-       WREG32(DACA_AUTODETECT_INT_CONTROL, 0);
-
-       tmp = RREG32(DC_HPD1_INT_CONTROL) & DC_HPDx_INT_POLARITY;
-       WREG32(DC_HPD1_INT_CONTROL, tmp);
-       tmp = RREG32(DC_HPD2_INT_CONTROL) & DC_HPDx_INT_POLARITY;
-       WREG32(DC_HPD2_INT_CONTROL, tmp);
-       tmp = RREG32(DC_HPD3_INT_CONTROL) & DC_HPDx_INT_POLARITY;
-       WREG32(DC_HPD3_INT_CONTROL, tmp);
-       tmp = RREG32(DC_HPD4_INT_CONTROL) & DC_HPDx_INT_POLARITY;
-       WREG32(DC_HPD4_INT_CONTROL, tmp);
-       tmp = RREG32(DC_HPD5_INT_CONTROL) & DC_HPDx_INT_POLARITY;
-       WREG32(DC_HPD5_INT_CONTROL, tmp);
-       tmp = RREG32(DC_HPD6_INT_CONTROL) & DC_HPDx_INT_POLARITY;
-       WREG32(DC_HPD6_INT_CONTROL, tmp);
+       if (!ASIC_IS_NODCE(rdev)) {
+               WREG32(DACA_AUTODETECT_INT_CONTROL, 0);
 
+               tmp = RREG32(DC_HPD1_INT_CONTROL) & DC_HPDx_INT_POLARITY;
+               WREG32(DC_HPD1_INT_CONTROL, tmp);
+               tmp = RREG32(DC_HPD2_INT_CONTROL) & DC_HPDx_INT_POLARITY;
+               WREG32(DC_HPD2_INT_CONTROL, tmp);
+               tmp = RREG32(DC_HPD3_INT_CONTROL) & DC_HPDx_INT_POLARITY;
+               WREG32(DC_HPD3_INT_CONTROL, tmp);
+               tmp = RREG32(DC_HPD4_INT_CONTROL) & DC_HPDx_INT_POLARITY;
+               WREG32(DC_HPD4_INT_CONTROL, tmp);
+               tmp = RREG32(DC_HPD5_INT_CONTROL) & DC_HPDx_INT_POLARITY;
+               WREG32(DC_HPD5_INT_CONTROL, tmp);
+               tmp = RREG32(DC_HPD6_INT_CONTROL) & DC_HPDx_INT_POLARITY;
+               WREG32(DC_HPD6_INT_CONTROL, tmp);
+       }
 }
 
 static int si_irq_init(struct radeon_device *rdev)
@@ -4366,7 +4574,7 @@ int si_irq_set(struct radeon_device *rdev)
        u32 cp_int_cntl = CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE;
        u32 cp_int_cntl1 = 0, cp_int_cntl2 = 0;
        u32 crtc1 = 0, crtc2 = 0, crtc3 = 0, crtc4 = 0, crtc5 = 0, crtc6 = 0;
-       u32 hpd1, hpd2, hpd3, hpd4, hpd5, hpd6;
+       u32 hpd1 = 0, hpd2 = 0, hpd3 = 0, hpd4 = 0, hpd5 = 0, hpd6 = 0;
        u32 grbm_int_cntl = 0;
        u32 grph1 = 0, grph2 = 0, grph3 = 0, grph4 = 0, grph5 = 0, grph6 = 0;
        u32 dma_cntl, dma_cntl1;
@@ -4383,12 +4591,14 @@ int si_irq_set(struct radeon_device *rdev)
                return 0;
        }
 
-       hpd1 = RREG32(DC_HPD1_INT_CONTROL) & ~DC_HPDx_INT_EN;
-       hpd2 = RREG32(DC_HPD2_INT_CONTROL) & ~DC_HPDx_INT_EN;
-       hpd3 = RREG32(DC_HPD3_INT_CONTROL) & ~DC_HPDx_INT_EN;
-       hpd4 = RREG32(DC_HPD4_INT_CONTROL) & ~DC_HPDx_INT_EN;
-       hpd5 = RREG32(DC_HPD5_INT_CONTROL) & ~DC_HPDx_INT_EN;
-       hpd6 = RREG32(DC_HPD6_INT_CONTROL) & ~DC_HPDx_INT_EN;
+       if (!ASIC_IS_NODCE(rdev)) {
+               hpd1 = RREG32(DC_HPD1_INT_CONTROL) & ~DC_HPDx_INT_EN;
+               hpd2 = RREG32(DC_HPD2_INT_CONTROL) & ~DC_HPDx_INT_EN;
+               hpd3 = RREG32(DC_HPD3_INT_CONTROL) & ~DC_HPDx_INT_EN;
+               hpd4 = RREG32(DC_HPD4_INT_CONTROL) & ~DC_HPDx_INT_EN;
+               hpd5 = RREG32(DC_HPD5_INT_CONTROL) & ~DC_HPDx_INT_EN;
+               hpd6 = RREG32(DC_HPD6_INT_CONTROL) & ~DC_HPDx_INT_EN;
+       }
 
        dma_cntl = RREG32(DMA_CNTL + DMA0_REGISTER_OFFSET) & ~TRAP_ENABLE;
        dma_cntl1 = RREG32(DMA_CNTL + DMA1_REGISTER_OFFSET) & ~TRAP_ENABLE;
@@ -4479,8 +4689,10 @@ int si_irq_set(struct radeon_device *rdev)
 
        WREG32(GRBM_INT_CNTL, grbm_int_cntl);
 
-       WREG32(INT_MASK + EVERGREEN_CRTC0_REGISTER_OFFSET, crtc1);
-       WREG32(INT_MASK + EVERGREEN_CRTC1_REGISTER_OFFSET, crtc2);
+       if (rdev->num_crtc >= 2) {
+               WREG32(INT_MASK + EVERGREEN_CRTC0_REGISTER_OFFSET, crtc1);
+               WREG32(INT_MASK + EVERGREEN_CRTC1_REGISTER_OFFSET, crtc2);
+       }
        if (rdev->num_crtc >= 4) {
                WREG32(INT_MASK + EVERGREEN_CRTC2_REGISTER_OFFSET, crtc3);
                WREG32(INT_MASK + EVERGREEN_CRTC3_REGISTER_OFFSET, crtc4);
@@ -4490,8 +4702,10 @@ int si_irq_set(struct radeon_device *rdev)
                WREG32(INT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, crtc6);
        }
 
-       WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, grph1);
-       WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, grph2);
+       if (rdev->num_crtc >= 2) {
+               WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, grph1);
+               WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, grph2);
+       }
        if (rdev->num_crtc >= 4) {
                WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, grph3);
                WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, grph4);
@@ -4501,12 +4715,14 @@ int si_irq_set(struct radeon_device *rdev)
                WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, grph6);
        }
 
-       WREG32(DC_HPD1_INT_CONTROL, hpd1);
-       WREG32(DC_HPD2_INT_CONTROL, hpd2);
-       WREG32(DC_HPD3_INT_CONTROL, hpd3);
-       WREG32(DC_HPD4_INT_CONTROL, hpd4);
-       WREG32(DC_HPD5_INT_CONTROL, hpd5);
-       WREG32(DC_HPD6_INT_CONTROL, hpd6);
+       if (!ASIC_IS_NODCE(rdev)) {
+               WREG32(DC_HPD1_INT_CONTROL, hpd1);
+               WREG32(DC_HPD2_INT_CONTROL, hpd2);
+               WREG32(DC_HPD3_INT_CONTROL, hpd3);
+               WREG32(DC_HPD4_INT_CONTROL, hpd4);
+               WREG32(DC_HPD5_INT_CONTROL, hpd5);
+               WREG32(DC_HPD6_INT_CONTROL, hpd6);
+       }
 
        return 0;
 }
@@ -4515,6 +4731,9 @@ static inline void si_irq_ack(struct radeon_device *rdev)
 {
        u32 tmp;
 
+       if (ASIC_IS_NODCE(rdev))
+               return;
+
        rdev->irq.stat_regs.evergreen.disp_int = RREG32(DISP_INTERRUPT_STATUS);
        rdev->irq.stat_regs.evergreen.disp_int_cont = RREG32(DISP_INTERRUPT_STATUS_CONTINUE);
        rdev->irq.stat_regs.evergreen.disp_int_cont2 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE2);
@@ -5118,17 +5337,25 @@ static int si_startup(struct radeon_device *rdev)
                return r;
        }
 
-       r = rv770_uvd_resume(rdev);
-       if (!r) {
-               r = radeon_fence_driver_start_ring(rdev,
-                                                  R600_RING_TYPE_UVD_INDEX);
+       if (rdev->has_uvd) {
+               r = rv770_uvd_resume(rdev);
+               if (!r) {
+                       r = radeon_fence_driver_start_ring(rdev,
+                                                          R600_RING_TYPE_UVD_INDEX);
+                       if (r)
+                               dev_err(rdev->dev, "UVD fences init error (%d).\n", r);
+               }
                if (r)
-                       dev_err(rdev->dev, "UVD fences init error (%d).\n", r);
+                       rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
        }
-       if (r)
-               rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
 
        /* Enable IRQ */
+       if (!rdev->irq.installed) {
+               r = radeon_irq_kms_init(rdev);
+               if (r)
+                       return r;
+       }
+
        r = si_irq_init(rdev);
        if (r) {
                DRM_ERROR("radeon: IH init failed (%d).\n", r);
@@ -5185,16 +5412,18 @@ static int si_startup(struct radeon_device *rdev)
        if (r)
                return r;
 
-       ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
-       if (ring->ring_size) {
-               r = radeon_ring_init(rdev, ring, ring->ring_size,
-                                    R600_WB_UVD_RPTR_OFFSET,
-                                    UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR,
-                                    0, 0xfffff, RADEON_CP_PACKET2);
-               if (!r)
-                       r = r600_uvd_init(rdev);
-               if (r)
-                       DRM_ERROR("radeon: failed initializing UVD (%d).\n", r);
+       if (rdev->has_uvd) {
+               ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
+               if (ring->ring_size) {
+                       r = radeon_ring_init(rdev, ring, ring->ring_size,
+                                            R600_WB_UVD_RPTR_OFFSET,
+                                            UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR,
+                                            0, 0xfffff, RADEON_CP_PACKET2);
+                       if (!r)
+                               r = r600_uvd_init(rdev);
+                       if (r)
+                               DRM_ERROR("radeon: failed initializing UVD (%d).\n", r);
+               }
        }
 
        r = radeon_ib_pool_init(rdev);
@@ -5243,8 +5472,10 @@ int si_suspend(struct radeon_device *rdev)
        radeon_vm_manager_fini(rdev);
        si_cp_enable(rdev, false);
        cayman_dma_stop(rdev);
-       r600_uvd_rbc_stop(rdev);
-       radeon_uvd_suspend(rdev);
+       if (rdev->has_uvd) {
+               r600_uvd_rbc_stop(rdev);
+               radeon_uvd_suspend(rdev);
+       }
        si_irq_suspend(rdev);
        radeon_wb_disable(rdev);
        si_pcie_gart_disable(rdev);
@@ -5308,10 +5539,6 @@ int si_init(struct radeon_device *rdev)
        if (r)
                return r;
 
-       r = radeon_irq_kms_init(rdev);
-       if (r)
-               return r;
-
        ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
        ring->ring_obj = NULL;
        r600_ring_init(rdev, ring, 1024 * 1024);
@@ -5332,11 +5559,13 @@ int si_init(struct radeon_device *rdev)
        ring->ring_obj = NULL;
        r600_ring_init(rdev, ring, 64 * 1024);
 
-       r = radeon_uvd_init(rdev);
-       if (!r) {
-               ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
-               ring->ring_obj = NULL;
-               r600_ring_init(rdev, ring, 4096);
+       if (rdev->has_uvd) {
+               r = radeon_uvd_init(rdev);
+               if (!r) {
+                       ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
+                       ring->ring_obj = NULL;
+                       r600_ring_init(rdev, ring, 4096);
+               }
        }
 
        rdev->ih.ring_obj = NULL;
@@ -5384,7 +5613,8 @@ void si_fini(struct radeon_device *rdev)
        radeon_vm_manager_fini(rdev);
        radeon_ib_pool_fini(rdev);
        radeon_irq_kms_fini(rdev);
-       radeon_uvd_fini(rdev);
+       if (rdev->has_uvd)
+               radeon_uvd_fini(rdev);
        si_pcie_gart_fini(rdev);
        r600_vram_scratch_fini(rdev);
        radeon_gem_fini(rdev);
index 222877b..8f2d7d4 100644 (file)
@@ -28,6 +28,7 @@
 
 #define TAHITI_GB_ADDR_CONFIG_GOLDEN        0x12011003
 #define VERDE_GB_ADDR_CONFIG_GOLDEN         0x12010002
+#define HAINAN_GB_ADDR_CONFIG_GOLDEN        0x02010001
 
 /* discrete uvd clocks */
 #define        CG_UPLL_FUNC_CNTL                               0x634
index 7dff49e..99e2034 100644 (file)
@@ -451,27 +451,16 @@ void shmob_drm_crtc_finish_page_flip(struct shmob_drm_crtc *scrtc)
 {
        struct drm_pending_vblank_event *event;
        struct drm_device *dev = scrtc->crtc.dev;
-       struct timeval vblanktime;
        unsigned long flags;
 
        spin_lock_irqsave(&dev->event_lock, flags);
        event = scrtc->event;
        scrtc->event = NULL;
+       if (event) {
+               drm_send_vblank_event(dev, 0, event);
+               drm_vblank_put(dev, 0);
+       }
        spin_unlock_irqrestore(&dev->event_lock, flags);
-
-       if (event == NULL)
-               return;
-
-       event->event.sequence = drm_vblank_count_and_time(dev, 0, &vblanktime);
-       event->event.tv_sec = vblanktime.tv_sec;
-       event->event.tv_usec = vblanktime.tv_usec;
-
-       spin_lock_irqsave(&dev->event_lock, flags);
-       list_add_tail(&event->base.link, &event->base.file_priv->event_list);
-       wake_up_interruptible(&event->base.file_priv->event_wait);
-       spin_unlock_irqrestore(&dev->event_lock, flags);
-
-       drm_vblank_put(dev, 0);
 }
 
 static int shmob_drm_crtc_page_flip(struct drm_crtc *crtc,
index e461e99..7a4d101 100644 (file)
@@ -6,6 +6,7 @@ config DRM_TILCDC
        select DRM_GEM_CMA_HELPER
        select VIDEOMODE_HELPERS
        select BACKLIGHT_CLASS_DEVICE
+       select BACKLIGHT_LCD_SUPPORT
        help
          Choose this option if you have an TI SoC with LCDC display
          controller, for example AM33xx in beagle-bone, DA8xx, or
index 1e20603..8c04943 100644 (file)
@@ -1128,11 +1128,6 @@ static int tegra_dc_probe(struct platform_device *pdev)
                return err;
 
        regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!regs) {
-               dev_err(&pdev->dev, "failed to get registers\n");
-               return -ENXIO;
-       }
-
        dc->regs = devm_ioremap_resource(&pdev->dev, regs);
        if (IS_ERR(dc->regs))
                return PTR_ERR(dc->regs);
index dc9adfe..14ef6ab 100644 (file)
@@ -217,6 +217,13 @@ config HID_ELECOM
        ---help---
        Support for the ELECOM BM084 (bluetooth mouse).
 
+config HID_ELO
+       tristate "ELO USB 4000/4500 touchscreen"
+       depends on USB_HID
+       ---help---
+       Support for the ELO USB 4000/4500 touchscreens. Note that this is for
+       different devices than those handled by CONFIG_TOUCHSCREEN_USB_ELO.
+
 config HID_EZKEY
        tristate "Ezkey BTC 8193 keyboard" if EXPERT
        depends on HID
@@ -231,6 +238,9 @@ config HID_HOLTEK
        Support for Holtek based devices:
          - Holtek On Line Grip based game controller
          - Trust GXT 18 Gaming Keyboard
+         - Sharkoon Drakonia / Perixx MX-2000 gaming mice
+         - Tracer Sniper TRM-503 / NOVA Gaming Slider X200 /
+           Zalman ZM-GM1
 
 config HOLTEK_FF
        bool "Holtek On Line Grip force feedback support"
@@ -240,6 +250,12 @@ config HOLTEK_FF
          Say Y here if you have a Holtek On Line Grip based game controller
          and want to have force feedback support for it.
 
+config HID_HUION
+       tristate "Huion tablets"
+       depends on USB_HID
+       ---help---
+       Support for Huion 580 tablet.
+
 config HID_KEYTOUCH
        tristate "Keytouch HID devices"
        depends on HID
@@ -561,15 +577,6 @@ config HID_PRIMAX
        Support for Primax devices that are not fully compliant with the
        HID standard.
 
-config HID_PS3REMOTE
-       tristate "Sony PS3 BD Remote Control"
-       depends on HID
-       ---help---
-       Support for the Sony PS3 Blue-ray Disk Remote Control and Logitech
-       Harmony Adapter for PS3, which connect over Bluetooth.
-
-       Support for the 6-axis controllers is provided by HID_SONY.
-
 config HID_ROCCAT
        tristate "Roccat device support"
        depends on USB_HID
@@ -594,12 +601,17 @@ config HID_SAMSUNG
        Support for Samsung InfraRed remote control or keyboards.
 
 config HID_SONY
-       tristate "Sony PS3 controller"
+       tristate "Sony PS2/3 accessories"
        depends on USB_HID
+       depends on NEW_LEDS
+       depends on LEDS_CLASS
        ---help---
-       Support for Sony PS3 6-axis controllers.
+       Support for
 
-       Support for the Sony PS3 BD Remote is provided by HID_PS3REMOTE.
+         * Sony PS3 6-axis controllers
+         * Buzz controllers
+         * Sony PS3 Blue-ray Disk Remote Control (Bluetooth)
+         * Logitech Harmony adapter for Sony Playstation 3 (Bluetooth)
 
 config HID_SPEEDLINK
        tristate "Speedlink VAD Cezanne mouse support"
index 6a1215b..6f68728 100644 (file)
@@ -45,10 +45,13 @@ obj-$(CONFIG_HID_CYPRESS)   += hid-cypress.o
 obj-$(CONFIG_HID_DRAGONRISE)   += hid-dr.o
 obj-$(CONFIG_HID_EMS_FF)       += hid-emsff.o
 obj-$(CONFIG_HID_ELECOM)       += hid-elecom.o
+obj-$(CONFIG_HID_ELO)          += hid-elo.o
 obj-$(CONFIG_HID_EZKEY)                += hid-ezkey.o
 obj-$(CONFIG_HID_GYRATION)     += hid-gyration.o
 obj-$(CONFIG_HID_HOLTEK)       += hid-holtek-kbd.o
+obj-$(CONFIG_HID_HOLTEK)       += hid-holtek-mouse.o
 obj-$(CONFIG_HID_HOLTEK)       += hid-holtekff.o
+obj-$(CONFIG_HID_HUION)                += hid-huion.o
 obj-$(CONFIG_HID_HYPERV_MOUSE) += hid-hyperv.o
 obj-$(CONFIG_HID_ICADE)                += hid-icade.o
 obj-$(CONFIG_HID_KENSINGTON)   += hid-kensington.o
@@ -89,7 +92,6 @@ hid-picolcd-y                 += hid-picolcd_debugfs.o
 endif
 
 obj-$(CONFIG_HID_PRIMAX)       += hid-primax.o
-obj-$(CONFIG_HID_PS3REMOTE)    += hid-ps3remote.o
 obj-$(CONFIG_HID_ROCCAT)       += hid-roccat.o hid-roccat-common.o \
        hid-roccat-arvo.o hid-roccat-isku.o hid-roccat-kone.o \
        hid-roccat-koneplus.o hid-roccat-konepure.o hid-roccat-kovaplus.o \
index 264f550..e39dac6 100644 (file)
@@ -1293,7 +1293,7 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i
 
        if (hdrv && hdrv->raw_event && hid_match_report(hid, report)) {
                ret = hdrv->raw_event(hid, report, data, size);
-               if (ret != 0) {
+               if (ret < 0) {
                        ret = ret < 0 ? ret : 0;
                        goto unlock;
                }
@@ -1573,6 +1573,8 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) },
        { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0011) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ELO, 0x0009) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ELO, 0x0030) },
        { HID_USB_DEVICE(USB_VENDOR_ID_EMS, USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II) },
        { HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) },
        { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) },
@@ -1584,10 +1586,14 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) },
        { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK, USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP) },
        { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A04A) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A067) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_HUION, USB_DEVICE_ID_HUION_580) },
        { HID_USB_DEVICE(USB_VENDOR_ID_JESS2, USB_DEVICE_ID_JESS2_COLOR_RUMBLE_PAD) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ION, USB_DEVICE_ID_ICADE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_KEYTOUCH, USB_DEVICE_ID_KEYTOUCH_IEC) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) },
        { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_I405X) },
        { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X) },
@@ -1680,6 +1686,8 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_SKYCABLE, USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_BUZZ_CONTROLLER) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
        { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER) },
@@ -2042,6 +2050,8 @@ static const struct hid_device_id hid_ignore_list[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1006) },
        { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1007) },
        { HID_USB_DEVICE(USB_VENDOR_ID_IMATION, USB_DEVICE_ID_DISC_STAKKA) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_JABRA, USB_DEVICE_ID_JABRA_SPEAK_410) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_JABRA, USB_DEVICE_ID_JABRA_SPEAK_510) },
        { HID_USB_DEVICE(USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO) },
        { HID_USB_DEVICE(USB_VENDOR_ID_KWORLD, USB_DEVICE_ID_KWORLD_RADIO_FM700) },
        { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_GPEN_560) },
diff --git a/drivers/hid/hid-elo.c b/drivers/hid/hid-elo.c
new file mode 100644 (file)
index 0000000..f042a6c
--- /dev/null
@@ -0,0 +1,273 @@
+/*
+ * HID driver for ELO usb touchscreen 4000/4500
+ *
+ * Copyright (c) 2013 Jiri Slaby
+ *
+ * Data parsing taken from elousb driver by Vojtech Pavlik.
+ *
+ * This driver is licensed under the terms of GPLv2.
+ */
+
+#include <linux/hid.h>
+#include <linux/input.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/workqueue.h>
+
+#include "hid-ids.h"
+
+#define ELO_PERIODIC_READ_INTERVAL     HZ
+#define ELO_SMARTSET_CMD_TIMEOUT       2000 /* msec */
+
+/* Elo SmartSet commands */
+#define ELO_FLUSH_SMARTSET_RESPONSES   0x02 /* Flush all pending smartset responses */
+#define ELO_SEND_SMARTSET_COMMAND      0x05 /* Send a smartset command */
+#define ELO_GET_SMARTSET_RESPONSE      0x06 /* Get a smartset response */
+#define ELO_DIAG                       0x64 /* Diagnostics command */
+#define ELO_SMARTSET_PACKET_SIZE       8
+
+struct elo_priv {
+       struct usb_device *usbdev;
+       struct delayed_work work;
+       unsigned char buffer[ELO_SMARTSET_PACKET_SIZE];
+};
+
+static struct workqueue_struct *wq;
+static bool use_fw_quirk = true;
+module_param(use_fw_quirk, bool, S_IRUGO);
+MODULE_PARM_DESC(use_fw_quirk, "Do periodic pokes for broken M firmwares (default = true)");
+
+static void elo_input_configured(struct hid_device *hdev,
+               struct hid_input *hidinput)
+{
+       struct input_dev *input = hidinput->input;
+
+       set_bit(BTN_TOUCH, input->keybit);
+       set_bit(ABS_PRESSURE, input->absbit);
+       input_set_abs_params(input, ABS_PRESSURE, 0, 256, 0, 0);
+}
+
+static void elo_process_data(struct input_dev *input, const u8 *data, int size)
+{
+       int press;
+
+       input_report_abs(input, ABS_X, (data[3] << 8) | data[2]);
+       input_report_abs(input, ABS_Y, (data[5] << 8) | data[4]);
+
+       press = 0;
+       if (data[1] & 0x80)
+               press = (data[7] << 8) | data[6];
+       input_report_abs(input, ABS_PRESSURE, press);
+
+       if (data[1] & 0x03) {
+               input_report_key(input, BTN_TOUCH, 1);
+               input_sync(input);
+       }
+
+       if (data[1] & 0x04)
+               input_report_key(input, BTN_TOUCH, 0);
+
+       input_sync(input);
+}
+
+static int elo_raw_event(struct hid_device *hdev, struct hid_report *report,
+        u8 *data, int size)
+{
+       struct hid_input *hidinput;
+
+       if (!(hdev->claimed & HID_CLAIMED_INPUT) || list_empty(&hdev->inputs))
+               return 0;
+
+       hidinput = list_first_entry(&hdev->inputs, struct hid_input, list);
+
+       switch (report->id) {
+       case 0:
+               if (data[0] == 'T') {   /* Mandatory ELO packet marker */
+                       elo_process_data(hidinput->input, data, size);
+                       return 1;
+               }
+               break;
+       default:        /* unknown report */
+               /* Unknown report type; pass upstream */
+               hid_info(hdev, "unknown report type %d\n", report->id);
+               break;
+       }
+
+       return 0;
+}
+
+static int elo_smartset_send_get(struct usb_device *dev, u8 command,
+               void *data)
+{
+       unsigned int pipe;
+       u8 dir;
+
+       if (command == ELO_SEND_SMARTSET_COMMAND) {
+               pipe = usb_sndctrlpipe(dev, 0);
+               dir = USB_DIR_OUT;
+       } else if (command == ELO_GET_SMARTSET_RESPONSE) {
+               pipe = usb_rcvctrlpipe(dev, 0);
+               dir = USB_DIR_IN;
+       } else
+               return -EINVAL;
+
+       return usb_control_msg(dev, pipe, command,
+                       dir | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       0, 0, data, ELO_SMARTSET_PACKET_SIZE,
+                       ELO_SMARTSET_CMD_TIMEOUT);
+}
+
+static int elo_flush_smartset_responses(struct usb_device *dev)
+{
+       return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+                       ELO_FLUSH_SMARTSET_RESPONSES,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       0, 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
+}
+
+static void elo_work(struct work_struct *work)
+{
+       struct elo_priv *priv = container_of(work, struct elo_priv, work.work);
+       struct usb_device *dev = priv->usbdev;
+       unsigned char *buffer = priv->buffer;
+       int ret;
+
+       ret = elo_flush_smartset_responses(dev);
+       if (ret < 0) {
+               dev_err(&dev->dev, "initial FLUSH_SMARTSET_RESPONSES failed, error %d\n",
+                               ret);
+               goto fail;
+       }
+
+       /* send Diagnostics command */
+       *buffer = ELO_DIAG;
+       ret = elo_smartset_send_get(dev, ELO_SEND_SMARTSET_COMMAND, buffer);
+       if (ret < 0) {
+               dev_err(&dev->dev, "send Diagnostics Command failed, error %d\n",
+                               ret);
+               goto fail;
+       }
+
+       /* get the result */
+       ret = elo_smartset_send_get(dev, ELO_GET_SMARTSET_RESPONSE, buffer);
+       if (ret < 0) {
+               dev_err(&dev->dev, "get Diagnostics Command response failed, error %d\n",
+                               ret);
+               goto fail;
+       }
+
+       /* read the ack */
+       if (*buffer != 'A') {
+               ret = elo_smartset_send_get(dev, ELO_GET_SMARTSET_RESPONSE,
+                               buffer);
+               if (ret < 0) {
+                       dev_err(&dev->dev, "get acknowledge response failed, error %d\n",
+                                       ret);
+                       goto fail;
+               }
+       }
+
+fail:
+       ret = elo_flush_smartset_responses(dev);
+       if (ret < 0)
+               dev_err(&dev->dev, "final FLUSH_SMARTSET_RESPONSES failed, error %d\n",
+                               ret);
+       queue_delayed_work(wq, &priv->work, ELO_PERIODIC_READ_INTERVAL);
+}
+
+/*
+ * Not all Elo devices need the periodic HID descriptor reads.
+ * Only firmware version M needs this.
+ */
+static bool elo_broken_firmware(struct usb_device *dev)
+{
+       return use_fw_quirk && le16_to_cpu(dev->descriptor.bcdDevice) == 0x10d;
+}
+
+static int elo_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+       struct elo_priv *priv;
+       int ret;
+
+       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       INIT_DELAYED_WORK(&priv->work, elo_work);
+       priv->usbdev = interface_to_usbdev(to_usb_interface(hdev->dev.parent));
+
+       hid_set_drvdata(hdev, priv);
+
+       ret = hid_parse(hdev);
+       if (ret) {
+               hid_err(hdev, "parse failed\n");
+               goto err_free;
+       }
+
+       ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+       if (ret) {
+               hid_err(hdev, "hw start failed\n");
+               goto err_free;
+       }
+
+       if (elo_broken_firmware(priv->usbdev)) {
+               hid_info(hdev, "broken firmware found, installing workaround\n");
+               queue_delayed_work(wq, &priv->work, ELO_PERIODIC_READ_INTERVAL);
+       }
+
+       return 0;
+err_free:
+       kfree(priv);
+       return ret;
+}
+
+static void elo_remove(struct hid_device *hdev)
+{
+       struct elo_priv *priv = hid_get_drvdata(hdev);
+
+       hid_hw_stop(hdev);
+       flush_workqueue(wq);
+       kfree(priv);
+}
+
+static const struct hid_device_id elo_devices[] = {
+       { HID_USB_DEVICE(USB_VENDOR_ID_ELO, 0x0009), },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ELO, 0x0030), },
+       { }
+};
+MODULE_DEVICE_TABLE(hid, elo_devices);
+
+static struct hid_driver elo_driver = {
+       .name = "elo",
+       .id_table = elo_devices,
+       .probe = elo_probe,
+       .remove = elo_remove,
+       .raw_event = elo_raw_event,
+       .input_configured = elo_input_configured,
+};
+
+static int __init elo_driver_init(void)
+{
+       int ret;
+
+       wq = create_singlethread_workqueue("elousb");
+       if (!wq)
+               return -ENOMEM;
+
+       ret = hid_register_driver(&elo_driver);
+       if (ret)
+               destroy_workqueue(wq);
+
+       return ret;
+}
+module_init(elo_driver_init);
+
+static void __exit elo_driver_exit(void)
+{
+       hid_unregister_driver(&elo_driver);
+       destroy_workqueue(wq);
+}
+module_exit(elo_driver_exit);
+
+MODULE_AUTHOR("Jiri Slaby <jslaby@suse.cz>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hid/hid-holtek-mouse.c b/drivers/hid/hid-holtek-mouse.c
new file mode 100644 (file)
index 0000000..7e6db3c
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * HID driver for Holtek gaming mice
+ * Copyright (c) 2013 Christian Ohm
+ * Heavily inspired by various other HID drivers that adjust the report
+ * descriptor.
+*/
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the 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/hid.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+
+#include "hid-ids.h"
+
+/*
+ * The report descriptor of some Holtek based gaming mice specifies an
+ * excessively large number of consumer usages (2^15), which is more than
+ * HID_MAX_USAGES. This prevents proper parsing of the report descriptor.
+ *
+ * This driver fixes the report descriptor for:
+ * - USB ID 04d9:a067, sold as Sharkoon Drakonia and Perixx MX-2000
+ * - USB ID 04d9:a04a, sold as Tracer Sniper TRM-503, NOVA Gaming Slider X200
+ *   and Zalman ZM-GM1
+ */
+
+static __u8 *holtek_mouse_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+               unsigned int *rsize)
+{
+       struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
+
+       if (intf->cur_altsetting->desc.bInterfaceNumber == 1) {
+               /* Change usage maximum and logical maximum from 0x7fff to
+                * 0x2fff, so they don't exceed HID_MAX_USAGES */
+               switch (hdev->product) {
+               case USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A067:
+                       if (*rsize >= 122 && rdesc[115] == 0xff && rdesc[116] == 0x7f
+                                       && rdesc[120] == 0xff && rdesc[121] == 0x7f) {
+                               hid_info(hdev, "Fixing up report descriptor\n");
+                               rdesc[116] = rdesc[121] = 0x2f;
+                       }
+                       break;
+               case USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A04A:
+                       if (*rsize >= 113 && rdesc[106] == 0xff && rdesc[107] == 0x7f
+                                       && rdesc[111] == 0xff && rdesc[112] == 0x7f) {
+                               hid_info(hdev, "Fixing up report descriptor\n");
+                               rdesc[107] = rdesc[112] = 0x2f;
+                       }
+                       break;
+               }
+
+       }
+       return rdesc;
+}
+
+static const struct hid_device_id holtek_mouse_devices[] = {
+       { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT,
+                       USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A067) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT,
+                       USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A04A) },
+       { }
+};
+MODULE_DEVICE_TABLE(hid, holtek_mouse_devices);
+
+static struct hid_driver holtek_mouse_driver = {
+       .name = "holtek_mouse",
+       .id_table = holtek_mouse_devices,
+       .report_fixup = holtek_mouse_report_fixup,
+};
+
+module_hid_driver(holtek_mouse_driver);
+MODULE_LICENSE("GPL");
diff --git a/drivers/hid/hid-huion.c b/drivers/hid/hid-huion.c
new file mode 100644 (file)
index 0000000..cbf4da4
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ *  HID driver for Huion devices not fully compliant with HID standard
+ *
+ *  Copyright (c) 2013 Martin Rusko
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the 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/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include "usbhid/usbhid.h"
+
+#include "hid-ids.h"
+
+/* Original Huion 580 report descriptor size */
+#define HUION_580_RDESC_ORIG_SIZE      177
+
+/* Fixed Huion 580 report descriptor */
+static __u8 huion_580_rdesc_fixed[] = {
+       0x05, 0x0D,         /*  Usage Page (Digitizer),             */
+       0x09, 0x02,         /*  Usage (Pen),                        */
+       0xA1, 0x01,         /*  Collection (Application),           */
+       0x85, 0x07,         /*      Report ID (7),                  */
+       0x09, 0x20,         /*      Usage (Stylus),                 */
+       0xA0,               /*      Collection (Physical),          */
+       0x14,               /*          Logical Minimum (0),        */
+       0x25, 0x01,         /*          Logical Maximum (1),        */
+       0x75, 0x01,         /*          Report Size (1),            */
+       0x09, 0x42,         /*          Usage (Tip Switch),         */
+       0x09, 0x44,         /*          Usage (Barrel Switch),      */
+       0x09, 0x46,         /*          Usage (Tablet Pick),        */
+       0x95, 0x03,         /*          Report Count (3),           */
+       0x81, 0x02,         /*          Input (Variable),           */
+       0x95, 0x03,         /*          Report Count (3),           */
+       0x81, 0x03,         /*          Input (Constant, Variable), */
+       0x09, 0x32,         /*          Usage (In Range),           */
+       0x95, 0x01,         /*          Report Count (1),           */
+       0x81, 0x02,         /*          Input (Variable),           */
+       0x95, 0x01,         /*          Report Count (1),           */
+       0x81, 0x03,         /*          Input (Constant, Variable), */
+       0x75, 0x10,         /*          Report Size (16),           */
+       0x95, 0x01,         /*          Report Count (1),           */
+       0xA4,               /*          Push,                       */
+       0x05, 0x01,         /*          Usage Page (Desktop),       */
+       0x65, 0x13,         /*          Unit (Inch),                */
+       0x55, 0xFD,         /*          Unit Exponent (-3),         */
+       0x34,               /*          Physical Minimum (0),       */
+       0x09, 0x30,         /*          Usage (X),                  */
+       0x46, 0x40, 0x1F,   /*          Physical Maximum (8000),    */
+       0x26, 0x00, 0x7D,   /*          Logical Maximum (32000),    */
+       0x81, 0x02,         /*          Input (Variable),           */
+       0x09, 0x31,         /*          Usage (Y),                  */
+       0x46, 0x88, 0x13,   /*          Physical Maximum (5000),    */
+       0x26, 0x20, 0x4E,   /*          Logical Maximum (20000),    */
+       0x81, 0x02,         /*          Input (Variable),           */
+       0xB4,               /*          Pop,                        */
+       0x09, 0x30,         /*          Usage (Tip Pressure),       */
+       0x26, 0xFF, 0x07,   /*          Logical Maximum (2047),     */
+       0x81, 0x02,         /*          Input (Variable),           */
+       0xC0,               /*      End Collection,                 */
+       0xC0                /*  End Collection                      */
+};
+
+static __u8 *huion_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+               unsigned int *rsize)
+{
+       switch (hdev->product) {
+       case USB_DEVICE_ID_HUION_580:
+               if (*rsize == HUION_580_RDESC_ORIG_SIZE) {
+                       rdesc = huion_580_rdesc_fixed;
+                       *rsize = sizeof(huion_580_rdesc_fixed);
+               }
+               break;
+       }
+       return rdesc;
+}
+
+/**
+ * Enable fully-functional tablet mode by reading special string
+ * descriptor.
+ *
+ * @hdev:      HID device
+ *
+ * The specific string descriptor and data were discovered by sniffing
+ * the Windows driver traffic.
+ */
+static int huion_tablet_enable(struct hid_device *hdev)
+{
+       int rc;
+       char buf[22];
+
+       rc = usb_string(hid_to_usb_dev(hdev), 0x64, buf, sizeof(buf));
+       if (rc < 0)
+               return rc;
+
+       return 0;
+}
+
+static int huion_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+       int ret;
+       struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
+
+       /* Ignore interfaces 1 (mouse) and 2 (keyboard) for Huion 580 tablet,
+        * as they are not used
+        */
+       switch (id->product) {
+       case USB_DEVICE_ID_HUION_580:
+               if (intf->cur_altsetting->desc.bInterfaceNumber != 0x00)
+                       return -ENODEV;
+               break;
+       }
+
+       ret = hid_parse(hdev);
+       if (ret) {
+               hid_err(hdev, "parse failed\n");
+               goto err;
+       }
+
+       ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+       if (ret) {
+               hid_err(hdev, "hw start failed\n");
+               goto err;
+       }
+
+       switch (id->product) {
+       case USB_DEVICE_ID_HUION_580:
+               ret = huion_tablet_enable(hdev);
+               if (ret) {
+                       hid_err(hdev, "tablet enabling failed\n");
+                       goto enabling_err;
+               }
+               break;
+       }
+
+       return 0;
+enabling_err:
+       hid_hw_stop(hdev);
+err:
+       return ret;
+}
+
+static int huion_raw_event(struct hid_device *hdev, struct hid_report *report,
+                       u8 *data, int size)
+{
+       /* If this is a pen input report then invert the in-range bit */
+       if (report->type == HID_INPUT_REPORT && report->id == 0x07 && size >= 2)
+               data[1] ^= 0x40;
+
+       return 0;
+}
+
+static const struct hid_device_id huion_devices[] = {
+       { HID_USB_DEVICE(USB_VENDOR_ID_HUION, USB_DEVICE_ID_HUION_580) },
+       { }
+};
+MODULE_DEVICE_TABLE(hid, huion_devices);
+
+static struct hid_driver huion_driver = {
+       .name = "huion",
+       .id_table = huion_devices,
+       .probe = huion_probe,
+       .report_fixup = huion_report_fixup,
+       .raw_event = huion_raw_event,
+};
+module_hid_driver(huion_driver);
+
+MODULE_AUTHOR("Martin Rusko");
+MODULE_DESCRIPTION("Huion HID driver");
+MODULE_LICENSE("GPL");
index aa3fec0..7132173 100644 (file)
@@ -199,13 +199,11 @@ static void mousevsc_on_receive_device_info(struct mousevsc_dev *input_device,
        if (desc->bLength == 0)
                goto cleanup;
 
-       input_device->hid_desc = kzalloc(desc->bLength, GFP_ATOMIC);
+       input_device->hid_desc = kmemdup(desc, desc->bLength, GFP_ATOMIC);
 
        if (!input_device->hid_desc)
                goto cleanup;
 
-       memcpy(input_device->hid_desc, desc, desc->bLength);
-
        input_device->report_desc_size = desc->desc[0].wDescriptorLength;
        if (input_device->report_desc_size == 0) {
                input_device->dev_info_status = -EINVAL;
index 38535c9..c5aea29 100644 (file)
 #define USB_DEVICE_ID_CYPRESS_BARCODE_4        0xed81
 #define USB_DEVICE_ID_CYPRESS_TRUETOUCH        0xc001
 
+#define USB_VENDOR_ID_DATA_MODUL       0x7374
+#define USB_VENDOR_ID_DATA_MODUL_EASYMAXTOUCH  0x1201
+
 #define USB_VENDOR_ID_DEALEXTREAME     0x10c5
 #define USB_DEVICE_ID_DEALEXTREAME_RADIO_SI4701        0x819a
 
 #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_725E      0x725e
 #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7262      0x7262
 #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_726B      0x726b
-#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72AA      0x72aa
 #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72A1      0x72a1
+#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72AA      0x72aa
+#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72C4      0x72c4
+#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72D0      0x72d0
 #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72FA      0x72fa
 #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7302      0x7302
 #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7349      0x7349
 #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_73F7      0x73f7
 #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001      0xa001
-#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7224      0x7224
-#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72D0      0x72d0
-#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72C4      0x72c4
 
 #define USB_VENDOR_ID_ELECOM           0x056e
 #define USB_DEVICE_ID_ELECOM_BM084     0x0061
 #define USB_DEVICE_ID_UGCI_FLYING      0x0020
 #define USB_DEVICE_ID_UGCI_FIGHTING    0x0030
 
+#define USB_VENDOR_ID_HUION            0x256c
+#define USB_DEVICE_ID_HUION_580                0x006e
+
 #define USB_VENDOR_ID_IDEACOM          0x1cb6
 #define USB_DEVICE_ID_IDEACOM_IDC6650  0x6650
 #define USB_DEVICE_ID_IDEACOM_IDC6651  0x6651
 
 #define USB_VENDOR_ID_HOLTEK_ALT               0x04d9
 #define USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD      0xa055
+#define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A067    0xa067
+#define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A04A    0xa04a
 
 #define USB_VENDOR_ID_IMATION          0x0718
 #define USB_DEVICE_ID_DISC_STAKKA      0xd000
 #define USB_VENDOR_ID_IRTOUCHSYSTEMS   0x6615
 #define USB_DEVICE_ID_IRTOUCH_INFRARED_USB     0x0070
 
+#define USB_VENDOR_ID_JABRA            0x0b0e
+#define USB_DEVICE_ID_JABRA_SPEAK_410  0x0412
+#define USB_DEVICE_ID_JABRA_SPEAK_510  0x0420
+
 #define USB_VENDOR_ID_JESS             0x0c45
 #define USB_DEVICE_ID_JESS_YUREX       0x1010
 
 
 #define USB_VENDOR_ID_KYE              0x0458
 #define USB_DEVICE_ID_KYE_ERGO_525V    0x0087
+#define USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE 0x0138
 #define USB_DEVICE_ID_KYE_GPEN_560     0x5003
 #define USB_DEVICE_ID_KYE_EASYPEN_I405X        0x5010
 #define USB_DEVICE_ID_KYE_MOUSEPEN_I608X       0x5011
 #define USB_DEVICE_ID_SONY_PS3_BDREMOTE                0x0306
 #define USB_DEVICE_ID_SONY_PS3_CONTROLLER      0x0268
 #define USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER       0x042f
+#define USB_DEVICE_ID_SONY_BUZZ_CONTROLLER             0x0002
+#define USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER    0x1000
 
 #define USB_VENDOR_ID_SOUNDGRAPH       0x15c2
 #define USB_DEVICE_ID_SOUNDGRAPH_IMON_FIRST    0x0034
index 945b815..7480799 100644 (file)
@@ -354,10 +354,10 @@ static int hidinput_get_battery_property(struct power_supply *psy,
                                              dev->battery_report_type);
 
                if (ret != 2) {
-                       if (ret >= 0)
-                               ret = -EINVAL;
+                       ret = -ENODATA;
                        break;
                }
+               ret = 0;
 
                if (dev->battery_min < dev->battery_max &&
                    buf[1] >= dev->battery_min &&
@@ -1042,9 +1042,14 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
 
        /*
         * Ignore out-of-range values as per HID specification,
-        * section 5.10 and 6.2.25
+        * section 5.10 and 6.2.25.
+        *
+        * The logical_minimum < logical_maximum check is done so that we
+        * don't unintentionally discard values sent by devices which
+        * don't specify logical min and max.
         */
        if ((field->flags & HID_MAIN_ITEM_VARIABLE) &&
+           (field->logical_minimum < field->logical_maximum) &&
            (value < field->logical_minimum ||
             value > field->logical_maximum)) {
                dbg_hid("Ignoring out-of-range value %x\n", value);
index 6af90db..1e2ee2a 100644 (file)
@@ -314,6 +314,25 @@ static __u8 *kye_report_fixup(struct hid_device *hdev, __u8 *rdesc,
                        *rsize = sizeof(easypen_m610x_rdesc_fixed);
                }
                break;
+       case USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE:
+               /*
+                * the fixup that need to be done:
+                *   - change Usage Maximum in the Comsumer Control
+                *     (report ID 3) to a reasonable value
+                */
+               if (*rsize >= 135 &&
+                       /* Usage Page (Consumer Devices) */
+                       rdesc[104] == 0x05 && rdesc[105] == 0x0c &&
+                       /* Usage (Consumer Control) */
+                       rdesc[106] == 0x09 && rdesc[107] == 0x01 &&
+                       /*   Usage Maximum > 12287 */
+                       rdesc[114] == 0x2a && rdesc[116] > 0x2f) {
+                       hid_info(hdev,
+                                "fixing up Genius Gila Gaming Mouse "
+                                "report descriptor\n");
+                       rdesc[116] = 0x2f;
+               }
+               break;
        }
        return rdesc;
 }
@@ -407,6 +426,8 @@ static const struct hid_device_id kye_devices[] = {
                                USB_DEVICE_ID_KYE_MOUSEPEN_I608X) },
        { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
                                USB_DEVICE_ID_KYE_EASYPEN_M610X) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
+                               USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE) },
        { }
 };
 MODULE_DEVICE_TABLE(hid, kye_devices);
index dc3ae5c..cb0e361 100644 (file)
@@ -264,9 +264,12 @@ static struct mt_class mt_classes[] = {
 static void mt_free_input_name(struct hid_input *hi)
 {
        struct hid_device *hdev = hi->report->device;
+       const char *name = hi->input->name;
 
-       if (hi->input->name != hdev->name)
-               kfree(hi->input->name);
+       if (name != hdev->name) {
+               hi->input->name = hdev->name;
+               kfree(name);
+       }
 }
 
 static ssize_t mt_show_quirks(struct device *dev,
@@ -1040,11 +1043,11 @@ static void mt_remove(struct hid_device *hdev)
        struct hid_input *hi;
 
        sysfs_remove_group(&hdev->dev.kobj, &mt_attribute_group);
-       hid_hw_stop(hdev);
-
        list_for_each_entry(hi, &hdev->inputs, list)
                mt_free_input_name(hi);
 
+       hid_hw_stop(hdev);
+
        kfree(td);
        hid_set_drvdata(hdev, NULL);
 }
@@ -1108,6 +1111,11 @@ static const struct hid_device_id mt_devices[] = {
                HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS,
                        USB_DEVICE_ID_CYPRESS_TRUETOUCH) },
 
+       /* Data Modul easyMaxTouch */
+       { .driver_data = MT_CLS_DEFAULT,
+               MT_USB_DEVICE(USB_VENDOR_ID_DATA_MODUL,
+                       USB_VENDOR_ID_DATA_MODUL_EASYMAXTOUCH) },
+
        /* eGalax devices (resistive) */
        { .driver_data = MT_CLS_EGALAX,
                MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
@@ -1117,33 +1125,39 @@ static const struct hid_device_id mt_devices[] = {
                        USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480E) },
 
        /* eGalax devices (capacitive) */
-       { .driver_data = MT_CLS_EGALAX,
-               MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
-                       USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_720C) },
        { .driver_data = MT_CLS_EGALAX_SERIAL,
                MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
                        USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7207) },
-       { .driver_data = MT_CLS_EGALAX_SERIAL,
+       { .driver_data = MT_CLS_EGALAX,
                MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
-                       USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_725E) },
+                       USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_720C) },
        { .driver_data = MT_CLS_EGALAX_SERIAL,
                MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
                        USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7224) },
        { .driver_data = MT_CLS_EGALAX_SERIAL,
                MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
                        USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_722A) },
-       { .driver_data = MT_CLS_EGALAX,
+       { .driver_data = MT_CLS_EGALAX_SERIAL,
                MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
-                       USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_726B) },
+                       USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_725E) },
        { .driver_data = MT_CLS_EGALAX_SERIAL,
                MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
                        USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7262) },
+       { .driver_data = MT_CLS_EGALAX,
+               MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
+                       USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_726B) },
        { .driver_data = MT_CLS_EGALAX,
                MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
                        USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72A1) },
        { .driver_data = MT_CLS_EGALAX_SERIAL,
                MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
                        USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72AA) },
+       { .driver_data = MT_CLS_EGALAX,
+               HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
+                       USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72C4) },
+       { .driver_data = MT_CLS_EGALAX,
+               HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
+                       USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72D0) },
        { .driver_data = MT_CLS_EGALAX,
                MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
                        USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72FA) },
@@ -1159,15 +1173,6 @@ static const struct hid_device_id mt_devices[] = {
        { .driver_data = MT_CLS_EGALAX_SERIAL,
                MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
                        USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001) },
-       { .driver_data = MT_CLS_EGALAX,
-               HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
-                       USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7224) },
-       { .driver_data = MT_CLS_EGALAX,
-               HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
-                       USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72D0) },
-       { .driver_data = MT_CLS_EGALAX,
-               HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
-                       USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72C4) },
 
        /* Elo TouchSystems IntelliTouch Plus panel */
        { .driver_data = MT_CLS_DUAL_CONTACT_ID,
diff --git a/drivers/hid/hid-ps3remote.c b/drivers/hid/hid-ps3remote.c
deleted file mode 100644 (file)
index f1239d3..0000000
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * HID driver for Sony PS3 BD Remote Control
- *
- * Copyright (c) 2012 David Dillow <dave@thedillows.org>
- * Based on a blend of the bluez fakehid user-space code by Marcel Holtmann
- * and other kernel HID drivers.
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-
-/* NOTE: in order for the Sony PS3 BD Remote Control to be found by
- * a Bluetooth host, the key combination Start+Enter has to be kept pressed
- * for about 7 seconds with the Bluetooth Host Controller in discovering mode.
- *
- * There will be no PIN request from the device.
- */
-
-#include <linux/device.h>
-#include <linux/hid.h>
-#include <linux/module.h>
-
-#include "hid-ids.h"
-
-static __u8 ps3remote_rdesc[] = {
-       0x05, 0x01,          /* GUsagePage Generic Desktop */
-       0x09, 0x05,          /* LUsage 0x05 [Game Pad] */
-       0xA1, 0x01,          /* MCollection Application (mouse, keyboard) */
-
-        /* Use collection 1 for joypad buttons */
-        0xA1, 0x02,         /* MCollection Logical (interrelated data) */
-
-         /* Ignore the 1st byte, maybe it is used for a controller
-          * number but it's not needed for correct operation */
-         0x75, 0x08,        /* GReportSize 0x08 [8] */
-         0x95, 0x01,        /* GReportCount 0x01 [1] */
-         0x81, 0x01,        /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */
-
-         /* Bytes from 2nd to 4th are a bitmap for joypad buttons, for these
-          * buttons multiple keypresses are allowed */
-         0x05, 0x09,        /* GUsagePage Button */
-         0x19, 0x01,        /* LUsageMinimum 0x01 [Button 1 (primary/trigger)] */
-         0x29, 0x18,        /* LUsageMaximum 0x18 [Button 24] */
-         0x14,              /* GLogicalMinimum [0] */
-         0x25, 0x01,        /* GLogicalMaximum 0x01 [1] */
-         0x75, 0x01,        /* GReportSize 0x01 [1] */
-         0x95, 0x18,        /* GReportCount 0x18 [24] */
-         0x81, 0x02,        /* MInput 0x02 (Data[0] Var[1] Abs[2]) */
-
-         0xC0,              /* MEndCollection */
-
-        /* Use collection 2 for remote control buttons */
-        0xA1, 0x02,         /* MCollection Logical (interrelated data) */
-
-         /* 5th byte is used for remote control buttons */
-         0x05, 0x09,        /* GUsagePage Button */
-         0x18,              /* LUsageMinimum [No button pressed] */
-         0x29, 0xFE,        /* LUsageMaximum 0xFE [Button 254] */
-         0x14,              /* GLogicalMinimum [0] */
-         0x26, 0xFE, 0x00,  /* GLogicalMaximum 0x00FE [254] */
-         0x75, 0x08,        /* GReportSize 0x08 [8] */
-         0x95, 0x01,        /* GReportCount 0x01 [1] */
-         0x80,              /* MInput  */
-
-         /* Ignore bytes from 6th to 11th, 6th to 10th are always constant at
-          * 0xff and 11th is for press indication */
-         0x75, 0x08,        /* GReportSize 0x08 [8] */
-         0x95, 0x06,        /* GReportCount 0x06 [6] */
-         0x81, 0x01,        /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */
-
-         /* 12th byte is for battery strength */
-         0x05, 0x06,        /* GUsagePage Generic Device Controls */
-         0x09, 0x20,        /* LUsage 0x20 [Battery Strength] */
-         0x14,              /* GLogicalMinimum [0] */
-         0x25, 0x05,        /* GLogicalMaximum 0x05 [5] */
-         0x75, 0x08,        /* GReportSize 0x08 [8] */
-         0x95, 0x01,        /* GReportCount 0x01 [1] */
-         0x81, 0x02,        /* MInput 0x02 (Data[0] Var[1] Abs[2]) */
-
-         0xC0,              /* MEndCollection */
-
-        0xC0                /* MEndCollection [Game Pad] */
-};
-
-static const unsigned int ps3remote_keymap_joypad_buttons[] = {
-       [0x01] = KEY_SELECT,
-       [0x02] = BTN_THUMBL,            /* L3 */
-       [0x03] = BTN_THUMBR,            /* R3 */
-       [0x04] = BTN_START,
-       [0x05] = KEY_UP,
-       [0x06] = KEY_RIGHT,
-       [0x07] = KEY_DOWN,
-       [0x08] = KEY_LEFT,
-       [0x09] = BTN_TL2,               /* L2 */
-       [0x0a] = BTN_TR2,               /* R2 */
-       [0x0b] = BTN_TL,                /* L1 */
-       [0x0c] = BTN_TR,                /* R1 */
-       [0x0d] = KEY_OPTION,            /* options/triangle */
-       [0x0e] = KEY_BACK,              /* back/circle */
-       [0x0f] = BTN_0,                 /* cross */
-       [0x10] = KEY_SCREEN,            /* view/square */
-       [0x11] = KEY_HOMEPAGE,          /* PS button */
-       [0x14] = KEY_ENTER,
-};
-static const unsigned int ps3remote_keymap_remote_buttons[] = {
-       [0x00] = KEY_1,
-       [0x01] = KEY_2,
-       [0x02] = KEY_3,
-       [0x03] = KEY_4,
-       [0x04] = KEY_5,
-       [0x05] = KEY_6,
-       [0x06] = KEY_7,
-       [0x07] = KEY_8,
-       [0x08] = KEY_9,
-       [0x09] = KEY_0,
-       [0x0e] = KEY_ESC,               /* return */
-       [0x0f] = KEY_CLEAR,
-       [0x16] = KEY_EJECTCD,
-       [0x1a] = KEY_MENU,              /* top menu */
-       [0x28] = KEY_TIME,
-       [0x30] = KEY_PREVIOUS,
-       [0x31] = KEY_NEXT,
-       [0x32] = KEY_PLAY,
-       [0x33] = KEY_REWIND,            /* scan back */
-       [0x34] = KEY_FORWARD,           /* scan forward */
-       [0x38] = KEY_STOP,
-       [0x39] = KEY_PAUSE,
-       [0x40] = KEY_CONTEXT_MENU,      /* pop up/menu */
-       [0x60] = KEY_FRAMEBACK,         /* slow/step back */
-       [0x61] = KEY_FRAMEFORWARD,      /* slow/step forward */
-       [0x63] = KEY_SUBTITLE,
-       [0x64] = KEY_AUDIO,
-       [0x65] = KEY_ANGLE,
-       [0x70] = KEY_INFO,              /* display */
-       [0x80] = KEY_BLUE,
-       [0x81] = KEY_RED,
-       [0x82] = KEY_GREEN,
-       [0x83] = KEY_YELLOW,
-};
-
-static __u8 *ps3remote_fixup(struct hid_device *hdev, __u8 *rdesc,
-                            unsigned int *rsize)
-{
-       *rsize = sizeof(ps3remote_rdesc);
-       return ps3remote_rdesc;
-}
-
-static int ps3remote_mapping(struct hid_device *hdev, struct hid_input *hi,
-                            struct hid_field *field, struct hid_usage *usage,
-                            unsigned long **bit, int *max)
-{
-       unsigned int key = usage->hid & HID_USAGE;
-
-       if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON)
-               return -1;
-
-       switch (usage->collection_index) {
-       case 1:
-               if (key >= ARRAY_SIZE(ps3remote_keymap_joypad_buttons))
-                       return -1;
-
-               key = ps3remote_keymap_joypad_buttons[key];
-               if (!key)
-                       return -1;
-               break;
-       case 2:
-               if (key >= ARRAY_SIZE(ps3remote_keymap_remote_buttons))
-                       return -1;
-
-               key = ps3remote_keymap_remote_buttons[key];
-               if (!key)
-                       return -1;
-               break;
-       default:
-               return -1;
-       }
-
-       hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key);
-       return 1;
-}
-
-static const struct hid_device_id ps3remote_devices[] = {
-       /* PS3 BD Remote Control */
-       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE) },
-       /* Logitech Harmony Adapter for PS3 */
-       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3) },
-       { }
-};
-MODULE_DEVICE_TABLE(hid, ps3remote_devices);
-
-static struct hid_driver ps3remote_driver = {
-       .name          = "ps3_remote",
-       .id_table      = ps3remote_devices,
-       .report_fixup  = ps3remote_fixup,
-       .input_mapping = ps3remote_mapping,
-};
-module_hid_driver(ps3remote_driver);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("David Dillow <dave@thedillows.org>, Antonio Ospite <ospite@studenti.unina.it>");
index b59b3df..65c4ccf 100644 (file)
@@ -366,7 +366,7 @@ void roccat_disconnect(int minor)
        mutex_lock(&devices_lock);
        devices[minor] = NULL;
        mutex_unlock(&devices_lock);
-       
+
        if (device->open) {
                hid_hw_close(device->hid);
                wake_up_interruptible(&device->wait);
@@ -426,13 +426,23 @@ static int __init roccat_init(void)
 
        if (retval < 0) {
                pr_warn("can't get major number\n");
-               return retval;
+               goto error;
        }
 
        cdev_init(&roccat_cdev, &roccat_ops);
-       cdev_add(&roccat_cdev, dev_id, ROCCAT_MAX_DEVICES);
+       retval = cdev_add(&roccat_cdev, dev_id, ROCCAT_MAX_DEVICES);
 
+       if (retval < 0) {
+               pr_warn("cannot add cdev\n");
+               goto cleanup_alloc_chrdev_region;
+       }
        return 0;
+
+
+ cleanup_alloc_chrdev_region:
+       unregister_chrdev_region(dev_id, ROCCAT_MAX_DEVICES);
+ error:
+       return retval;
 }
 
 static void __exit roccat_exit(void)
index 312098e..ecbc749 100644 (file)
@@ -1,11 +1,13 @@
 /*
- *  HID driver for some sony "special" devices
+ *  HID driver for Sony / PS2 / PS3 BD devices.
  *
  *  Copyright (c) 1999 Andreas Gal
  *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
  *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
  *  Copyright (c) 2008 Jiri Slaby
- *  Copyright (c) 2006-2008 Jiri Kosina
+ *  Copyright (c) 2012 David Dillow <dave@thedillows.org>
+ *  Copyright (c) 2006-2013 Jiri Kosina
+ *  Copyright (c) 2013 Colin Leitner <colin.leitner@gmail.com>
  */
 
 /*
  * any later version.
  */
 
+/* NOTE: in order for the Sony PS3 BD Remote Control to be found by
+ * a Bluetooth host, the key combination Start+Enter has to be kept pressed
+ * for about 7 seconds with the Bluetooth Host Controller in discovering mode.
+ *
+ * There will be no PIN request from the device.
+ */
+
 #include <linux/device.h>
 #include <linux/hid.h>
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/usb.h>
+#include <linux/leds.h>
 
 #include "hid-ids.h"
 
 #define VAIO_RDESC_CONSTANT     (1 << 0)
 #define SIXAXIS_CONTROLLER_USB  (1 << 1)
 #define SIXAXIS_CONTROLLER_BT   (1 << 2)
+#define BUZZ_CONTROLLER         (1 << 3)
+#define PS3REMOTE              (1 << 4)
 
 static const u8 sixaxis_rdesc_fixup[] = {
        0x95, 0x13, 0x09, 0x01, 0x81, 0x02, 0x95, 0x0C,
@@ -55,10 +67,214 @@ static const u8 sixaxis_rdesc_fixup2[] = {
        0xb1, 0x02, 0xc0, 0xc0,
 };
 
+static __u8 ps3remote_rdesc[] = {
+       0x05, 0x01,          /* GUsagePage Generic Desktop */
+       0x09, 0x05,          /* LUsage 0x05 [Game Pad] */
+       0xA1, 0x01,          /* MCollection Application (mouse, keyboard) */
+
+        /* Use collection 1 for joypad buttons */
+        0xA1, 0x02,         /* MCollection Logical (interrelated data) */
+
+         /* Ignore the 1st byte, maybe it is used for a controller
+          * number but it's not needed for correct operation */
+         0x75, 0x08,        /* GReportSize 0x08 [8] */
+         0x95, 0x01,        /* GReportCount 0x01 [1] */
+         0x81, 0x01,        /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */
+
+         /* Bytes from 2nd to 4th are a bitmap for joypad buttons, for these
+          * buttons multiple keypresses are allowed */
+         0x05, 0x09,        /* GUsagePage Button */
+         0x19, 0x01,        /* LUsageMinimum 0x01 [Button 1 (primary/trigger)] */
+         0x29, 0x18,        /* LUsageMaximum 0x18 [Button 24] */
+         0x14,              /* GLogicalMinimum [0] */
+         0x25, 0x01,        /* GLogicalMaximum 0x01 [1] */
+         0x75, 0x01,        /* GReportSize 0x01 [1] */
+         0x95, 0x18,        /* GReportCount 0x18 [24] */
+         0x81, 0x02,        /* MInput 0x02 (Data[0] Var[1] Abs[2]) */
+
+         0xC0,              /* MEndCollection */
+
+        /* Use collection 2 for remote control buttons */
+        0xA1, 0x02,         /* MCollection Logical (interrelated data) */
+
+         /* 5th byte is used for remote control buttons */
+         0x05, 0x09,        /* GUsagePage Button */
+         0x18,              /* LUsageMinimum [No button pressed] */
+         0x29, 0xFE,        /* LUsageMaximum 0xFE [Button 254] */
+         0x14,              /* GLogicalMinimum [0] */
+         0x26, 0xFE, 0x00,  /* GLogicalMaximum 0x00FE [254] */
+         0x75, 0x08,        /* GReportSize 0x08 [8] */
+         0x95, 0x01,        /* GReportCount 0x01 [1] */
+         0x80,              /* MInput  */
+
+         /* Ignore bytes from 6th to 11th, 6th to 10th are always constant at
+          * 0xff and 11th is for press indication */
+         0x75, 0x08,        /* GReportSize 0x08 [8] */
+         0x95, 0x06,        /* GReportCount 0x06 [6] */
+         0x81, 0x01,        /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */
+
+         /* 12th byte is for battery strength */
+         0x05, 0x06,        /* GUsagePage Generic Device Controls */
+         0x09, 0x20,        /* LUsage 0x20 [Battery Strength] */
+         0x14,              /* GLogicalMinimum [0] */
+         0x25, 0x05,        /* GLogicalMaximum 0x05 [5] */
+         0x75, 0x08,        /* GReportSize 0x08 [8] */
+         0x95, 0x01,        /* GReportCount 0x01 [1] */
+         0x81, 0x02,        /* MInput 0x02 (Data[0] Var[1] Abs[2]) */
+
+         0xC0,              /* MEndCollection */
+
+        0xC0                /* MEndCollection [Game Pad] */
+};
+
+static const unsigned int ps3remote_keymap_joypad_buttons[] = {
+       [0x01] = KEY_SELECT,
+       [0x02] = BTN_THUMBL,            /* L3 */
+       [0x03] = BTN_THUMBR,            /* R3 */
+       [0x04] = BTN_START,
+       [0x05] = KEY_UP,
+       [0x06] = KEY_RIGHT,
+       [0x07] = KEY_DOWN,
+       [0x08] = KEY_LEFT,
+       [0x09] = BTN_TL2,               /* L2 */
+       [0x0a] = BTN_TR2,               /* R2 */
+       [0x0b] = BTN_TL,                /* L1 */
+       [0x0c] = BTN_TR,                /* R1 */
+       [0x0d] = KEY_OPTION,            /* options/triangle */
+       [0x0e] = KEY_BACK,              /* back/circle */
+       [0x0f] = BTN_0,                 /* cross */
+       [0x10] = KEY_SCREEN,            /* view/square */
+       [0x11] = KEY_HOMEPAGE,          /* PS button */
+       [0x14] = KEY_ENTER,
+};
+static const unsigned int ps3remote_keymap_remote_buttons[] = {
+       [0x00] = KEY_1,
+       [0x01] = KEY_2,
+       [0x02] = KEY_3,
+       [0x03] = KEY_4,
+       [0x04] = KEY_5,
+       [0x05] = KEY_6,
+       [0x06] = KEY_7,
+       [0x07] = KEY_8,
+       [0x08] = KEY_9,
+       [0x09] = KEY_0,
+       [0x0e] = KEY_ESC,               /* return */
+       [0x0f] = KEY_CLEAR,
+       [0x16] = KEY_EJECTCD,
+       [0x1a] = KEY_MENU,              /* top menu */
+       [0x28] = KEY_TIME,
+       [0x30] = KEY_PREVIOUS,
+       [0x31] = KEY_NEXT,
+       [0x32] = KEY_PLAY,
+       [0x33] = KEY_REWIND,            /* scan back */
+       [0x34] = KEY_FORWARD,           /* scan forward */
+       [0x38] = KEY_STOP,
+       [0x39] = KEY_PAUSE,
+       [0x40] = KEY_CONTEXT_MENU,      /* pop up/menu */
+       [0x60] = KEY_FRAMEBACK,         /* slow/step back */
+       [0x61] = KEY_FRAMEFORWARD,      /* slow/step forward */
+       [0x63] = KEY_SUBTITLE,
+       [0x64] = KEY_AUDIO,
+       [0x65] = KEY_ANGLE,
+       [0x70] = KEY_INFO,              /* display */
+       [0x80] = KEY_BLUE,
+       [0x81] = KEY_RED,
+       [0x82] = KEY_GREEN,
+       [0x83] = KEY_YELLOW,
+};
+
+static const unsigned int buzz_keymap[] = {
+       /* The controller has 4 remote buzzers, each with one LED and 5
+        * buttons.
+        * 
+        * We use the mapping chosen by the controller, which is:
+        *
+        * Key          Offset
+        * -------------------
+        * Buzz              1
+        * Blue              5
+        * Orange            4
+        * Green             3
+        * Yellow            2
+        *
+        * So, for example, the orange button on the third buzzer is mapped to
+        * BTN_TRIGGER_HAPPY14
+        */
+       [ 1] = BTN_TRIGGER_HAPPY1,
+       [ 2] = BTN_TRIGGER_HAPPY2,
+       [ 3] = BTN_TRIGGER_HAPPY3,
+       [ 4] = BTN_TRIGGER_HAPPY4,
+       [ 5] = BTN_TRIGGER_HAPPY5,
+       [ 6] = BTN_TRIGGER_HAPPY6,
+       [ 7] = BTN_TRIGGER_HAPPY7,
+       [ 8] = BTN_TRIGGER_HAPPY8,
+       [ 9] = BTN_TRIGGER_HAPPY9,
+       [10] = BTN_TRIGGER_HAPPY10,
+       [11] = BTN_TRIGGER_HAPPY11,
+       [12] = BTN_TRIGGER_HAPPY12,
+       [13] = BTN_TRIGGER_HAPPY13,
+       [14] = BTN_TRIGGER_HAPPY14,
+       [15] = BTN_TRIGGER_HAPPY15,
+       [16] = BTN_TRIGGER_HAPPY16,
+       [17] = BTN_TRIGGER_HAPPY17,
+       [18] = BTN_TRIGGER_HAPPY18,
+       [19] = BTN_TRIGGER_HAPPY19,
+       [20] = BTN_TRIGGER_HAPPY20,
+};
+
 struct sony_sc {
        unsigned long quirks;
+
+       void *extra;
 };
 
+struct buzz_extra {
+       int led_state;
+       struct led_classdev *leds[4];
+};
+
+static __u8 *ps3remote_fixup(struct hid_device *hdev, __u8 *rdesc,
+                            unsigned int *rsize)
+{
+       *rsize = sizeof(ps3remote_rdesc);
+       return ps3remote_rdesc;
+}
+
+static int ps3remote_mapping(struct hid_device *hdev, struct hid_input *hi,
+                            struct hid_field *field, struct hid_usage *usage,
+                            unsigned long **bit, int *max)
+{
+       unsigned int key = usage->hid & HID_USAGE;
+
+       if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON)
+               return -1;
+
+       switch (usage->collection_index) {
+       case 1:
+               if (key >= ARRAY_SIZE(ps3remote_keymap_joypad_buttons))
+                       return -1;
+
+               key = ps3remote_keymap_joypad_buttons[key];
+               if (!key)
+                       return -1;
+               break;
+       case 2:
+               if (key >= ARRAY_SIZE(ps3remote_keymap_remote_buttons))
+                       return -1;
+
+               key = ps3remote_keymap_remote_buttons[key];
+               if (!key)
+                       return -1;
+               break;
+       default:
+               return -1;
+       }
+
+       hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key);
+       return 1;
+}
+
+
 /* Sony Vaio VGX has wrongly mouse pointer declared as constant */
 static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc,
                unsigned int *rsize)
@@ -95,6 +311,10 @@ static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc,
                *rsize = sizeof(sixaxis_rdesc_fixup2);
                memcpy(rdesc, &sixaxis_rdesc_fixup2, *rsize);
        }
+
+       if (sc->quirks & PS3REMOTE)
+               return ps3remote_fixup(hdev, rdesc, rsize);
+
        return rdesc;
 }
 
@@ -117,6 +337,41 @@ static int sony_raw_event(struct hid_device *hdev, struct hid_report *report,
        return 0;
 }
 
+static int sony_mapping(struct hid_device *hdev, struct hid_input *hi,
+                       struct hid_field *field, struct hid_usage *usage,
+                       unsigned long **bit, int *max)
+{
+       struct sony_sc *sc = hid_get_drvdata(hdev);
+
+       if (sc->quirks & BUZZ_CONTROLLER) {
+               unsigned int key = usage->hid & HID_USAGE;
+
+               if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON)
+                       return -1;
+
+               switch (usage->collection_index) {
+               case 1:
+                       if (key >= ARRAY_SIZE(buzz_keymap))
+                               return -1;
+
+                       key = buzz_keymap[key];
+                       if (!key)
+                               return -1;
+                       break;
+               default:
+                       return -1;
+               }
+
+               hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key);
+               return 1;
+       }
+
+       if (sc->quirks & PS3REMOTE)
+               return ps3remote_mapping(hdev, hi, field, usage, bit, max);
+
+       return -1;
+}
+
 /*
  * The Sony Sixaxis does not handle HID Output Reports on the Interrupt EP
  * like it should according to usbhid/hid-core.c::usbhid_output_raw_report()
@@ -192,11 +447,181 @@ static int sixaxis_set_operational_bt(struct hid_device *hdev)
        return hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT);
 }
 
+static void buzz_set_leds(struct hid_device *hdev, int leds)
+{
+       struct list_head *report_list =
+               &hdev->report_enum[HID_OUTPUT_REPORT].report_list;
+       struct hid_report *report = list_entry(report_list->next,
+               struct hid_report, list);
+       __s32 *value = report->field[0]->value;
+
+       value[0] = 0x00;
+       value[1] = (leds & 1) ? 0xff : 0x00;
+       value[2] = (leds & 2) ? 0xff : 0x00;
+       value[3] = (leds & 4) ? 0xff : 0x00;
+       value[4] = (leds & 8) ? 0xff : 0x00;
+       value[5] = 0x00;
+       value[6] = 0x00;
+       hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
+}
+
+static void buzz_led_set_brightness(struct led_classdev *led,
+                                   enum led_brightness value)
+{
+       struct device *dev = led->dev->parent;
+       struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+       struct sony_sc *drv_data;
+       struct buzz_extra *buzz;
+
+       int n;
+
+       drv_data = hid_get_drvdata(hdev);
+       if (!drv_data || !drv_data->extra) {
+               hid_err(hdev, "No device data\n");
+               return;
+       }
+       buzz = drv_data->extra;
+
+       for (n = 0; n < 4; n++) {
+               if (led == buzz->leds[n]) {
+                       int on = !! (buzz->led_state & (1 << n));
+                       if (value == LED_OFF && on) {
+                               buzz->led_state &= ~(1 << n);
+                               buzz_set_leds(hdev, buzz->led_state);
+                       } else if (value != LED_OFF && !on) {
+                               buzz->led_state |= (1 << n);
+                               buzz_set_leds(hdev, buzz->led_state);
+                       }
+                       break;
+               }
+       }
+}
+
+static enum led_brightness buzz_led_get_brightness(struct led_classdev *led)
+{
+       struct device *dev = led->dev->parent;
+       struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+       struct sony_sc *drv_data;
+       struct buzz_extra *buzz;
+
+       int n;
+       int on = 0;
+
+       drv_data = hid_get_drvdata(hdev);
+       if (!drv_data || !drv_data->extra) {
+               hid_err(hdev, "No device data\n");
+               return LED_OFF;
+       }
+       buzz = drv_data->extra;
+
+       for (n = 0; n < 4; n++) {
+               if (led == buzz->leds[n]) {
+                       on = !! (buzz->led_state & (1 << n));
+                       break;
+               }
+       }
+
+       return on ? LED_FULL : LED_OFF;
+}
+
+static int buzz_init(struct hid_device *hdev)
+{
+       struct sony_sc *drv_data;
+       struct buzz_extra *buzz;
+       int n, ret = 0;
+       struct led_classdev *led;
+       size_t name_sz;
+       char *name;
+
+       drv_data = hid_get_drvdata(hdev);
+       BUG_ON(!(drv_data->quirks & BUZZ_CONTROLLER));
+
+       buzz = kzalloc(sizeof(*buzz), GFP_KERNEL);
+       if (!buzz) {
+               hid_err(hdev, "Insufficient memory, cannot allocate driver data\n");
+               return -ENOMEM;
+       }
+       drv_data->extra = buzz;
+
+       /* Clear LEDs as we have no way of reading their initial state. This is
+        * only relevant if the driver is loaded after somebody actively set the
+        * LEDs to on */
+       buzz_set_leds(hdev, 0x00);
+
+       name_sz = strlen(dev_name(&hdev->dev)) + strlen("::buzz#") + 1;
+
+       for (n = 0; n < 4; n++) {
+               led = kzalloc(sizeof(struct led_classdev) + name_sz, GFP_KERNEL);
+               if (!led) {
+                       hid_err(hdev, "Couldn't allocate memory for LED %d\n", n);
+                       goto error_leds;
+               }
+
+               name = (void *)(&led[1]);
+               snprintf(name, name_sz, "%s::buzz%d", dev_name(&hdev->dev), n + 1);
+               led->name = name;
+               led->brightness = 0;
+               led->max_brightness = 1;
+               led->brightness_get = buzz_led_get_brightness;
+               led->brightness_set = buzz_led_set_brightness;
+
+               if (led_classdev_register(&hdev->dev, led)) {
+                       hid_err(hdev, "Failed to register LED %d\n", n);
+                       kfree(led);
+                       goto error_leds;
+               }
+
+               buzz->leds[n] = led;
+       }
+
+       return ret;
+
+error_leds:
+       for (n = 0; n < 4; n++) {
+               led = buzz->leds[n];
+               buzz->leds[n] = NULL;
+               if (!led)
+                       continue;
+               led_classdev_unregister(led);
+               kfree(led);
+       }
+
+       kfree(drv_data->extra);
+       drv_data->extra = NULL;
+       return ret;
+}
+
+static void buzz_remove(struct hid_device *hdev)
+{
+       struct sony_sc *drv_data;
+       struct buzz_extra *buzz;
+       struct led_classdev *led;
+       int n;
+
+       drv_data = hid_get_drvdata(hdev);
+       BUG_ON(!(drv_data->quirks & BUZZ_CONTROLLER));
+
+       buzz = drv_data->extra;
+
+       for (n = 0; n < 4; n++) {
+               led = buzz->leds[n];
+               buzz->leds[n] = NULL;
+               if (!led)
+                       continue;
+               led_classdev_unregister(led);
+               kfree(led);
+       }
+
+       kfree(drv_data->extra);
+       drv_data->extra = NULL;
+}
+
 static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
 {
        int ret;
        unsigned long quirks = id->driver_data;
        struct sony_sc *sc;
+       unsigned int connect_mask = HID_CONNECT_DEFAULT;
 
        sc = kzalloc(sizeof(*sc), GFP_KERNEL);
        if (sc == NULL) {
@@ -213,8 +638,14 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
                goto err_free;
        }
 
-       ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT |
-                       HID_CONNECT_HIDDEV_FORCE);
+       if (sc->quirks & VAIO_RDESC_CONSTANT)
+               connect_mask |= HID_CONNECT_HIDDEV_FORCE;
+       else if (sc->quirks & SIXAXIS_CONTROLLER_USB)
+               connect_mask |= HID_CONNECT_HIDDEV_FORCE;
+       else if (sc->quirks & SIXAXIS_CONTROLLER_BT)
+               connect_mask |= HID_CONNECT_HIDDEV_FORCE;
+
+       ret = hid_hw_start(hdev, connect_mask);
        if (ret) {
                hid_err(hdev, "hw start failed\n");
                goto err_free;
@@ -226,6 +657,8 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
        }
        else if (sc->quirks & SIXAXIS_CONTROLLER_BT)
                ret = sixaxis_set_operational_bt(hdev);
+       else if (sc->quirks & BUZZ_CONTROLLER)
+               ret = buzz_init(hdev);
        else
                ret = 0;
 
@@ -242,8 +675,13 @@ err_free:
 
 static void sony_remove(struct hid_device *hdev)
 {
+       struct sony_sc *sc = hid_get_drvdata(hdev);
+
+       if (sc->quirks & BUZZ_CONTROLLER)
+               buzz_remove(hdev);
+
        hid_hw_stop(hdev);
-       kfree(hid_get_drvdata(hdev));
+       kfree(sc);
 }
 
 static const struct hid_device_id sony_devices[] = {
@@ -257,17 +695,30 @@ static const struct hid_device_id sony_devices[] = {
                .driver_data = VAIO_RDESC_CONSTANT },
        { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE),
                .driver_data = VAIO_RDESC_CONSTANT },
+       /* Wired Buzz Controller. Reported as Sony Hub from its USB ID and as
+        * Logitech joystick from the device descriptor. */
+       { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_BUZZ_CONTROLLER),
+               .driver_data = BUZZ_CONTROLLER },
+       { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER),
+               .driver_data = BUZZ_CONTROLLER },
+       /* PS3 BD Remote Control */
+       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE),
+               .driver_data = PS3REMOTE },
+       /* Logitech Harmony Adapter for PS3 */
+       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3),
+               .driver_data = PS3REMOTE },
        { }
 };
 MODULE_DEVICE_TABLE(hid, sony_devices);
 
 static struct hid_driver sony_driver = {
-       .name = "sony",
-       .id_table = sony_devices,
-       .probe = sony_probe,
-       .remove = sony_remove,
-       .report_fixup = sony_report_fixup,
-       .raw_event = sony_raw_event
+       .name          = "sony",
+       .id_table      = sony_devices,
+       .input_mapping = sony_mapping,
+       .probe         = sony_probe,
+       .remove        = sony_remove,
+       .report_fixup  = sony_report_fixup,
+       .raw_event     = sony_raw_event
 };
 module_hid_driver(sony_driver);
 
index a4a8bb0..60c75dc 100644 (file)
@@ -46,6 +46,7 @@ struct wacom_data {
        __u8 battery_capacity;
        __u8 power_raw;
        __u8 ps_connected;
+       __u8 bat_charging;
        struct power_supply battery;
        struct power_supply ac;
        __u8 led_selector;
@@ -62,6 +63,7 @@ static enum power_supply_property wacom_battery_props[] = {
        POWER_SUPPLY_PROP_PRESENT,
        POWER_SUPPLY_PROP_CAPACITY,
        POWER_SUPPLY_PROP_SCOPE,
+       POWER_SUPPLY_PROP_STATUS,
 };
 
 static enum power_supply_property wacom_ac_props[] = {
@@ -287,6 +289,15 @@ static int wacom_battery_get_property(struct power_supply *psy,
        case POWER_SUPPLY_PROP_CAPACITY:
                val->intval = wdata->battery_capacity;
                break;
+       case POWER_SUPPLY_PROP_STATUS:
+               if (wdata->bat_charging)
+                       val->intval = POWER_SUPPLY_STATUS_CHARGING;
+               else
+                       if (wdata->battery_capacity == 100 && wdata->ps_connected)
+                               val->intval = POWER_SUPPLY_STATUS_FULL;
+                       else
+                               val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+               break;
        default:
                ret = -EINVAL;
                break;
@@ -727,7 +738,8 @@ static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report,
                        if (power_raw != wdata->power_raw) {
                                wdata->power_raw = power_raw;
                                wdata->battery_capacity = batcap_i4[power_raw & 0x07];
-                               wdata->ps_connected = power_raw & 0x08;
+                               wdata->bat_charging = (power_raw & 0x08) ? 1 : 0;
+                               wdata->ps_connected = (power_raw & 0x10) ? 1 : 0;
                        }
 
                        break;
index 2b1799a..879b0ed 100644 (file)
@@ -108,6 +108,7 @@ static const struct i2c_hid_cmd hid_reset_cmd =             { I2C_HID_CMD(0x01),
 static const struct i2c_hid_cmd hid_get_report_cmd =   { I2C_HID_CMD(0x02) };
 static const struct i2c_hid_cmd hid_set_report_cmd =   { I2C_HID_CMD(0x03) };
 static const struct i2c_hid_cmd hid_set_power_cmd =    { I2C_HID_CMD(0x08) };
+static const struct i2c_hid_cmd hid_no_cmd =           { .length = 0 };
 
 /*
  * These definitions are not used here, but are defined by the spec.
@@ -259,8 +260,11 @@ static int i2c_hid_set_report(struct i2c_client *client, u8 reportType,
 {
        struct i2c_hid *ihid = i2c_get_clientdata(client);
        u8 *args = ihid->argsbuf;
+       const struct i2c_hid_cmd * hidcmd = &hid_set_report_cmd;
        int ret;
        u16 dataRegister = le16_to_cpu(ihid->hdesc.wDataRegister);
+       u16 outputRegister = le16_to_cpu(ihid->hdesc.wOutputRegister);
+       u16 maxOutputLength = le16_to_cpu(ihid->hdesc.wMaxOutputLength);
 
        /* hidraw already checked that data_len < HID_MAX_BUFFER_SIZE */
        u16 size =      2                       /* size */ +
@@ -278,8 +282,18 @@ static int i2c_hid_set_report(struct i2c_client *client, u8 reportType,
                reportID = 0x0F;
        }
 
-       args[index++] = dataRegister & 0xFF;
-       args[index++] = dataRegister >> 8;
+       /*
+        * use the data register for feature reports or if the device does not
+        * support the output register
+        */
+       if (reportType == 0x03 || maxOutputLength == 0) {
+               args[index++] = dataRegister & 0xFF;
+               args[index++] = dataRegister >> 8;
+       } else {
+               args[index++] = outputRegister & 0xFF;
+               args[index++] = outputRegister >> 8;
+               hidcmd = &hid_no_cmd;
+       }
 
        args[index++] = size & 0xFF;
        args[index++] = size >> 8;
@@ -289,7 +303,7 @@ static int i2c_hid_set_report(struct i2c_client *client, u8 reportType,
 
        memcpy(&args[index], buf, data_len);
 
-       ret = __i2c_hid_command(client, &hid_set_report_cmd, reportID,
+       ret = __i2c_hid_command(client, hidcmd, reportID,
                reportType, args, args_len, NULL, 0);
        if (ret) {
                dev_err(&client->dev, "failed to set a report to device.\n");
index bad8128..21ef689 100644 (file)
@@ -329,7 +329,7 @@ static u32 get_vp_index(uuid_le *type_guid)
                return 0;
        }
        cur_cpu = (++next_vp % max_cpus);
-       return cur_cpu;
+       return hv_context.vp_index[cur_cpu];
 }
 
 /*
index df0b699..2ebd6ce 100644 (file)
@@ -1414,14 +1414,18 @@ static int abituguru_probe(struct platform_device *pdev)
        pr_info("found Abit uGuru\n");
 
        /* Register sysfs hooks */
-       for (i = 0; i < sysfs_attr_i; i++)
-               if (device_create_file(&pdev->dev,
-                               &data->sysfs_attr[i].dev_attr))
+       for (i = 0; i < sysfs_attr_i; i++) {
+               res = device_create_file(&pdev->dev,
+                                        &data->sysfs_attr[i].dev_attr);
+               if (res)
                        goto abituguru_probe_error;
-       for (i = 0; i < ARRAY_SIZE(abituguru_sysfs_attr); i++)
-               if (device_create_file(&pdev->dev,
-                               &abituguru_sysfs_attr[i].dev_attr))
+       }
+       for (i = 0; i < ARRAY_SIZE(abituguru_sysfs_attr); i++) {
+               res = device_create_file(&pdev->dev,
+                                        &abituguru_sysfs_attr[i].dev_attr);
+               if (res)
                        goto abituguru_probe_error;
+       }
 
        data->hwmon_dev = hwmon_device_register(&pdev->dev);
        if (!IS_ERR(data->hwmon_dev))
index 7e76922..f920619 100644 (file)
@@ -331,26 +331,68 @@ static int adm1021_detect(struct i2c_client *client,
        man_id = i2c_smbus_read_byte_data(client, ADM1021_REG_MAN_ID);
        dev_id = i2c_smbus_read_byte_data(client, ADM1021_REG_DEV_ID);
 
+       if (man_id < 0 || dev_id < 0)
+               return -ENODEV;
+
        if (man_id == 0x4d && dev_id == 0x01)
                type_name = "max1617a";
        else if (man_id == 0x41) {
                if ((dev_id & 0xF0) == 0x30)
                        type_name = "adm1023";
-               else
+               else if ((dev_id & 0xF0) == 0x00)
                        type_name = "adm1021";
+               else
+                       return -ENODEV;
        } else if (man_id == 0x49)
                type_name = "thmc10";
        else if (man_id == 0x23)
                type_name = "gl523sm";
        else if (man_id == 0x54)
                type_name = "mc1066";
-       /* LM84 Mfr ID in a different place, and it has more unused bits */
-       else if (conv_rate == 0x00
-                && (config & 0x7F) == 0x00
-                && (status & 0xAB) == 0x00)
-               type_name = "lm84";
-       else
-               type_name = "max1617";
+       else {
+               int lte, rte, lhi, rhi, llo, rlo;
+
+               /* extra checks for LM84 and MAX1617 to avoid misdetections */
+
+               llo = i2c_smbus_read_byte_data(client, ADM1021_REG_THYST_R(0));
+               rlo = i2c_smbus_read_byte_data(client, ADM1021_REG_THYST_R(1));
+
+               /* fail if any of the additional register reads failed */
+               if (llo < 0 || rlo < 0)
+                       return -ENODEV;
+
+               lte = i2c_smbus_read_byte_data(client, ADM1021_REG_TEMP(0));
+               rte = i2c_smbus_read_byte_data(client, ADM1021_REG_TEMP(1));
+               lhi = i2c_smbus_read_byte_data(client, ADM1021_REG_TOS_R(0));
+               rhi = i2c_smbus_read_byte_data(client, ADM1021_REG_TOS_R(1));
+
+               /*
+                * Fail for negative temperatures and negative high limits.
+                * This check also catches read errors on the tested registers.
+                */
+               if ((s8)lte < 0 || (s8)rte < 0 || (s8)lhi < 0 || (s8)rhi < 0)
+                       return -ENODEV;
+
+               /* fail if all registers hold the same value */
+               if (lte == rte && lte == lhi && lte == rhi && lte == llo
+                   && lte == rlo)
+                       return -ENODEV;
+
+               /*
+                * LM84 Mfr ID is in a different place,
+                * and it has more unused bits.
+                */
+               if (conv_rate == 0x00
+                   && (config & 0x7F) == 0x00
+                   && (status & 0xAB) == 0x00) {
+                       type_name = "lm84";
+               } else {
+                       /* fail if low limits are larger than high limits */
+                       if ((s8)llo > lhi || (s8)rlo > rhi)
+                               return -ENODEV;
+                       type_name = "max1617";
+               }
+       }
 
        pr_debug("Detected chip %s at adapter %d, address 0x%02x.\n",
                 type_name, i2c_adapter_id(adapter), client->addr);
index aafa453..52b77af 100644 (file)
@@ -84,8 +84,10 @@ static int iio_hwmon_probe(struct platform_device *pdev)
                return PTR_ERR(channels);
 
        st = devm_kzalloc(dev, sizeof(*st), GFP_KERNEL);
-       if (st == NULL)
-               return -ENOMEM;
+       if (st == NULL) {
+               ret = -ENOMEM;
+               goto error_release_channels;
+       }
 
        st->channels = channels;
 
@@ -159,7 +161,7 @@ static int iio_hwmon_probe(struct platform_device *pdev)
 error_remove_group:
        sysfs_remove_group(&dev->kobj, &st->attr_group);
 error_release_channels:
-       iio_channel_release_all(st->channels);
+       iio_channel_release_all(channels);
        return ret;
 }
 
index f43f5e5..04638ae 100644 (file)
@@ -3705,8 +3705,10 @@ static int nct6775_probe(struct platform_device *pdev)
                        data->have_temp |= 1 << i;
                        data->have_temp_fixed |= 1 << i;
                        data->reg_temp[0][i] = reg_temp_alternate[i];
-                       data->reg_temp[1][i] = reg_temp_over[i];
-                       data->reg_temp[2][i] = reg_temp_hyst[i];
+                       if (i < num_reg_temp) {
+                               data->reg_temp[1][i] = reg_temp_over[i];
+                               data->reg_temp[2][i] = reg_temp_hyst[i];
+                       }
                        data->temp_src[i] = i + 1;
                        continue;
                }
index a478454..dfe6d95 100644 (file)
@@ -240,7 +240,7 @@ static struct tmp401_data *tmp401_update_device(struct device *dev)
        mutex_lock(&data->update_lock);
 
        next_update = data->last_updated +
-                     msecs_to_jiffies(data->update_interval) + 1;
+                     msecs_to_jiffies(data->update_interval);
        if (time_after(jiffies, next_update) || !data->valid) {
                if (data->kind != tmp432) {
                        /*
index 21fbb34..c41ca63 100644 (file)
@@ -383,7 +383,8 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
        /* Enable the adapter */
        __i2c_dw_enable(dev, true);
 
-       /* Enable interrupts */
+       /* Clear and enable interrupts */
+       i2c_dw_clear_int(dev);
        dw_writel(dev, DW_IC_INTR_DEFAULT_MASK, DW_IC_INTR_MASK);
 }
 
@@ -448,8 +449,14 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
                                cmd |= BIT(9);
 
                        if (msgs[dev->msg_write_idx].flags & I2C_M_RD) {
+
+                               /* avoid rx buffer overrun */
+                               if (rx_limit - dev->rx_outstanding <= 0)
+                                       break;
+
                                dw_writel(dev, cmd | 0x100, DW_IC_DATA_CMD);
                                rx_limit--;
+                               dev->rx_outstanding++;
                        } else
                                dw_writel(dev, cmd | *buf++, DW_IC_DATA_CMD);
                        tx_limit--; buf_len--;
@@ -502,8 +509,10 @@ i2c_dw_read(struct dw_i2c_dev *dev)
 
                rx_valid = dw_readl(dev, DW_IC_RXFLR);
 
-               for (; len > 0 && rx_valid > 0; len--, rx_valid--)
+               for (; len > 0 && rx_valid > 0; len--, rx_valid--) {
                        *buf++ = dw_readl(dev, DW_IC_DATA_CMD);
+                       dev->rx_outstanding--;
+               }
 
                if (len > 0) {
                        dev->status |= STATUS_READ_IN_PROGRESS;
@@ -561,6 +570,7 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
        dev->msg_err = 0;
        dev->status = STATUS_IDLE;
        dev->abort_source = 0;
+       dev->rx_outstanding = 0;
 
        ret = i2c_dw_wait_bus_not_busy(dev);
        if (ret < 0)
index 9c1840e..e761ad1 100644 (file)
@@ -60,6 +60,7 @@
  * @adapter: i2c subsystem adapter node
  * @tx_fifo_depth: depth of the hardware tx fifo
  * @rx_fifo_depth: depth of the hardware rx fifo
+ * @rx_outstanding: current master-rx elements in tx fifo
  */
 struct dw_i2c_dev {
        struct device           *dev;
@@ -88,6 +89,7 @@ struct dw_i2c_dev {
        u32                     master_cfg;
        unsigned int            tx_fifo_depth;
        unsigned int            rx_fifo_depth;
+       int                     rx_outstanding;
 };
 
 #define ACCESS_SWAP            0x00000001
index 8ec9133..35b70a1 100644 (file)
@@ -69,6 +69,7 @@ static int dw_i2c_acpi_configure(struct platform_device *pdev)
 static const struct acpi_device_id dw_i2c_acpi_match[] = {
        { "INT33C2", 0 },
        { "INT33C3", 0 },
+       { "80860F41", 0 },
        { }
 };
 MODULE_DEVICE_TABLE(acpi, dw_i2c_acpi_match);
index e1cf2e0..3a6903f 100644 (file)
@@ -231,7 +231,11 @@ static const char *i801_feature_names[] = {
 
 static unsigned int disable_features;
 module_param(disable_features, uint, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(disable_features, "Disable selected driver features");
+MODULE_PARM_DESC(disable_features, "Disable selected driver features:\n"
+       "\t\t  0x01  disable SMBus PEC\n"
+       "\t\t  0x02  disable the block buffer\n"
+       "\t\t  0x08  disable the I2C block read functionality\n"
+       "\t\t  0x10  don't use interrupts ");
 
 /* Make sure the SMBus host is ready to start transmitting.
    Return 0 if it is, -EBUSY if it is not. */
index 3bbd65d..1a3abd6 100644 (file)
@@ -252,7 +252,7 @@ mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data)
                writel(drv_data->cntl_bits,
                        drv_data->reg_base + MV64XXX_I2C_REG_CONTROL);
                drv_data->block = 0;
-               wake_up_interruptible(&drv_data->waitq);
+               wake_up(&drv_data->waitq);
                break;
 
        case MV64XXX_I2C_ACTION_CONTINUE:
@@ -300,7 +300,7 @@ mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data)
                writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_STOP,
                        drv_data->reg_base + MV64XXX_I2C_REG_CONTROL);
                drv_data->block = 0;
-               wake_up_interruptible(&drv_data->waitq);
+               wake_up(&drv_data->waitq);
                break;
 
        case MV64XXX_I2C_ACTION_INVALID:
@@ -315,7 +315,7 @@ mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data)
                writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_STOP,
                        drv_data->reg_base + MV64XXX_I2C_REG_CONTROL);
                drv_data->block = 0;
-               wake_up_interruptible(&drv_data->waitq);
+               wake_up(&drv_data->waitq);
                break;
        }
 }
@@ -381,7 +381,7 @@ mv64xxx_i2c_wait_for_completion(struct mv64xxx_i2c_data *drv_data)
        unsigned long   flags;
        char            abort = 0;
 
-       time_left = wait_event_interruptible_timeout(drv_data->waitq,
+       time_left = wait_event_timeout(drv_data->waitq,
                !drv_data->block, drv_data->adapter.timeout);
 
        spin_lock_irqsave(&drv_data->lock, flags);
index 6e8ee92..cab1c91 100644 (file)
@@ -1082,11 +1082,6 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
        /* map the registers */
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (res == NULL) {
-               dev_err(&pdev->dev, "cannot find IO resource\n");
-               return -ENOENT;
-       }
-
        i2c->regs = devm_ioremap_resource(&pdev->dev, res);
 
        if (IS_ERR(i2c->regs))
index 5a7ad24..a63c7d5 100644 (file)
@@ -303,12 +303,6 @@ static int i2c_sirfsoc_probe(struct platform_device *pdev)
        adap->class = I2C_CLASS_HWMON;
 
        mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (mem_res == NULL) {
-               dev_err(&pdev->dev, "Unable to get MEM resource\n");
-               err = -EINVAL;
-               goto out;
-       }
-
        siic->base = devm_ioremap_resource(&pdev->dev, mem_res);
        if (IS_ERR(siic->base)) {
                err = PTR_ERR(siic->base);
index b60ff90..9aa1b60 100644 (file)
@@ -714,11 +714,6 @@ static int tegra_i2c_probe(struct platform_device *pdev)
        int ret = 0;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(&pdev->dev, "no mem resource\n");
-               return -EINVAL;
-       }
-
        base = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(base))
                return PTR_ERR(base);
index 6b63cc7..48e31ed 100644 (file)
@@ -892,7 +892,8 @@ i2c_sysfs_delete_device(struct device *dev, struct device_attribute *attr,
 }
 
 static DEVICE_ATTR(new_device, S_IWUSR, NULL, i2c_sysfs_new_device);
-static DEVICE_ATTR(delete_device, S_IWUSR, NULL, i2c_sysfs_delete_device);
+static DEVICE_ATTR_IGNORE_LOCKDEP(delete_device, S_IWUSR, NULL,
+                                  i2c_sysfs_delete_device);
 
 static struct attribute *i2c_adapter_attrs[] = {
        &dev_attr_name.attr,
index 0e8fab1..fa6964d 100644 (file)
@@ -272,6 +272,27 @@ static struct cpuidle_state hsw_cstates[CPUIDLE_STATE_MAX] = {
                .exit_latency = 166,
                .target_residency = 500,
                .enter = &intel_idle },
+       {
+               .name = "C8-HSW",
+               .desc = "MWAIT 0x40",
+               .flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
+               .exit_latency = 300,
+               .target_residency = 900,
+               .enter = &intel_idle },
+       {
+               .name = "C9-HSW",
+               .desc = "MWAIT 0x50",
+               .flags = MWAIT2flg(0x50) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
+               .exit_latency = 600,
+               .target_residency = 1800,
+               .enter = &intel_idle },
+       {
+               .name = "C10-HSW",
+               .desc = "MWAIT 0x60",
+               .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
+               .exit_latency = 2600,
+               .target_residency = 7700,
+               .enter = &intel_idle },
        {
                .enter = NULL }
 };
index 9f3a8ef..b3d03d3 100644 (file)
@@ -390,8 +390,8 @@ static int exynos_adc_remove(struct platform_device *pdev)
 #ifdef CONFIG_PM_SLEEP
 static int exynos_adc_suspend(struct device *dev)
 {
-       struct platform_device *pdev = to_platform_device(dev);
-       struct exynos_adc *info = platform_get_drvdata(pdev);
+       struct iio_dev *indio_dev = dev_get_drvdata(dev);
+       struct exynos_adc *info = iio_priv(indio_dev);
        u32 con;
 
        if (info->version == ADC_V2) {
@@ -413,8 +413,8 @@ static int exynos_adc_suspend(struct device *dev)
 
 static int exynos_adc_resume(struct device *dev)
 {
-       struct platform_device *pdev = to_platform_device(dev);
-       struct exynos_adc *info = platform_get_drvdata(pdev);
+       struct iio_dev *indio_dev = dev_get_drvdata(dev);
+       struct exynos_adc *info = iio_priv(indio_dev);
        int ret;
 
        ret = regulator_enable(info->vdd);
index 9201022..9d19ba7 100644 (file)
@@ -64,7 +64,7 @@ struct iio_cb_buffer *iio_channel_get_all_cb(struct device *dev,
        while (chan->indio_dev) {
                if (chan->indio_dev != indio_dev) {
                        ret = -EINVAL;
-                       goto error_release_channels;
+                       goto error_free_scan_mask;
                }
                set_bit(chan->channel->scan_index,
                        cb_buff->buffer.scan_mask);
@@ -73,6 +73,8 @@ struct iio_cb_buffer *iio_channel_get_all_cb(struct device *dev,
 
        return cb_buff;
 
+error_free_scan_mask:
+       kfree(cb_buff->buffer.scan_mask);
 error_release_channels:
        iio_channel_release_all(cb_buff->channels);
 error_free_cb_buff:
@@ -100,6 +102,7 @@ EXPORT_SYMBOL_GPL(iio_channel_stop_all_cb);
 
 void iio_channel_release_all_cb(struct iio_cb_buffer *cb_buff)
 {
+       kfree(cb_buff->buffer.scan_mask);
        iio_channel_release_all(cb_buff->channels);
        kfree(cb_buff);
 }
index bd33473..ed9bc8a 100644 (file)
@@ -312,6 +312,8 @@ int st_sensors_read_info_raw(struct iio_dev *indio_dev,
                        goto read_error;
 
                *val = *val >> ch->scan_type.shift;
+
+               err = st_sensors_set_enable(indio_dev, false);
        }
        mutex_unlock(&indio_dev->mlock);
 
index f4a6f08..b61160b 100644 (file)
@@ -5,7 +5,7 @@ menu "Digital to analog converters"
 
 config AD5064
        tristate "Analog Devices AD5064 and similar multi-channel DAC driver"
-       depends on (SPI_MASTER || I2C)
+       depends on (SPI_MASTER && I2C!=m) || I2C
        help
          Say yes here to build support for Analog Devices AD5024, AD5025, AD5044,
          AD5045, AD5064, AD5064-1, AD5065, AD5628, AD5629R, AD5648, AD5666, AD5668,
@@ -27,7 +27,7 @@ config AD5360
 
 config AD5380
        tristate "Analog Devices AD5380/81/82/83/84/90/91/92 DAC driver"
-       depends on (SPI_MASTER || I2C)
+       depends on (SPI_MASTER && I2C!=m) || I2C
        select REGMAP_I2C if I2C
        select REGMAP_SPI if SPI_MASTER
        help
@@ -57,7 +57,7 @@ config AD5624R_SPI
 
 config AD5446
        tristate "Analog Devices AD5446 and similar single channel DACs driver"
-       depends on (SPI_MASTER || I2C)
+       depends on (SPI_MASTER && I2C!=m) || I2C
        help
          Say yes here to build support for Analog Devices AD5300, AD5301, AD5310,
          AD5311, AD5320, AD5321, AD5444, AD5446, AD5450, AD5451, AD5452, AD5453,
index a884252..e76d4ac 100644 (file)
@@ -212,7 +212,7 @@ static int adf4350_set_freq(struct adf4350_state *st, unsigned long long freq)
                (pdata->r2_user_settings & (ADF4350_REG2_PD_POLARITY_POS |
                ADF4350_REG2_LDP_6ns | ADF4350_REG2_LDF_INT_N |
                ADF4350_REG2_CHARGE_PUMP_CURR_uA(5000) |
-               ADF4350_REG2_MUXOUT(0x7) | ADF4350_REG2_NOISE_MODE(0x9)));
+               ADF4350_REG2_MUXOUT(0x7) | ADF4350_REG2_NOISE_MODE(0x3)));
 
        st->regs[ADF4350_REG3] = pdata->r3_user_settings &
                                 (ADF4350_REG3_12BIT_CLKDIV(0xFFF) |
index 795d100..98ddc32 100644 (file)
@@ -124,7 +124,7 @@ static int __of_iio_channel_get(struct iio_channel *channel,
        channel->indio_dev = indio_dev;
        index = iiospec.args_count ? iiospec.args[0] : 0;
        if (index >= indio_dev->num_channels) {
-               return -EINVAL;
+               err = -EINVAL;
                goto err_put;
        }
        channel->channel = &indio_dev->channels[index];
@@ -450,7 +450,7 @@ static int iio_convert_raw_to_processed_unlocked(struct iio_channel *chan,
        s64 raw64 = raw;
        int ret;
 
-       ret = iio_channel_read(chan, &offset, NULL, IIO_CHAN_INFO_SCALE);
+       ret = iio_channel_read(chan, &offset, NULL, IIO_CHAN_INFO_OFFSET);
        if (ret == 0)
                raw64 += offset;
 
index 81c7b73..3b9afcc 100644 (file)
@@ -61,7 +61,7 @@ int qib_alloc_lkey(struct qib_mregion *mr, int dma_region)
        if (dma_region) {
                struct qib_mregion *tmr;
 
-               tmr = rcu_dereference(dev->dma_mr);
+               tmr = rcu_access_pointer(dev->dma_mr);
                if (!tmr) {
                        qib_get_mr(mr);
                        rcu_assign_pointer(dev->dma_mr, mr);
index f19b099..2e84ef8 100644 (file)
@@ -5,6 +5,7 @@
  * Copyright (C) 2004 Alex Aizman
  * Copyright (C) 2005 Mike Christie
  * Copyright (c) 2005, 2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2013 Mellanox Technologies. All rights reserved.
  * maintained by openib-general@openib.org
  *
  * This software is available to you under a choice of one of two
index 06f578c..4f069c0 100644 (file)
@@ -8,6 +8,7 @@
  *
  * Copyright (c) 2004, 2005, 2006 Voltaire, Inc. All rights reserved.
  * Copyright (c) 2005, 2006 Cisco Systems.  All rights reserved.
+ * Copyright (c) 2013 Mellanox Technologies. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
index a00ccd1..b6d81a8 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2004, 2005, 2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2013 Mellanox Technologies. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
index 68ebb7f..7827baf 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2004, 2005, 2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2013 Mellanox Technologies. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
index 5278916..2c4941d 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (c) 2004, 2005, 2006 Voltaire, Inc. All rights reserved.
  * Copyright (c) 2005, 2006 Cisco Systems.  All rights reserved.
+ * Copyright (c) 2013 Mellanox Technologies. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -292,10 +293,10 @@ out_err:
 }
 
 /**
- * releases the FMR pool, QP and CMA ID objects, returns 0 on success,
+ * releases the FMR pool and QP objects, returns 0 on success,
  * -1 on failure
  */
-static int iser_free_ib_conn_res(struct iser_conn *ib_conn, int can_destroy_id)
+static int iser_free_ib_conn_res(struct iser_conn *ib_conn)
 {
        int cq_index;
        BUG_ON(ib_conn == NULL);
@@ -314,13 +315,9 @@ static int iser_free_ib_conn_res(struct iser_conn *ib_conn, int can_destroy_id)
 
                rdma_destroy_qp(ib_conn->cma_id);
        }
-       /* if cma handler context, the caller acts s.t the cma destroy the id */
-       if (ib_conn->cma_id != NULL && can_destroy_id)
-               rdma_destroy_id(ib_conn->cma_id);
 
        ib_conn->fmr_pool = NULL;
        ib_conn->qp       = NULL;
-       ib_conn->cma_id   = NULL;
        kfree(ib_conn->page_vec);
 
        if (ib_conn->login_buf) {
@@ -415,11 +412,16 @@ static void iser_conn_release(struct iser_conn *ib_conn, int can_destroy_id)
        list_del(&ib_conn->conn_list);
        mutex_unlock(&ig.connlist_mutex);
        iser_free_rx_descriptors(ib_conn);
-       iser_free_ib_conn_res(ib_conn, can_destroy_id);
+       iser_free_ib_conn_res(ib_conn);
        ib_conn->device = NULL;
        /* on EVENT_ADDR_ERROR there's no device yet for this conn */
        if (device != NULL)
                iser_device_try_release(device);
+       /* if cma handler context, the caller actually destroy the id */
+       if (ib_conn->cma_id != NULL && can_destroy_id) {
+               rdma_destroy_id(ib_conn->cma_id);
+               ib_conn->cma_id = NULL;
+       }
        iscsi_destroy_endpoint(ib_conn->ep);
 }
 
index b08ca7a..3f3f041 100644 (file)
@@ -2226,6 +2226,27 @@ static void srpt_close_ch(struct srpt_rdma_ch *ch)
        spin_unlock_irq(&sdev->spinlock);
 }
 
+/**
+ * srpt_shutdown_session() - Whether or not a session may be shut down.
+ */
+static int srpt_shutdown_session(struct se_session *se_sess)
+{
+       struct srpt_rdma_ch *ch = se_sess->fabric_sess_ptr;
+       unsigned long flags;
+
+       spin_lock_irqsave(&ch->spinlock, flags);
+       if (ch->in_shutdown) {
+               spin_unlock_irqrestore(&ch->spinlock, flags);
+               return true;
+       }
+
+       ch->in_shutdown = true;
+       target_sess_cmd_list_set_waiting(se_sess);
+       spin_unlock_irqrestore(&ch->spinlock, flags);
+
+       return true;
+}
+
 /**
  * srpt_drain_channel() - Drain a channel by resetting the IB queue pair.
  * @cm_id: Pointer to the CM ID of the channel to be drained.
@@ -2264,6 +2285,9 @@ static void srpt_drain_channel(struct ib_cm_id *cm_id)
        spin_unlock_irq(&sdev->spinlock);
 
        if (do_reset) {
+               if (ch->sess)
+                       srpt_shutdown_session(ch->sess);
+
                ret = srpt_ch_qp_err(ch);
                if (ret < 0)
                        printk(KERN_ERR "Setting queue pair in error state"
@@ -2328,7 +2352,7 @@ static void srpt_release_channel_work(struct work_struct *w)
        se_sess = ch->sess;
        BUG_ON(!se_sess);
 
-       target_wait_for_sess_cmds(se_sess, 0);
+       target_wait_for_sess_cmds(se_sess);
 
        transport_deregister_session_configfs(se_sess);
        transport_deregister_session(se_sess);
@@ -3466,14 +3490,6 @@ static void srpt_release_cmd(struct se_cmd *se_cmd)
        spin_unlock_irqrestore(&ch->spinlock, flags);
 }
 
-/**
- * srpt_shutdown_session() - Whether or not a session may be shut down.
- */
-static int srpt_shutdown_session(struct se_session *se_sess)
-{
-       return true;
-}
-
 /**
  * srpt_close_session() - Forcibly close a session.
  *
index 4caf55c..3dae156 100644 (file)
@@ -325,6 +325,7 @@ struct srpt_rdma_ch {
        u8                      sess_name[36];
        struct work_struct      release_work;
        struct completion       *release_done;
+       bool                    in_shutdown;
 };
 
 /**
index 2f78538..b2420ae 100644 (file)
@@ -1379,6 +1379,7 @@ static int synaptics_reconnect(struct psmouse *psmouse)
 {
        struct synaptics_data *priv = psmouse->private;
        struct synaptics_data old_priv = *priv;
+       unsigned char param[2];
        int retry = 0;
        int error;
 
@@ -1394,6 +1395,7 @@ static int synaptics_reconnect(struct psmouse *psmouse)
                         */
                        ssleep(1);
                }
+               ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_GETID);
                error = synaptics_detect(psmouse, 0);
        } while (error && ++retry < 3);
 
index 0bfd8cf..518282d 100644 (file)
@@ -342,10 +342,10 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
                wacom->id[idx] = (data[2] << 4) | (data[3] >> 4) |
                        ((data[7] & 0x0f) << 20) | ((data[8] & 0xf0) << 12);
 
-               switch (wacom->id[idx] & 0xfffff) {
+               switch (wacom->id[idx]) {
                case 0x812: /* Inking pen */
                case 0x801: /* Intuos3 Inking pen */
-               case 0x20802: /* Intuos4 Inking Pen */
+               case 0x120802: /* Intuos4/5 Inking Pen */
                case 0x012:
                        wacom->tool[idx] = BTN_TOOL_PENCIL;
                        break;
@@ -356,11 +356,13 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
                case 0x823: /* Intuos3 Grip Pen */
                case 0x813: /* Intuos3 Classic Pen */
                case 0x885: /* Intuos3 Marker Pen */
-               case 0x802: /* Intuos4 General Pen */
-               case 0x804: /* Intuos4 Marker Pen */
-               case 0x40802: /* Intuos4 Classic Pen */
-               case 0x18802: /* DTH2242 Grip Pen */
+               case 0x802: /* Intuos4/5 13HD/24HD General Pen */
+               case 0x804: /* Intuos4/5 13HD/24HD Marker Pen */
                case 0x022:
+               case 0x100804: /* Intuos4/5 13HD/24HD Art Pen */
+               case 0x140802: /* Intuos4/5 13HD/24HD Classic Pen */
+               case 0x160802: /* Cintiq 13HD Pro Pen */
+               case 0x180802: /* DTH2242 Pen */
                        wacom->tool[idx] = BTN_TOOL_PEN;
                        break;
 
@@ -391,10 +393,14 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
                case 0x82b: /* Intuos3 Grip Pen Eraser */
                case 0x81b: /* Intuos3 Classic Pen Eraser */
                case 0x91b: /* Intuos3 Airbrush Eraser */
-               case 0x80c: /* Intuos4 Marker Pen Eraser */
-               case 0x80a: /* Intuos4 General Pen Eraser */
-               case 0x4080a: /* Intuos4 Classic Pen Eraser */
-               case 0x90a: /* Intuos4 Airbrush Eraser */
+               case 0x80c: /* Intuos4/5 13HD/24HD Marker Pen Eraser */
+               case 0x80a: /* Intuos4/5 13HD/24HD General Pen Eraser */
+               case 0x90a: /* Intuos4/5 13HD/24HD Airbrush Eraser */
+               case 0x14080a: /* Intuos4/5 13HD/24HD Classic Pen Eraser */
+               case 0x10090a: /* Intuos4/5 13HD/24HD Airbrush Eraser */
+               case 0x10080c: /* Intuos4/5 13HD/24HD Art Pen Eraser */
+               case 0x16080a: /* Cintiq 13HD Pro Pen Eraser */
+               case 0x18080a: /* DTH2242 Eraser */
                        wacom->tool[idx] = BTN_TOOL_RUBBER;
                        break;
 
@@ -402,7 +408,8 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
                case 0x912:
                case 0x112:
                case 0x913: /* Intuos3 Airbrush */
-               case 0x902: /* Intuos4 Airbrush */
+               case 0x902: /* Intuos4/5 13HD/24HD Airbrush */
+               case 0x100902: /* Intuos4/5 13HD/24HD Airbrush */
                        wacom->tool[idx] = BTN_TOOL_AIRBRUSH;
                        break;
 
@@ -533,10 +540,8 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
                                input_report_key(input, BTN_8, (data[3] & 0x80));
                        }
                        if (data[1] | (data[2] & 0x01) | data[3]) {
-                               input_report_key(input, wacom->tool[1], 1);
                                input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
                        } else {
-                               input_report_key(input, wacom->tool[1], 0);
                                input_report_abs(input, ABS_MISC, 0);
                        }
                } else if (features->type == DTK) {
@@ -546,6 +551,26 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
                        input_report_key(input, BTN_3, (data[6] & 0x08));
                        input_report_key(input, BTN_4, (data[6] & 0x10));
                        input_report_key(input, BTN_5, (data[6] & 0x20));
+                       if (data[6] & 0x3f) {
+                               input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
+                       } else {
+                               input_report_abs(input, ABS_MISC, 0);
+                       }
+               } else if (features->type == WACOM_13HD) {
+                       input_report_key(input, BTN_0, (data[3] & 0x01));
+                       input_report_key(input, BTN_1, (data[4] & 0x01));
+                       input_report_key(input, BTN_2, (data[4] & 0x02));
+                       input_report_key(input, BTN_3, (data[4] & 0x04));
+                       input_report_key(input, BTN_4, (data[4] & 0x08));
+                       input_report_key(input, BTN_5, (data[4] & 0x10));
+                       input_report_key(input, BTN_6, (data[4] & 0x20));
+                       input_report_key(input, BTN_7, (data[4] & 0x40));
+                       input_report_key(input, BTN_8, (data[4] & 0x80));
+                       if ((data[3] & 0x01) | data[4]) {
+                               input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
+                       } else {
+                               input_report_abs(input, ABS_MISC, 0);
+                       }
                } else if (features->type == WACOM_24HD) {
                        input_report_key(input, BTN_0, (data[6] & 0x01));
                        input_report_key(input, BTN_1, (data[6] & 0x02));
@@ -590,10 +615,8 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
                        }
 
                        if (data[1] | data[2] | (data[3] & 0x1f) | data[4] | data[6] | data[8]) {
-                               input_report_key(input, wacom->tool[1], 1);
                                input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
                        } else {
-                               input_report_key(input, wacom->tool[1], 0);
                                input_report_abs(input, ABS_MISC, 0);
                        }
                } else if (features->type >= INTUOS5S && features->type <= INTUOS5L) {
@@ -618,10 +641,8 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
                        }
 
                        if (data[2] | (data[3] & 0x01) | data[4] | data[5]) {
-                               input_report_key(input, wacom->tool[1], 1);
                                input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
                        } else {
-                               input_report_key(input, wacom->tool[1], 0);
                                input_report_abs(input, ABS_MISC, 0);
                        }
                } else {
@@ -668,10 +689,8 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
                        if ((data[5] & 0x1f) | data[6] | (data[1] & 0x1f) |
                                data[2] | (data[3] & 0x1f) | data[4] | data[8] |
                                (data[7] & 0x01)) {
-                               input_report_key(input, wacom->tool[1], 1);
                                input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
                        } else {
-                               input_report_key(input, wacom->tool[1], 0);
                                input_report_abs(input, ABS_MISC, 0);
                        }
                }
@@ -1301,6 +1320,7 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
        case INTUOS4L:
        case CINTIQ:
        case WACOM_BEE:
+       case WACOM_13HD:
        case WACOM_21UX2:
        case WACOM_22HD:
        case WACOM_24HD:
@@ -1530,15 +1550,15 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
                __set_bit(KEY_PROG1, input_dev->keybit);
                __set_bit(KEY_PROG2, input_dev->keybit);
                __set_bit(KEY_PROG3, input_dev->keybit);
+
+               input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
+               input_set_abs_params(input_dev, ABS_THROTTLE, 0, 71, 0, 0);
                /* fall through */
 
        case DTK:
                for (i = 0; i < 6; i++)
                        __set_bit(BTN_0 + i, input_dev->keybit);
 
-               input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
-               input_set_abs_params(input_dev, ABS_THROTTLE, 0, 71, 0, 0);
-
                __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
 
                wacom_setup_cintiq(wacom_wac);
@@ -1579,6 +1599,15 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
                wacom_setup_cintiq(wacom_wac);
                break;
 
+       case WACOM_13HD:
+               for (i = 0; i < 9; i++)
+                       __set_bit(BTN_0 + i, input_dev->keybit);
+
+               input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
+               __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
+               wacom_setup_cintiq(wacom_wac);
+               break;
+
        case INTUOS3:
        case INTUOS3L:
                __set_bit(BTN_4, input_dev->keybit);
@@ -1937,7 +1966,8 @@ static const struct wacom_features wacom_features_0xF4 =
          63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
 static const struct wacom_features wacom_features_0xF8 =
        { "Wacom Cintiq 24HD touch", WACOM_PKGLEN_INTUOS,   104480, 65600, 2047, /* Pen */
-         63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf6 };
+         63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
+         .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf6 };
 static const struct wacom_features wacom_features_0xF6 =
        { "Wacom Cintiq 24HD touch", .type = WACOM_24HDT, /* Touch */
          .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf8, .touch_max = 10 };
@@ -1950,6 +1980,9 @@ static const struct wacom_features wacom_features_0xC5 =
 static const struct wacom_features wacom_features_0xC6 =
        { "Wacom Cintiq 12WX",    WACOM_PKGLEN_INTUOS,    53020, 33440, 1023,
          63, WACOM_BEE, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+static const struct wacom_features wacom_features_0x304 =
+       { "Wacom Cintiq 13HD",    WACOM_PKGLEN_INTUOS,    59552, 33848, 1023,
+         63, WACOM_13HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
 static const struct wacom_features wacom_features_0xC7 =
        { "Wacom DTU1931",        WACOM_PKGLEN_GRAPHIRE,  37832, 30305,  511,
          0, PL, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
@@ -1959,6 +1992,9 @@ static const struct wacom_features wacom_features_0xCE =
 static const struct wacom_features wacom_features_0xF0 =
        { "Wacom DTU1631",        WACOM_PKGLEN_GRAPHIRE,  34623, 19553,  511,
          0, DTU, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x57 =
+       { "Wacom DTK2241",        WACOM_PKGLEN_INTUOS,    95840, 54260, 2047,
+         63, DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES};
 static const struct wacom_features wacom_features_0x59 = /* Pen */
        { "Wacom DTH2242",        WACOM_PKGLEN_INTUOS,    95840, 54260, 2047,
          63, DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
@@ -1972,6 +2008,13 @@ static const struct wacom_features wacom_features_0xCC =
 static const struct wacom_features wacom_features_0xFA =
        { "Wacom Cintiq 22HD",    WACOM_PKGLEN_INTUOS,    95840, 54260, 2047,
          63, WACOM_22HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+static const struct wacom_features wacom_features_0x5B =
+       { "Wacom Cintiq 22HDT", WACOM_PKGLEN_INTUOS,      95840, 54260, 2047,
+         63, WACOM_22HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
+         .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x5e };
+static const struct wacom_features wacom_features_0x5E =
+       { "Wacom Cintiq 22HDT", .type = WACOM_24HDT,
+         .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x5b, .touch_max = 10 };
 static const struct wacom_features wacom_features_0x90 =
        { "Wacom ISDv4 90",       WACOM_PKGLEN_GRAPHIRE,  26202, 16325,  255,
          0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
@@ -2001,7 +2044,7 @@ static const struct wacom_features wacom_features_0xE5 =
 static const struct wacom_features wacom_features_0xE6 =
        { "Wacom ISDv4 E6",       WACOM_PKGLEN_TPC2FG,    27760, 15694,  255,
          0, TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
-       .touch_max = 2 };
+         .touch_max = 2 };
 static const struct wacom_features wacom_features_0xEC =
        { "Wacom ISDv4 EC",       WACOM_PKGLEN_GRAPHIRE,  25710, 14500,  255,
          0, TABLETPC,    WACOM_INTUOS_RES, WACOM_INTUOS_RES };
@@ -2143,8 +2186,11 @@ const struct usb_device_id wacom_ids[] = {
        { USB_DEVICE_WACOM(0x43) },
        { USB_DEVICE_WACOM(0x44) },
        { USB_DEVICE_WACOM(0x45) },
+       { USB_DEVICE_WACOM(0x57) },
        { USB_DEVICE_WACOM(0x59) },
        { USB_DEVICE_DETAILED(0x5D, USB_CLASS_HID, 0, 0) },
+       { USB_DEVICE_WACOM(0x5B) },
+       { USB_DEVICE_DETAILED(0x5E, USB_CLASS_HID, 0, 0) },
        { USB_DEVICE_WACOM(0xB0) },
        { USB_DEVICE_WACOM(0xB1) },
        { USB_DEVICE_WACOM(0xB2) },
@@ -2205,6 +2251,7 @@ const struct usb_device_id wacom_ids[] = {
        { USB_DEVICE_WACOM(0x100) },
        { USB_DEVICE_WACOM(0x101) },
        { USB_DEVICE_WACOM(0x10D) },
+       { USB_DEVICE_WACOM(0x304) },
        { USB_DEVICE_WACOM(0x4001) },
        { USB_DEVICE_WACOM(0x47) },
        { USB_DEVICE_WACOM(0xF4) },
index 5f9a772..dfc9e08 100644 (file)
@@ -82,6 +82,7 @@ enum {
        WACOM_24HD,
        CINTIQ,
        WACOM_BEE,
+       WACOM_13HD,
        WACOM_MO,
        WIRELESS,
        BAMBOO_PT,
index 17c9097..39f3df8 100644 (file)
@@ -216,7 +216,7 @@ static int egalax_ts_probe(struct i2c_client *client,
        input_set_abs_params(input_dev,
                             ABS_MT_POSITION_X, 0, EGALAX_MAX_X, 0, 0);
        input_set_abs_params(input_dev,
-                            ABS_MT_POSITION_X, 0, EGALAX_MAX_Y, 0, 0);
+                            ABS_MT_POSITION_Y, 0, EGALAX_MAX_Y, 0, 0);
        input_mt_init_slots(input_dev, MAX_SUPPORT_POINTS, 0);
 
        input_set_drvdata(input_dev, ts);
index 29889bb..63b3d4e 100644 (file)
@@ -76,16 +76,10 @@ asmlinkage void __exception_irq_entry icoll_handle_irq(struct pt_regs *regs)
 {
        u32 irqnr;
 
-       do {
-               irqnr = __raw_readl(icoll_base + HW_ICOLL_STAT_OFFSET);
-               if (irqnr != 0x7f) {
-                       __raw_writel(irqnr, icoll_base + HW_ICOLL_VECTOR);
-                       irqnr = irq_find_mapping(icoll_domain, irqnr);
-                       handle_IRQ(irqnr, regs);
-                       continue;
-               }
-               break;
-       } while (1);
+       irqnr = __raw_readl(icoll_base + HW_ICOLL_STAT_OFFSET);
+       __raw_writel(irqnr, icoll_base + HW_ICOLL_VECTOR);
+       irqnr = irq_find_mapping(icoll_domain, irqnr);
+       handle_IRQ(irqnr, regs);
 }
 
 static int icoll_irq_domain_map(struct irq_domain *d, unsigned int virq,
index 065b7a3..47a52ab 100644 (file)
@@ -119,7 +119,7 @@ static int fpga_irqdomain_map(struct irq_domain *d, unsigned int irq,
 
        /* Skip invalid IRQs, only register handlers for the real ones */
        if (!(f->valid & BIT(hwirq)))
-               return -ENOTSUPP;
+               return -EPERM;
        irq_set_chip_data(irq, f);
        irq_set_chip_and_handler(irq, &f->chip,
                                handle_level_irq);
index 884d11c..2bbb004 100644 (file)
@@ -197,7 +197,7 @@ static int vic_irqdomain_map(struct irq_domain *d, unsigned int irq,
 
        /* Skip invalid IRQs, only register handlers for the real ones */
        if (!(v->valid_sources & (1 << hwirq)))
-               return -ENOTSUPP;
+               return -EPERM;
        irq_set_chip_and_handler(irq, &vic_chip, handle_level_irq);
        irq_set_chip_data(irq, v->base);
        set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
index 9b1b274..c123709 100644 (file)
@@ -93,7 +93,7 @@ capi_ctr_put(struct capi_ctr *ctr)
 
 static inline struct capi_ctr *get_capi_ctr_by_nr(u16 contr)
 {
-       if (contr - 1 >= CAPI_MAXCONTR)
+       if (contr < 1 || contr - 1 >= CAPI_MAXCONTR)
                return NULL;
 
        return capi_controller[contr - 1];
@@ -103,7 +103,7 @@ static inline struct capi20_appl *__get_capi_appl_by_nr(u16 applid)
 {
        lockdep_assert_held(&capi_controller_lock);
 
-       if (applid - 1 >= CAPI_MAXAPPL)
+       if (applid < 1 || applid - 1 >= CAPI_MAXAPPL)
                return NULL;
 
        return capi_applications[applid - 1];
@@ -111,7 +111,7 @@ static inline struct capi20_appl *__get_capi_appl_by_nr(u16 applid)
 
 static inline struct capi20_appl *get_capi_appl_by_nr(u16 applid)
 {
-       if (applid - 1 >= CAPI_MAXAPPL)
+       if (applid < 1 || applid - 1 >= CAPI_MAXAPPL)
                return NULL;
 
        return rcu_dereference(capi_applications[applid - 1]);
index a0d931b..b02b679 100644 (file)
@@ -107,6 +107,10 @@ static int create_gpio_led(const struct gpio_led *template,
                return 0;
        }
 
+       ret = devm_gpio_request(parent, template->gpio, template->name);
+       if (ret < 0)
+               return ret;
+
        led_dat->cdev.name = template->name;
        led_dat->cdev.default_trigger = template->default_trigger;
        led_dat->gpio = template->gpio;
@@ -126,10 +130,7 @@ static int create_gpio_led(const struct gpio_led *template,
        if (!template->retain_state_suspended)
                led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
 
-       ret = devm_gpio_request_one(parent, template->gpio,
-                                   (led_dat->active_low ^ state) ?
-                                   GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW,
-                                   template->name);
+       ret = gpio_direction_output(led_dat->gpio, led_dat->active_low ^ state);
        if (ret < 0)
                return ret;
 
index ee14662..98cae52 100644 (file)
@@ -47,37 +47,37 @@ static struct ot200_led leds[] = {
        {
                .name = "led_1",
                .port = 0x49,
-               .mask = BIT(7),
+               .mask = BIT(6),
        },
        {
                .name = "led_2",
                .port = 0x49,
-               .mask = BIT(6),
+               .mask = BIT(5),
        },
        {
                .name = "led_3",
                .port = 0x49,
-               .mask = BIT(5),
+               .mask = BIT(4),
        },
        {
                .name = "led_4",
                .port = 0x49,
-               .mask = BIT(4),
+               .mask = BIT(3),
        },
        {
                .name = "led_5",
                .port = 0x49,
-               .mask = BIT(3),
+               .mask = BIT(2),
        },
        {
                .name = "led_6",
                .port = 0x49,
-               .mask = BIT(2),
+               .mask = BIT(1),
        },
        {
                .name = "led_7",
                .port = 0x49,
-               .mask = BIT(1),
+               .mask = BIT(0),
        }
 };
 
index 699187a..5b9ac32 100644 (file)
@@ -1002,6 +1002,7 @@ void guest_set_pgd(struct lguest *lg, unsigned long gpgdir, u32 idx)
                        kill_guest(&lg->cpus[0],
                                   "Cannot populate switcher mapping");
                }
+               lg->pgdirs[pgdir].last_host_cpu = -1;
        }
 }
 
index 05c220d..f950c9d 100644 (file)
@@ -1,7 +1,6 @@
 
 config BCACHE
        tristate "Block device as cache"
-       select CLOSURES
        ---help---
        Allows a block device to be used as cache for other devices; uses
        a btree for indexing and the layout is optimized for SSDs.
index 340146d..d3e15b4 100644 (file)
@@ -1241,7 +1241,7 @@ void bch_cache_set_stop(struct cache_set *);
 struct cache_set *bch_cache_set_alloc(struct cache_sb *);
 void bch_btree_cache_free(struct cache_set *);
 int bch_btree_cache_alloc(struct cache_set *);
-void bch_writeback_init_cached_dev(struct cached_dev *);
+void bch_cached_dev_writeback_init(struct cached_dev *);
 void bch_moving_init_cache_set(struct cache_set *);
 
 void bch_cache_allocator_exit(struct cache *ca);
index 64e6794..b8730e7 100644 (file)
@@ -93,24 +93,6 @@ static struct attribute *bch_stats_files[] = {
 };
 static KTYPE(bch_stats);
 
-static void scale_accounting(unsigned long data);
-
-void bch_cache_accounting_init(struct cache_accounting *acc,
-                              struct closure *parent)
-{
-       kobject_init(&acc->total.kobj,          &bch_stats_ktype);
-       kobject_init(&acc->five_minute.kobj,    &bch_stats_ktype);
-       kobject_init(&acc->hour.kobj,           &bch_stats_ktype);
-       kobject_init(&acc->day.kobj,            &bch_stats_ktype);
-
-       closure_init(&acc->cl, parent);
-       init_timer(&acc->timer);
-       acc->timer.expires      = jiffies + accounting_delay;
-       acc->timer.data         = (unsigned long) acc;
-       acc->timer.function     = scale_accounting;
-       add_timer(&acc->timer);
-}
-
 int bch_cache_accounting_add_kobjs(struct cache_accounting *acc,
                                   struct kobject *parent)
 {
@@ -244,3 +226,19 @@ void bch_mark_sectors_bypassed(struct search *s, int sectors)
        atomic_add(sectors, &dc->accounting.collector.sectors_bypassed);
        atomic_add(sectors, &s->op.c->accounting.collector.sectors_bypassed);
 }
+
+void bch_cache_accounting_init(struct cache_accounting *acc,
+                              struct closure *parent)
+{
+       kobject_init(&acc->total.kobj,          &bch_stats_ktype);
+       kobject_init(&acc->five_minute.kobj,    &bch_stats_ktype);
+       kobject_init(&acc->hour.kobj,           &bch_stats_ktype);
+       kobject_init(&acc->day.kobj,            &bch_stats_ktype);
+
+       closure_init(&acc->cl, parent);
+       init_timer(&acc->timer);
+       acc->timer.expires      = jiffies + accounting_delay;
+       acc->timer.data         = (unsigned long) acc;
+       acc->timer.function     = scale_accounting;
+       add_timer(&acc->timer);
+}
index c8046bc..f88e2b6 100644 (file)
@@ -634,11 +634,10 @@ static int open_dev(struct block_device *b, fmode_t mode)
        return 0;
 }
 
-static int release_dev(struct gendisk *b, fmode_t mode)
+static void release_dev(struct gendisk *b, fmode_t mode)
 {
        struct bcache_device *d = b->private_data;
        closure_put(&d->cl);
-       return 0;
 }
 
 static int ioctl_dev(struct block_device *b, fmode_t mode,
@@ -732,8 +731,7 @@ static void bcache_device_free(struct bcache_device *d)
 
        if (d->c)
                bcache_device_detach(d);
-
-       if (d->disk)
+       if (d->disk && d->disk->flags & GENHD_FL_UP)
                del_gendisk(d->disk);
        if (d->disk && d->disk->queue)
                blk_cleanup_queue(d->disk->queue);
@@ -756,12 +754,9 @@ static int bcache_device_init(struct bcache_device *d, unsigned block_size)
        if (!(d->bio_split = bioset_create(4, offsetof(struct bbio, bio))) ||
            !(d->unaligned_bvec = mempool_create_kmalloc_pool(1,
                                sizeof(struct bio_vec) * BIO_MAX_PAGES)) ||
-           bio_split_pool_init(&d->bio_split_hook))
-
-               return -ENOMEM;
-
-       d->disk = alloc_disk(1);
-       if (!d->disk)
+           bio_split_pool_init(&d->bio_split_hook) ||
+           !(d->disk = alloc_disk(1)) ||
+           !(q = blk_alloc_queue(GFP_KERNEL)))
                return -ENOMEM;
 
        snprintf(d->disk->disk_name, DISK_NAME_LEN, "bcache%i", bcache_minor);
@@ -771,10 +766,6 @@ static int bcache_device_init(struct bcache_device *d, unsigned block_size)
        d->disk->fops           = &bcache_ops;
        d->disk->private_data   = d;
 
-       q = blk_alloc_queue(GFP_KERNEL);
-       if (!q)
-               return -ENOMEM;
-
        blk_queue_make_request(q, NULL);
        d->disk->queue                  = q;
        q->queuedata                    = d;
@@ -999,14 +990,17 @@ static void cached_dev_free(struct closure *cl)
 
        mutex_lock(&bch_register_lock);
 
-       bd_unlink_disk_holder(dc->bdev, dc->disk.disk);
+       if (atomic_read(&dc->running))
+               bd_unlink_disk_holder(dc->bdev, dc->disk.disk);
        bcache_device_free(&dc->disk);
        list_del(&dc->list);
 
        mutex_unlock(&bch_register_lock);
 
        if (!IS_ERR_OR_NULL(dc->bdev)) {
-               blk_sync_queue(bdev_get_queue(dc->bdev));
+               if (dc->bdev->bd_disk)
+                       blk_sync_queue(bdev_get_queue(dc->bdev));
+
                blkdev_put(dc->bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
        }
 
@@ -1028,73 +1022,67 @@ static void cached_dev_flush(struct closure *cl)
 
 static int cached_dev_init(struct cached_dev *dc, unsigned block_size)
 {
-       int err;
+       int ret;
        struct io *io;
-
-       closure_init(&dc->disk.cl, NULL);
-       set_closure_fn(&dc->disk.cl, cached_dev_flush, system_wq);
+       struct request_queue *q = bdev_get_queue(dc->bdev);
 
        __module_get(THIS_MODULE);
        INIT_LIST_HEAD(&dc->list);
+       closure_init(&dc->disk.cl, NULL);
+       set_closure_fn(&dc->disk.cl, cached_dev_flush, system_wq);
        kobject_init(&dc->disk.kobj, &bch_cached_dev_ktype);
-
-       bch_cache_accounting_init(&dc->accounting, &dc->disk.cl);
-
-       err = bcache_device_init(&dc->disk, block_size);
-       if (err)
-               goto err;
-
-       spin_lock_init(&dc->io_lock);
-       closure_init_unlocked(&dc->sb_write);
        INIT_WORK(&dc->detach, cached_dev_detach_finish);
+       closure_init_unlocked(&dc->sb_write);
+       INIT_LIST_HEAD(&dc->io_lru);
+       spin_lock_init(&dc->io_lock);
+       bch_cache_accounting_init(&dc->accounting, &dc->disk.cl);
 
        dc->sequential_merge            = true;
        dc->sequential_cutoff           = 4 << 20;
 
-       INIT_LIST_HEAD(&dc->io_lru);
-       dc->sb_bio.bi_max_vecs  = 1;
-       dc->sb_bio.bi_io_vec    = dc->sb_bio.bi_inline_vecs;
-
        for (io = dc->io; io < dc->io + RECENT_IO; io++) {
                list_add(&io->lru, &dc->io_lru);
                hlist_add_head(&io->hash, dc->io_hash + RECENT_IO);
        }
 
-       bch_writeback_init_cached_dev(dc);
+       ret = bcache_device_init(&dc->disk, block_size);
+       if (ret)
+               return ret;
+
+       set_capacity(dc->disk.disk,
+                    dc->bdev->bd_part->nr_sects - dc->sb.data_offset);
+
+       dc->disk.disk->queue->backing_dev_info.ra_pages =
+               max(dc->disk.disk->queue->backing_dev_info.ra_pages,
+                   q->backing_dev_info.ra_pages);
+
+       bch_cached_dev_request_init(dc);
+       bch_cached_dev_writeback_init(dc);
        return 0;
-err:
-       bcache_device_stop(&dc->disk);
-       return err;
 }
 
 /* Cached device - bcache superblock */
 
-static const char *register_bdev(struct cache_sb *sb, struct page *sb_page,
+static void register_bdev(struct cache_sb *sb, struct page *sb_page,
                                 struct block_device *bdev,
                                 struct cached_dev *dc)
 {
        char name[BDEVNAME_SIZE];
        const char *err = "cannot allocate memory";
-       struct gendisk *g;
        struct cache_set *c;
 
-       if (!dc || cached_dev_init(dc, sb->block_size << 9) != 0)
-               return err;
-
        memcpy(&dc->sb, sb, sizeof(struct cache_sb));
-       dc->sb_bio.bi_io_vec[0].bv_page = sb_page;
        dc->bdev = bdev;
        dc->bdev->bd_holder = dc;
 
-       g = dc->disk.disk;
-
-       set_capacity(g, dc->bdev->bd_part->nr_sects - dc->sb.data_offset);
-
-       g->queue->backing_dev_info.ra_pages =
-               max(g->queue->backing_dev_info.ra_pages,
-                   bdev->bd_queue->backing_dev_info.ra_pages);
+       bio_init(&dc->sb_bio);
+       dc->sb_bio.bi_max_vecs  = 1;
+       dc->sb_bio.bi_io_vec    = dc->sb_bio.bi_inline_vecs;
+       dc->sb_bio.bi_io_vec[0].bv_page = sb_page;
+       get_page(sb_page);
 
-       bch_cached_dev_request_init(dc);
+       if (cached_dev_init(dc, sb->block_size << 9))
+               goto err;
 
        err = "error creating kobject";
        if (kobject_add(&dc->disk.kobj, &part_to_dev(bdev->bd_part)->kobj,
@@ -1103,6 +1091,8 @@ static const char *register_bdev(struct cache_sb *sb, struct page *sb_page,
        if (bch_cache_accounting_add_kobjs(&dc->accounting, &dc->disk.kobj))
                goto err;
 
+       pr_info("registered backing device %s", bdevname(bdev, name));
+
        list_add(&dc->list, &uncached_devices);
        list_for_each_entry(c, &bch_cache_sets, list)
                bch_cached_dev_attach(dc, c);
@@ -1111,15 +1101,10 @@ static const char *register_bdev(struct cache_sb *sb, struct page *sb_page,
            BDEV_STATE(&dc->sb) == BDEV_STATE_STALE)
                bch_cached_dev_run(dc);
 
-       return NULL;
+       return;
 err:
-       kobject_put(&dc->disk.kobj);
        pr_notice("error opening %s: %s", bdevname(bdev, name), err);
-       /*
-        * Return NULL instead of an error because kobject_put() cleans
-        * everything up
-        */
-       return NULL;
+       bcache_device_stop(&dc->disk);
 }
 
 /* Flash only volumes */
@@ -1717,20 +1702,11 @@ static int cache_alloc(struct cache_sb *sb, struct cache *ca)
        size_t free;
        struct bucket *b;
 
-       if (!ca)
-               return -ENOMEM;
-
        __module_get(THIS_MODULE);
        kobject_init(&ca->kobj, &bch_cache_ktype);
 
-       memcpy(&ca->sb, sb, sizeof(struct cache_sb));
-
        INIT_LIST_HEAD(&ca->discards);
 
-       bio_init(&ca->sb_bio);
-       ca->sb_bio.bi_max_vecs  = 1;
-       ca->sb_bio.bi_io_vec    = ca->sb_bio.bi_inline_vecs;
-
        bio_init(&ca->journal.bio);
        ca->journal.bio.bi_max_vecs = 8;
        ca->journal.bio.bi_io_vec = ca->journal.bio.bi_inline_vecs;
@@ -1742,18 +1718,17 @@ static int cache_alloc(struct cache_sb *sb, struct cache *ca)
            !init_fifo(&ca->free_inc,   free << 2, GFP_KERNEL) ||
            !init_fifo(&ca->unused,     free << 2, GFP_KERNEL) ||
            !init_heap(&ca->heap,       free << 3, GFP_KERNEL) ||
-           !(ca->buckets       = vmalloc(sizeof(struct bucket) *
+           !(ca->buckets       = vzalloc(sizeof(struct bucket) *
                                          ca->sb.nbuckets)) ||
            !(ca->prio_buckets  = kzalloc(sizeof(uint64_t) * prio_buckets(ca) *
                                          2, GFP_KERNEL)) ||
            !(ca->disk_buckets  = alloc_bucket_pages(GFP_KERNEL, ca)) ||
            !(ca->alloc_workqueue = alloc_workqueue("bch_allocator", 0, 1)) ||
            bio_split_pool_init(&ca->bio_split_hook))
-               goto err;
+               return -ENOMEM;
 
        ca->prio_last_buckets = ca->prio_buckets + prio_buckets(ca);
 
-       memset(ca->buckets, 0, ca->sb.nbuckets * sizeof(struct bucket));
        for_each_bucket(b, ca)
                atomic_set(&b->pin, 0);
 
@@ -1766,22 +1741,28 @@ err:
        return -ENOMEM;
 }
 
-static const char *register_cache(struct cache_sb *sb, struct page *sb_page,
+static void register_cache(struct cache_sb *sb, struct page *sb_page,
                                  struct block_device *bdev, struct cache *ca)
 {
        char name[BDEVNAME_SIZE];
        const char *err = "cannot allocate memory";
 
-       if (cache_alloc(sb, ca) != 0)
-               return err;
-
-       ca->sb_bio.bi_io_vec[0].bv_page = sb_page;
+       memcpy(&ca->sb, sb, sizeof(struct cache_sb));
        ca->bdev = bdev;
        ca->bdev->bd_holder = ca;
 
+       bio_init(&ca->sb_bio);
+       ca->sb_bio.bi_max_vecs  = 1;
+       ca->sb_bio.bi_io_vec    = ca->sb_bio.bi_inline_vecs;
+       ca->sb_bio.bi_io_vec[0].bv_page = sb_page;
+       get_page(sb_page);
+
        if (blk_queue_discard(bdev_get_queue(ca->bdev)))
                ca->discard = CACHE_DISCARD(&ca->sb);
 
+       if (cache_alloc(sb, ca) != 0)
+               goto err;
+
        err = "error creating kobject";
        if (kobject_add(&ca->kobj, &part_to_dev(bdev->bd_part)->kobj, "bcache"))
                goto err;
@@ -1791,15 +1772,10 @@ static const char *register_cache(struct cache_sb *sb, struct page *sb_page,
                goto err;
 
        pr_info("registered cache device %s", bdevname(bdev, name));
-
-       return NULL;
+       return;
 err:
+       pr_notice("error opening %s: %s", bdevname(bdev, name), err);
        kobject_put(&ca->kobj);
-       pr_info("error opening %s: %s", bdevname(bdev, name), err);
-       /* Return NULL instead of an error because kobject_put() cleans
-        * everything up
-        */
-       return NULL;
 }
 
 /* Global interfaces/init */
@@ -1833,12 +1809,15 @@ static ssize_t register_bcache(struct kobject *k, struct kobj_attribute *attr,
        bdev = blkdev_get_by_path(strim(path),
                                  FMODE_READ|FMODE_WRITE|FMODE_EXCL,
                                  sb);
-       if (bdev == ERR_PTR(-EBUSY))
-               err = "device busy";
-
-       if (IS_ERR(bdev) ||
-           set_blocksize(bdev, 4096))
+       if (IS_ERR(bdev)) {
+               if (bdev == ERR_PTR(-EBUSY))
+                       err = "device busy";
                goto err;
+       }
+
+       err = "failed to set blocksize";
+       if (set_blocksize(bdev, 4096))
+               goto err_close;
 
        err = read_super(sb, bdev, &sb_page);
        if (err)
@@ -1846,33 +1825,33 @@ static ssize_t register_bcache(struct kobject *k, struct kobj_attribute *attr,
 
        if (SB_IS_BDEV(sb)) {
                struct cached_dev *dc = kzalloc(sizeof(*dc), GFP_KERNEL);
+               if (!dc)
+                       goto err_close;
 
-               err = register_bdev(sb, sb_page, bdev, dc);
+               register_bdev(sb, sb_page, bdev, dc);
        } else {
                struct cache *ca = kzalloc(sizeof(*ca), GFP_KERNEL);
+               if (!ca)
+                       goto err_close;
 
-               err = register_cache(sb, sb_page, bdev, ca);
+               register_cache(sb, sb_page, bdev, ca);
        }
-
-       if (err) {
-               /* register_(bdev|cache) will only return an error if they
-                * didn't get far enough to create the kobject - if they did,
-                * the kobject destructor will do this cleanup.
-                */
+out:
+       if (sb_page)
                put_page(sb_page);
-err_close:
-               blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
-err:
-               if (attr != &ksysfs_register_quiet)
-                       pr_info("error opening %s: %s", path, err);
-               ret = -EINVAL;
-       }
-
        kfree(sb);
        kfree(path);
        mutex_unlock(&bch_register_lock);
        module_put(THIS_MODULE);
        return ret;
+
+err_close:
+       blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
+err:
+       if (attr != &ksysfs_register_quiet)
+               pr_info("error opening %s: %s", path, err);
+       ret = -EINVAL;
+       goto out;
 }
 
 static int bcache_reboot(struct notifier_block *n, unsigned long code, void *x)
index 93e7e31..2714ed3 100644 (file)
@@ -375,7 +375,7 @@ err:
        refill_dirty(cl);
 }
 
-void bch_writeback_init_cached_dev(struct cached_dev *dc)
+void bch_cached_dev_writeback_init(struct cached_dev *dc)
 {
        closure_init_unlocked(&dc->writeback);
        init_rwsem(&dc->writeback_lock);
index c608313..0387e05 100644 (file)
@@ -319,6 +319,9 @@ static void __cache_size_refresh(void)
 static void *alloc_buffer_data(struct dm_bufio_client *c, gfp_t gfp_mask,
                               enum data_mode *data_mode)
 {
+       unsigned noio_flag;
+       void *ptr;
+
        if (c->block_size <= DM_BUFIO_BLOCK_SIZE_SLAB_LIMIT) {
                *data_mode = DATA_MODE_SLAB;
                return kmem_cache_alloc(DM_BUFIO_CACHE(c), gfp_mask);
@@ -332,7 +335,26 @@ static void *alloc_buffer_data(struct dm_bufio_client *c, gfp_t gfp_mask,
        }
 
        *data_mode = DATA_MODE_VMALLOC;
-       return __vmalloc(c->block_size, gfp_mask, PAGE_KERNEL);
+
+       /*
+        * __vmalloc allocates the data pages and auxiliary structures with
+        * gfp_flags that were specified, but pagetables are always allocated
+        * with GFP_KERNEL, no matter what was specified as gfp_mask.
+        *
+        * Consequently, we must set per-process flag PF_MEMALLOC_NOIO so that
+        * all allocations done by this process (including pagetables) are done
+        * as if GFP_NOIO was specified.
+        */
+
+       if (gfp_mask & __GFP_NORETRY)
+               noio_flag = memalloc_noio_save();
+
+       ptr = __vmalloc(c->block_size, gfp_mask, PAGE_KERNEL);
+
+       if (gfp_mask & __GFP_NORETRY)
+               memalloc_noio_restore(noio_flag);
+
+       return ptr;
 }
 
 /*
index 83e995f..1af7255 100644 (file)
@@ -1044,7 +1044,7 @@ void dm_cache_metadata_get_stats(struct dm_cache_metadata *cmd,
                                 struct dm_cache_statistics *stats)
 {
        down_read(&cmd->root_lock);
-       memcpy(stats, &cmd->stats, sizeof(*stats));
+       *stats = cmd->stats;
        up_read(&cmd->root_lock);
 }
 
@@ -1052,7 +1052,7 @@ void dm_cache_metadata_set_stats(struct dm_cache_metadata *cmd,
                                 struct dm_cache_statistics *stats)
 {
        down_write(&cmd->root_lock);
-       memcpy(&cmd->stats, stats, sizeof(*stats));
+       cmd->stats = *stats;
        up_write(&cmd->root_lock);
 }
 
index 558bdfd..33369ca 100644 (file)
@@ -130,8 +130,8 @@ struct dm_cache_policy {
         *
         * Must not block.
         *
-        * Returns 1 iff in cache, 0 iff not, < 0 on error (-EWOULDBLOCK
-        * would be typical).
+        * Returns 0 if in cache, -ENOENT if not, < 0 for other errors
+        * (-EWOULDBLOCK would be typical).
         */
        int (*lookup)(struct dm_cache_policy *p, dm_oblock_t oblock, dm_cblock_t *cblock);
 
index 1074409..df44b60 100644 (file)
@@ -205,7 +205,7 @@ struct per_bio_data {
        /*
         * writethrough fields.  These MUST remain at the end of this
         * structure and the 'cache' member must be the first as it
-        * is used to determine the offsetof the writethrough fields.
+        * is used to determine the offset of the writethrough fields.
         */
        struct cache *cache;
        dm_cblock_t cblock;
@@ -393,7 +393,7 @@ static int get_cell(struct cache *cache,
        return r;
 }
 
- /*----------------------------------------------------------------*/
+/*----------------------------------------------------------------*/
 
 static bool is_dirty(struct cache *cache, dm_cblock_t b)
 {
@@ -419,6 +419,7 @@ static void clear_dirty(struct cache *cache, dm_oblock_t oblock, dm_cblock_t cbl
 }
 
 /*----------------------------------------------------------------*/
+
 static bool block_size_is_power_of_two(struct cache *cache)
 {
        return cache->sectors_per_block_shift >= 0;
@@ -667,7 +668,7 @@ static void writethrough_endio(struct bio *bio, int err)
 
        /*
         * We can't issue this bio directly, since we're in interrupt
-        * context.  So it get's put on a bio list for processing by the
+        * context.  So it gets put on a bio list for processing by the
         * worker thread.
         */
        defer_writethrough_bio(pb->cache, bio);
@@ -1445,6 +1446,7 @@ static void do_worker(struct work_struct *ws)
 static void do_waker(struct work_struct *ws)
 {
        struct cache *cache = container_of(to_delayed_work(ws), struct cache, waker);
+       policy_tick(cache->policy);
        wake_worker(cache);
        queue_delayed_work(cache->wq, &cache->waker, COMMIT_PERIOD);
 }
@@ -1809,7 +1811,37 @@ static int parse_cache_args(struct cache_args *ca, int argc, char **argv,
 
 static struct kmem_cache *migration_cache;
 
-static int set_config_values(struct dm_cache_policy *p, int argc, const char **argv)
+#define NOT_CORE_OPTION 1
+
+static int process_config_option(struct cache *cache, const char *key, const char *value)
+{
+       unsigned long tmp;
+
+       if (!strcasecmp(key, "migration_threshold")) {
+               if (kstrtoul(value, 10, &tmp))
+                       return -EINVAL;
+
+               cache->migration_threshold = tmp;
+               return 0;
+       }
+
+       return NOT_CORE_OPTION;
+}
+
+static int set_config_value(struct cache *cache, const char *key, const char *value)
+{
+       int r = process_config_option(cache, key, value);
+
+       if (r == NOT_CORE_OPTION)
+               r = policy_set_config_value(cache->policy, key, value);
+
+       if (r)
+               DMWARN("bad config value for %s: %s", key, value);
+
+       return r;
+}
+
+static int set_config_values(struct cache *cache, int argc, const char **argv)
 {
        int r = 0;
 
@@ -1819,12 +1851,9 @@ static int set_config_values(struct dm_cache_policy *p, int argc, const char **a
        }
 
        while (argc) {
-               r = policy_set_config_value(p, argv[0], argv[1]);
-               if (r) {
-                       DMWARN("policy_set_config_value failed: key = '%s', value = '%s'",
-                              argv[0], argv[1]);
-                       return r;
-               }
+               r = set_config_value(cache, argv[0], argv[1]);
+               if (r)
+                       break;
 
                argc -= 2;
                argv += 2;
@@ -1836,8 +1865,6 @@ static int set_config_values(struct dm_cache_policy *p, int argc, const char **a
 static int create_cache_policy(struct cache *cache, struct cache_args *ca,
                               char **error)
 {
-       int r;
-
        cache->policy = dm_cache_policy_create(ca->policy_name,
                                               cache->cache_size,
                                               cache->origin_sectors,
@@ -1847,14 +1874,7 @@ static int create_cache_policy(struct cache *cache, struct cache_args *ca,
                return -ENOMEM;
        }
 
-       r = set_config_values(cache->policy, ca->policy_argc, ca->policy_argv);
-       if (r) {
-               *error = "Error setting cache policy's config values";
-               dm_cache_policy_destroy(cache->policy);
-               cache->policy = NULL;
-       }
-
-       return r;
+       return 0;
 }
 
 /*
@@ -1886,7 +1906,7 @@ static sector_t calculate_discard_block_size(sector_t cache_block_size,
        return discard_block_size;
 }
 
-#define DEFAULT_MIGRATION_THRESHOLD (2048 * 100)
+#define DEFAULT_MIGRATION_THRESHOLD 2048
 
 static int cache_create(struct cache_args *ca, struct cache **result)
 {
@@ -1911,7 +1931,7 @@ static int cache_create(struct cache_args *ca, struct cache **result)
        ti->discards_supported = true;
        ti->discard_zeroes_data_unsupported = true;
 
-       memcpy(&cache->features, &ca->features, sizeof(cache->features));
+       cache->features = ca->features;
        ti->per_bio_data_size = get_per_bio_data_size(cache);
 
        cache->callbacks.congested_fn = cache_is_congested;
@@ -1948,7 +1968,15 @@ static int cache_create(struct cache_args *ca, struct cache **result)
        r = create_cache_policy(cache, ca, error);
        if (r)
                goto bad;
+
        cache->policy_nr_args = ca->policy_argc;
+       cache->migration_threshold = DEFAULT_MIGRATION_THRESHOLD;
+
+       r = set_config_values(cache, ca->policy_argc, ca->policy_argv);
+       if (r) {
+               *error = "Error setting cache policy's config values";
+               goto bad;
+       }
 
        cmd = dm_cache_metadata_open(cache->metadata_dev->bdev,
                                     ca->block_size, may_format,
@@ -1967,10 +1995,10 @@ static int cache_create(struct cache_args *ca, struct cache **result)
        INIT_LIST_HEAD(&cache->quiesced_migrations);
        INIT_LIST_HEAD(&cache->completed_migrations);
        INIT_LIST_HEAD(&cache->need_commit_migrations);
-       cache->migration_threshold = DEFAULT_MIGRATION_THRESHOLD;
        atomic_set(&cache->nr_migrations, 0);
        init_waitqueue_head(&cache->migration_wait);
 
+       r = -ENOMEM;
        cache->nr_dirty = 0;
        cache->dirty_bitset = alloc_bitset(from_cblock(cache->cache_size));
        if (!cache->dirty_bitset) {
@@ -2517,23 +2545,6 @@ err:
        DMEMIT("Error");
 }
 
-#define NOT_CORE_OPTION 1
-
-static int process_config_option(struct cache *cache, char **argv)
-{
-       unsigned long tmp;
-
-       if (!strcasecmp(argv[0], "migration_threshold")) {
-               if (kstrtoul(argv[1], 10, &tmp))
-                       return -EINVAL;
-
-               cache->migration_threshold = tmp;
-               return 0;
-       }
-
-       return NOT_CORE_OPTION;
-}
-
 /*
  * Supports <key> <value>.
  *
@@ -2541,17 +2552,12 @@ static int process_config_option(struct cache *cache, char **argv)
  */
 static int cache_message(struct dm_target *ti, unsigned argc, char **argv)
 {
-       int r;
        struct cache *cache = ti->private;
 
        if (argc != 2)
                return -EINVAL;
 
-       r = process_config_option(cache, argv);
-       if (r == NOT_CORE_OPTION)
-               return policy_set_config_value(cache->policy, argv[0], argv[1]);
-
-       return r;
+       return set_config_value(cache, argv[0], argv[1]);
 }
 
 static int cache_iterate_devices(struct dm_target *ti,
@@ -2609,7 +2615,7 @@ static void cache_io_hints(struct dm_target *ti, struct queue_limits *limits)
 
 static struct target_type cache_target = {
        .name = "cache",
-       .version = {1, 1, 0},
+       .version = {1, 1, 1},
        .module = THIS_MODULE,
        .ctr = cache_ctr,
        .dtr = cache_dtr,
index 51bb816..bdf26f5 100644 (file)
@@ -907,6 +907,7 @@ static int multipath_ctr(struct dm_target *ti, unsigned int argc,
 
        ti->num_flush_bios = 1;
        ti->num_discard_bios = 1;
+       ti->num_write_same_bios = 1;
 
        return 0;
 
index c0e0702..c434e5a 100644 (file)
@@ -1121,6 +1121,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
        s->pending_pool = mempool_create_slab_pool(MIN_IOS, pending_cache);
        if (!s->pending_pool) {
                ti->error = "Could not allocate mempool for pending exceptions";
+               r = -ENOMEM;
                goto bad_pending_pool;
        }
 
index ea5e878..d907ca6 100644 (file)
@@ -94,7 +94,7 @@ static int get_stripe(struct dm_target *ti, struct stripe_c *sc,
 static int stripe_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 {
        struct stripe_c *sc;
-       sector_t width;
+       sector_t width, tmp_len;
        uint32_t stripes;
        uint32_t chunk_size;
        int r;
@@ -116,15 +116,16 @@ static int stripe_ctr(struct dm_target *ti, unsigned int argc, char **argv)
        }
 
        width = ti->len;
-       if (sector_div(width, chunk_size)) {
+       if (sector_div(width, stripes)) {
                ti->error = "Target length not divisible by "
-                   "chunk size";
+                   "number of stripes";
                return -EINVAL;
        }
 
-       if (sector_div(width, stripes)) {
+       tmp_len = width;
+       if (sector_div(tmp_len, chunk_size)) {
                ti->error = "Target length not divisible by "
-                   "number of stripes";
+                   "chunk size";
                return -EINVAL;
        }
 
index e50dad0..1ff252a 100644 (file)
@@ -1442,7 +1442,7 @@ static bool dm_table_supports_write_same(struct dm_table *t)
                        return false;
 
                if (!ti->type->iterate_devices ||
-                   !ti->type->iterate_devices(ti, device_not_write_same_capable, NULL))
+                   ti->type->iterate_devices(ti, device_not_write_same_capable, NULL))
                        return false;
        }
 
index 00cee02..60bce43 100644 (file)
@@ -1645,12 +1645,12 @@ int dm_thin_get_highest_mapped_block(struct dm_thin_device *td,
        return r;
 }
 
-static int __resize_data_dev(struct dm_pool_metadata *pmd, dm_block_t new_count)
+static int __resize_space_map(struct dm_space_map *sm, dm_block_t new_count)
 {
        int r;
        dm_block_t old_count;
 
-       r = dm_sm_get_nr_blocks(pmd->data_sm, &old_count);
+       r = dm_sm_get_nr_blocks(sm, &old_count);
        if (r)
                return r;
 
@@ -1658,11 +1658,11 @@ static int __resize_data_dev(struct dm_pool_metadata *pmd, dm_block_t new_count)
                return 0;
 
        if (new_count < old_count) {
-               DMERR("cannot reduce size of data device");
+               DMERR("cannot reduce size of space map");
                return -EINVAL;
        }
 
-       return dm_sm_extend(pmd->data_sm, new_count - old_count);
+       return dm_sm_extend(sm, new_count - old_count);
 }
 
 int dm_pool_resize_data_dev(struct dm_pool_metadata *pmd, dm_block_t new_count)
@@ -1671,7 +1671,19 @@ int dm_pool_resize_data_dev(struct dm_pool_metadata *pmd, dm_block_t new_count)
 
        down_write(&pmd->root_lock);
        if (!pmd->fail_io)
-               r = __resize_data_dev(pmd, new_count);
+               r = __resize_space_map(pmd->data_sm, new_count);
+       up_write(&pmd->root_lock);
+
+       return r;
+}
+
+int dm_pool_resize_metadata_dev(struct dm_pool_metadata *pmd, dm_block_t new_count)
+{
+       int r = -EINVAL;
+
+       down_write(&pmd->root_lock);
+       if (!pmd->fail_io)
+               r = __resize_space_map(pmd->metadata_sm, new_count);
        up_write(&pmd->root_lock);
 
        return r;
@@ -1684,3 +1696,17 @@ void dm_pool_metadata_read_only(struct dm_pool_metadata *pmd)
        dm_bm_set_read_only(pmd->bm);
        up_write(&pmd->root_lock);
 }
+
+int dm_pool_register_metadata_threshold(struct dm_pool_metadata *pmd,
+                                       dm_block_t threshold,
+                                       dm_sm_threshold_fn fn,
+                                       void *context)
+{
+       int r;
+
+       down_write(&pmd->root_lock);
+       r = dm_sm_register_threshold_callback(pmd->metadata_sm, threshold, fn, context);
+       up_write(&pmd->root_lock);
+
+       return r;
+}
index 0cecc37..845ebbe 100644 (file)
@@ -8,6 +8,7 @@
 #define DM_THIN_METADATA_H
 
 #include "persistent-data/dm-block-manager.h"
+#include "persistent-data/dm-space-map.h"
 
 #define THIN_METADATA_BLOCK_SIZE 4096
 
@@ -185,6 +186,7 @@ int dm_pool_get_data_dev_size(struct dm_pool_metadata *pmd, dm_block_t *result);
  * blocks would be lost.
  */
 int dm_pool_resize_data_dev(struct dm_pool_metadata *pmd, dm_block_t new_size);
+int dm_pool_resize_metadata_dev(struct dm_pool_metadata *pmd, dm_block_t new_size);
 
 /*
  * Flicks the underlying block manager into read only mode, so you know
@@ -192,6 +194,11 @@ int dm_pool_resize_data_dev(struct dm_pool_metadata *pmd, dm_block_t new_size);
  */
 void dm_pool_metadata_read_only(struct dm_pool_metadata *pmd);
 
+int dm_pool_register_metadata_threshold(struct dm_pool_metadata *pmd,
+                                       dm_block_t threshold,
+                                       dm_sm_threshold_fn fn,
+                                       void *context);
+
 /*----------------------------------------------------------------*/
 
 #endif
index 004ad16..88f2f80 100644 (file)
@@ -922,7 +922,7 @@ static int alloc_data_block(struct thin_c *tc, dm_block_t *result)
                return r;
 
        if (free_blocks <= pool->low_water_blocks && !pool->low_water_triggered) {
-               DMWARN("%s: reached low water mark, sending event.",
+               DMWARN("%s: reached low water mark for data device: sending event.",
                       dm_device_name(pool->pool_md));
                spin_lock_irqsave(&pool->lock, flags);
                pool->low_water_triggered = 1;
@@ -1281,6 +1281,10 @@ static void process_bio_fail(struct thin_c *tc, struct bio *bio)
        bio_io_error(bio);
 }
 
+/*
+ * FIXME: should we also commit due to size of transaction, measured in
+ * metadata blocks?
+ */
 static int need_commit_due_to_time(struct pool *pool)
 {
        return jiffies < pool->last_commit_jiffies ||
@@ -1909,6 +1913,56 @@ static int parse_pool_features(struct dm_arg_set *as, struct pool_features *pf,
        return r;
 }
 
+static void metadata_low_callback(void *context)
+{
+       struct pool *pool = context;
+
+       DMWARN("%s: reached low water mark for metadata device: sending event.",
+              dm_device_name(pool->pool_md));
+
+       dm_table_event(pool->ti->table);
+}
+
+static sector_t get_metadata_dev_size(struct block_device *bdev)
+{
+       sector_t metadata_dev_size = i_size_read(bdev->bd_inode) >> SECTOR_SHIFT;
+       char buffer[BDEVNAME_SIZE];
+
+       if (metadata_dev_size > THIN_METADATA_MAX_SECTORS_WARNING) {
+               DMWARN("Metadata device %s is larger than %u sectors: excess space will not be used.",
+                      bdevname(bdev, buffer), THIN_METADATA_MAX_SECTORS);
+               metadata_dev_size = THIN_METADATA_MAX_SECTORS_WARNING;
+       }
+
+       return metadata_dev_size;
+}
+
+static dm_block_t get_metadata_dev_size_in_blocks(struct block_device *bdev)
+{
+       sector_t metadata_dev_size = get_metadata_dev_size(bdev);
+
+       sector_div(metadata_dev_size, THIN_METADATA_BLOCK_SIZE >> SECTOR_SHIFT);
+
+       return metadata_dev_size;
+}
+
+/*
+ * When a metadata threshold is crossed a dm event is triggered, and
+ * userland should respond by growing the metadata device.  We could let
+ * userland set the threshold, like we do with the data threshold, but I'm
+ * not sure they know enough to do this well.
+ */
+static dm_block_t calc_metadata_threshold(struct pool_c *pt)
+{
+       /*
+        * 4M is ample for all ops with the possible exception of thin
+        * device deletion which is harmless if it fails (just retry the
+        * delete after you've grown the device).
+        */
+       dm_block_t quarter = get_metadata_dev_size_in_blocks(pt->metadata_dev->bdev) / 4;
+       return min((dm_block_t)1024ULL /* 4M */, quarter);
+}
+
 /*
  * thin-pool <metadata dev> <data dev>
  *          <data block size (sectors)>
@@ -1931,8 +1985,7 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
        unsigned long block_size;
        dm_block_t low_water_blocks;
        struct dm_dev *metadata_dev;
-       sector_t metadata_dev_size;
-       char b[BDEVNAME_SIZE];
+       fmode_t metadata_mode;
 
        /*
         * FIXME Remove validation from scope of lock.
@@ -1944,19 +1997,32 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
                r = -EINVAL;
                goto out_unlock;
        }
+
        as.argc = argc;
        as.argv = argv;
 
-       r = dm_get_device(ti, argv[0], FMODE_READ | FMODE_WRITE, &metadata_dev);
+       /*
+        * Set default pool features.
+        */
+       pool_features_init(&pf);
+
+       dm_consume_args(&as, 4);
+       r = parse_pool_features(&as, &pf, ti);
+       if (r)
+               goto out_unlock;
+
+       metadata_mode = FMODE_READ | ((pf.mode == PM_READ_ONLY) ? 0 : FMODE_WRITE);
+       r = dm_get_device(ti, argv[0], metadata_mode, &metadata_dev);
        if (r) {
                ti->error = "Error opening metadata block device";
                goto out_unlock;
        }
 
-       metadata_dev_size = i_size_read(metadata_dev->bdev->bd_inode) >> SECTOR_SHIFT;
-       if (metadata_dev_size > THIN_METADATA_MAX_SECTORS_WARNING)
-               DMWARN("Metadata device %s is larger than %u sectors: excess space will not be used.",
-                      bdevname(metadata_dev->bdev, b), THIN_METADATA_MAX_SECTORS);
+       /*
+        * Run for the side-effect of possibly issuing a warning if the
+        * device is too big.
+        */
+       (void) get_metadata_dev_size(metadata_dev->bdev);
 
        r = dm_get_device(ti, argv[1], FMODE_READ | FMODE_WRITE, &data_dev);
        if (r) {
@@ -1979,16 +2045,6 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
                goto out;
        }
 
-       /*
-        * Set default pool features.
-        */
-       pool_features_init(&pf);
-
-       dm_consume_args(&as, 4);
-       r = parse_pool_features(&as, &pf, ti);
-       if (r)
-               goto out;
-
        pt = kzalloc(sizeof(*pt), GFP_KERNEL);
        if (!pt) {
                r = -ENOMEM;
@@ -2040,6 +2096,13 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
        }
        ti->private = pt;
 
+       r = dm_pool_register_metadata_threshold(pt->pool->pmd,
+                                               calc_metadata_threshold(pt),
+                                               metadata_low_callback,
+                                               pool);
+       if (r)
+               goto out_free_pt;
+
        pt->callbacks.congested_fn = pool_is_congested;
        dm_table_add_target_callbacks(ti->table, &pt->callbacks);
 
@@ -2079,18 +2142,7 @@ static int pool_map(struct dm_target *ti, struct bio *bio)
        return r;
 }
 
-/*
- * Retrieves the number of blocks of the data device from
- * the superblock and compares it to the actual device size,
- * thus resizing the data device in case it has grown.
- *
- * This both copes with opening preallocated data devices in the ctr
- * being followed by a resume
- * -and-
- * calling the resume method individually after userspace has
- * grown the data device in reaction to a table event.
- */
-static int pool_preresume(struct dm_target *ti)
+static int maybe_resize_data_dev(struct dm_target *ti, bool *need_commit)
 {
        int r;
        struct pool_c *pt = ti->private;
@@ -2098,12 +2150,7 @@ static int pool_preresume(struct dm_target *ti)
        sector_t data_size = ti->len;
        dm_block_t sb_data_size;
 
-       /*
-        * Take control of the pool object.
-        */
-       r = bind_control_target(pool, ti);
-       if (r)
-               return r;
+       *need_commit = false;
 
        (void) sector_div(data_size, pool->sectors_per_block);
 
@@ -2114,7 +2161,7 @@ static int pool_preresume(struct dm_target *ti)
        }
 
        if (data_size < sb_data_size) {
-               DMERR("pool target too small, is %llu blocks (expected %llu)",
+               DMERR("pool target (%llu blocks) too small: expected %llu",
                      (unsigned long long)data_size, sb_data_size);
                return -EINVAL;
 
@@ -2122,17 +2169,90 @@ static int pool_preresume(struct dm_target *ti)
                r = dm_pool_resize_data_dev(pool->pmd, data_size);
                if (r) {
                        DMERR("failed to resize data device");
-                       /* FIXME Stricter than necessary: Rollback transaction instead here */
                        set_pool_mode(pool, PM_READ_ONLY);
                        return r;
                }
 
-               (void) commit_or_fallback(pool);
+               *need_commit = true;
        }
 
        return 0;
 }
 
+static int maybe_resize_metadata_dev(struct dm_target *ti, bool *need_commit)
+{
+       int r;
+       struct pool_c *pt = ti->private;
+       struct pool *pool = pt->pool;
+       dm_block_t metadata_dev_size, sb_metadata_dev_size;
+
+       *need_commit = false;
+
+       metadata_dev_size = get_metadata_dev_size_in_blocks(pool->md_dev);
+
+       r = dm_pool_get_metadata_dev_size(pool->pmd, &sb_metadata_dev_size);
+       if (r) {
+               DMERR("failed to retrieve data device size");
+               return r;
+       }
+
+       if (metadata_dev_size < sb_metadata_dev_size) {
+               DMERR("metadata device (%llu blocks) too small: expected %llu",
+                     metadata_dev_size, sb_metadata_dev_size);
+               return -EINVAL;
+
+       } else if (metadata_dev_size > sb_metadata_dev_size) {
+               r = dm_pool_resize_metadata_dev(pool->pmd, metadata_dev_size);
+               if (r) {
+                       DMERR("failed to resize metadata device");
+                       return r;
+               }
+
+               *need_commit = true;
+       }
+
+       return 0;
+}
+
+/*
+ * Retrieves the number of blocks of the data device from
+ * the superblock and compares it to the actual device size,
+ * thus resizing the data device in case it has grown.
+ *
+ * This both copes with opening preallocated data devices in the ctr
+ * being followed by a resume
+ * -and-
+ * calling the resume method individually after userspace has
+ * grown the data device in reaction to a table event.
+ */
+static int pool_preresume(struct dm_target *ti)
+{
+       int r;
+       bool need_commit1, need_commit2;
+       struct pool_c *pt = ti->private;
+       struct pool *pool = pt->pool;
+
+       /*
+        * Take control of the pool object.
+        */
+       r = bind_control_target(pool, ti);
+       if (r)
+               return r;
+
+       r = maybe_resize_data_dev(ti, &need_commit1);
+       if (r)
+               return r;
+
+       r = maybe_resize_metadata_dev(ti, &need_commit2);
+       if (r)
+               return r;
+
+       if (need_commit1 || need_commit2)
+               (void) commit_or_fallback(pool);
+
+       return 0;
+}
+
 static void pool_resume(struct dm_target *ti)
 {
        struct pool_c *pt = ti->private;
@@ -2549,7 +2669,7 @@ static struct target_type pool_target = {
        .name = "thin-pool",
        .features = DM_TARGET_SINGLETON | DM_TARGET_ALWAYS_WRITEABLE |
                    DM_TARGET_IMMUTABLE,
-       .version = {1, 7, 0},
+       .version = {1, 8, 0},
        .module = THIS_MODULE,
        .ctr = pool_ctr,
        .dtr = pool_dtr,
index f6d29e6..e735a6d 100644 (file)
@@ -248,7 +248,8 @@ static struct dm_space_map ops = {
        .new_block = sm_disk_new_block,
        .commit = sm_disk_commit,
        .root_size = sm_disk_root_size,
-       .copy_root = sm_disk_copy_root
+       .copy_root = sm_disk_copy_root,
+       .register_threshold_callback = NULL
 };
 
 struct dm_space_map *dm_sm_disk_create(struct dm_transaction_manager *tm,
index 906cf3d..1c95968 100644 (file)
 
 /*----------------------------------------------------------------*/
 
+/*
+ * An edge triggered threshold.
+ */
+struct threshold {
+       bool threshold_set;
+       bool value_set;
+       dm_block_t threshold;
+       dm_block_t current_value;
+       dm_sm_threshold_fn fn;
+       void *context;
+};
+
+static void threshold_init(struct threshold *t)
+{
+       t->threshold_set = false;
+       t->value_set = false;
+}
+
+static void set_threshold(struct threshold *t, dm_block_t value,
+                         dm_sm_threshold_fn fn, void *context)
+{
+       t->threshold_set = true;
+       t->threshold = value;
+       t->fn = fn;
+       t->context = context;
+}
+
+static bool below_threshold(struct threshold *t, dm_block_t value)
+{
+       return t->threshold_set && value <= t->threshold;
+}
+
+static bool threshold_already_triggered(struct threshold *t)
+{
+       return t->value_set && below_threshold(t, t->current_value);
+}
+
+static void check_threshold(struct threshold *t, dm_block_t value)
+{
+       if (below_threshold(t, value) &&
+           !threshold_already_triggered(t))
+               t->fn(t->context);
+
+       t->value_set = true;
+       t->current_value = value;
+}
+
+/*----------------------------------------------------------------*/
+
 /*
  * Space map interface.
  *
@@ -54,6 +103,8 @@ struct sm_metadata {
        unsigned allocated_this_transaction;
        unsigned nr_uncommitted;
        struct block_op uncommitted[MAX_RECURSIVE_ALLOCATIONS];
+
+       struct threshold threshold;
 };
 
 static int add_bop(struct sm_metadata *smm, enum block_op_type type, dm_block_t b)
@@ -144,12 +195,6 @@ static void sm_metadata_destroy(struct dm_space_map *sm)
        kfree(smm);
 }
 
-static int sm_metadata_extend(struct dm_space_map *sm, dm_block_t extra_blocks)
-{
-       DMERR("doesn't support extend");
-       return -EINVAL;
-}
-
 static int sm_metadata_get_nr_blocks(struct dm_space_map *sm, dm_block_t *count)
 {
        struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
@@ -335,9 +380,19 @@ static int sm_metadata_new_block_(struct dm_space_map *sm, dm_block_t *b)
 
 static int sm_metadata_new_block(struct dm_space_map *sm, dm_block_t *b)
 {
+       dm_block_t count;
+       struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
        int r = sm_metadata_new_block_(sm, b);
        if (r)
                DMERR("unable to allocate new metadata block");
+
+       r = sm_metadata_get_nr_free(sm, &count);
+       if (r)
+               DMERR("couldn't get free block count");
+
+       check_threshold(&smm->threshold, count);
+
        return r;
 }
 
@@ -357,6 +412,18 @@ static int sm_metadata_commit(struct dm_space_map *sm)
        return 0;
 }
 
+static int sm_metadata_register_threshold_callback(struct dm_space_map *sm,
+                                                  dm_block_t threshold,
+                                                  dm_sm_threshold_fn fn,
+                                                  void *context)
+{
+       struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+       set_threshold(&smm->threshold, threshold, fn, context);
+
+       return 0;
+}
+
 static int sm_metadata_root_size(struct dm_space_map *sm, size_t *result)
 {
        *result = sizeof(struct disk_sm_root);
@@ -382,6 +449,8 @@ static int sm_metadata_copy_root(struct dm_space_map *sm, void *where_le, size_t
        return 0;
 }
 
+static int sm_metadata_extend(struct dm_space_map *sm, dm_block_t extra_blocks);
+
 static struct dm_space_map ops = {
        .destroy = sm_metadata_destroy,
        .extend = sm_metadata_extend,
@@ -395,7 +464,8 @@ static struct dm_space_map ops = {
        .new_block = sm_metadata_new_block,
        .commit = sm_metadata_commit,
        .root_size = sm_metadata_root_size,
-       .copy_root = sm_metadata_copy_root
+       .copy_root = sm_metadata_copy_root,
+       .register_threshold_callback = sm_metadata_register_threshold_callback
 };
 
 /*----------------------------------------------------------------*/
@@ -410,7 +480,7 @@ static void sm_bootstrap_destroy(struct dm_space_map *sm)
 
 static int sm_bootstrap_extend(struct dm_space_map *sm, dm_block_t extra_blocks)
 {
-       DMERR("boostrap doesn't support extend");
+       DMERR("bootstrap doesn't support extend");
 
        return -EINVAL;
 }
@@ -450,7 +520,7 @@ static int sm_bootstrap_count_is_more_than_one(struct dm_space_map *sm,
 static int sm_bootstrap_set_count(struct dm_space_map *sm, dm_block_t b,
                                  uint32_t count)
 {
-       DMERR("boostrap doesn't support set_count");
+       DMERR("bootstrap doesn't support set_count");
 
        return -EINVAL;
 }
@@ -491,7 +561,7 @@ static int sm_bootstrap_commit(struct dm_space_map *sm)
 
 static int sm_bootstrap_root_size(struct dm_space_map *sm, size_t *result)
 {
-       DMERR("boostrap doesn't support root_size");
+       DMERR("bootstrap doesn't support root_size");
 
        return -EINVAL;
 }
@@ -499,7 +569,7 @@ static int sm_bootstrap_root_size(struct dm_space_map *sm, size_t *result)
 static int sm_bootstrap_copy_root(struct dm_space_map *sm, void *where,
                                  size_t max)
 {
-       DMERR("boostrap doesn't support copy_root");
+       DMERR("bootstrap doesn't support copy_root");
 
        return -EINVAL;
 }
@@ -517,11 +587,42 @@ static struct dm_space_map bootstrap_ops = {
        .new_block = sm_bootstrap_new_block,
        .commit = sm_bootstrap_commit,
        .root_size = sm_bootstrap_root_size,
-       .copy_root = sm_bootstrap_copy_root
+       .copy_root = sm_bootstrap_copy_root,
+       .register_threshold_callback = NULL
 };
 
 /*----------------------------------------------------------------*/
 
+static int sm_metadata_extend(struct dm_space_map *sm, dm_block_t extra_blocks)
+{
+       int r, i;
+       enum allocation_event ev;
+       struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+       dm_block_t old_len = smm->ll.nr_blocks;
+
+       /*
+        * Flick into a mode where all blocks get allocated in the new area.
+        */
+       smm->begin = old_len;
+       memcpy(&smm->sm, &bootstrap_ops, sizeof(smm->sm));
+
+       /*
+        * Extend.
+        */
+       r = sm_ll_extend(&smm->ll, extra_blocks);
+
+       /*
+        * Switch back to normal behaviour.
+        */
+       memcpy(&smm->sm, &ops, sizeof(smm->sm));
+       for (i = old_len; !r && i < smm->begin; i++)
+               r = sm_ll_inc(&smm->ll, i, &ev);
+
+       return r;
+}
+
+/*----------------------------------------------------------------*/
+
 struct dm_space_map *dm_sm_metadata_init(void)
 {
        struct sm_metadata *smm;
@@ -549,6 +650,7 @@ int dm_sm_metadata_create(struct dm_space_map *sm,
        smm->recursion_count = 0;
        smm->allocated_this_transaction = 0;
        smm->nr_uncommitted = 0;
+       threshold_init(&smm->threshold);
 
        memcpy(&smm->sm, &bootstrap_ops, sizeof(smm->sm));
 
@@ -590,6 +692,7 @@ int dm_sm_metadata_open(struct dm_space_map *sm,
        smm->recursion_count = 0;
        smm->allocated_this_transaction = 0;
        smm->nr_uncommitted = 0;
+       threshold_init(&smm->threshold);
 
        memcpy(&smm->old_ll, &smm->ll, sizeof(smm->old_ll));
        return 0;
index 1cbfc6b..3e6d115 100644 (file)
@@ -9,6 +9,8 @@
 
 #include "dm-block-manager.h"
 
+typedef void (*dm_sm_threshold_fn)(void *context);
+
 /*
  * struct dm_space_map keeps a record of how many times each block in a device
  * is referenced.  It needs to be fixed on disk as part of the transaction.
@@ -59,6 +61,15 @@ struct dm_space_map {
         */
        int (*root_size)(struct dm_space_map *sm, size_t *result);
        int (*copy_root)(struct dm_space_map *sm, void *copy_to_here_le, size_t len);
+
+       /*
+        * You can register one threshold callback which is edge-triggered
+        * when the free space in the space map drops below the threshold.
+        */
+       int (*register_threshold_callback)(struct dm_space_map *sm,
+                                          dm_block_t threshold,
+                                          dm_sm_threshold_fn fn,
+                                          void *context);
 };
 
 /*----------------------------------------------------------------*/
@@ -131,4 +142,16 @@ static inline int dm_sm_copy_root(struct dm_space_map *sm, void *copy_to_here_le
        return sm->copy_root(sm, copy_to_here_le, len);
 }
 
+static inline int dm_sm_register_threshold_callback(struct dm_space_map *sm,
+                                                   dm_block_t threshold,
+                                                   dm_sm_threshold_fn fn,
+                                                   void *context)
+{
+       if (sm->register_threshold_callback)
+               return sm->register_threshold_callback(sm, threshold, fn, context);
+
+       return -EINVAL;
+}
+
+
 #endif /* _LINUX_DM_SPACE_MAP_H */
index 9359828..753f318 100644 (file)
@@ -664,6 +664,7 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
                        if (test_bit(R5_ReadNoMerge, &sh->dev[i].flags))
                                bi->bi_rw |= REQ_FLUSH;
 
+                       bi->bi_vcnt = 1;
                        bi->bi_io_vec[0].bv_len = STRIPE_SIZE;
                        bi->bi_io_vec[0].bv_offset = 0;
                        bi->bi_size = STRIPE_SIZE;
@@ -701,6 +702,7 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
                        else
                                rbi->bi_sector = (sh->sector
                                                  + rrdev->data_offset);
+                       rbi->bi_vcnt = 1;
                        rbi->bi_io_vec[0].bv_len = STRIPE_SIZE;
                        rbi->bi_io_vec[0].bv_offset = 0;
                        rbi->bi_size = STRIPE_SIZE;
index ca2754a..5e04008 100644 (file)
@@ -176,7 +176,7 @@ struct zoran_fh;
 
 struct zoran_mapping {
        struct zoran_fh *fh;
-       int count;
+       atomic_t count;
 };
 
 struct zoran_buffer {
index 1168a84..d133c30 100644 (file)
@@ -2803,8 +2803,7 @@ static void
 zoran_vm_open (struct vm_area_struct *vma)
 {
        struct zoran_mapping *map = vma->vm_private_data;
-
-       map->count++;
+       atomic_inc(&map->count);
 }
 
 static void
@@ -2815,7 +2814,7 @@ zoran_vm_close (struct vm_area_struct *vma)
        struct zoran *zr = fh->zr;
        int i;
 
-       if (--map->count > 0)
+       if (!atomic_dec_and_mutex_lock(&map->count, &zr->resource_lock))
                return;
 
        dprintk(3, KERN_INFO "%s: %s - munmap(%s)\n", ZR_DEVNAME(zr),
@@ -2828,14 +2827,16 @@ zoran_vm_close (struct vm_area_struct *vma)
        kfree(map);
 
        /* Any buffers still mapped? */
-       for (i = 0; i < fh->buffers.num_buffers; i++)
-               if (fh->buffers.buffer[i].map)
+       for (i = 0; i < fh->buffers.num_buffers; i++) {
+               if (fh->buffers.buffer[i].map) {
+                       mutex_unlock(&zr->resource_lock);
                        return;
+               }
+       }
 
        dprintk(3, KERN_INFO "%s: %s - free %s buffers\n", ZR_DEVNAME(zr),
                __func__, mode_name(fh->map_mode));
 
-       mutex_lock(&zr->resource_lock);
 
        if (fh->map_mode == ZORAN_MAP_MODE_RAW) {
                if (fh->buffers.active != ZORAN_FREE) {
@@ -2939,7 +2940,7 @@ zoran_mmap (struct file           *file,
                goto mmap_unlock_and_return;
        }
        map->fh = fh;
-       map->count = 1;
+       atomic_set(&map->count, 1);
 
        vma->vm_ops = &zoran_vm_ops;
        vma->vm_flags |= VM_DONTEXPAND;
index 477268a..d338b19 100644 (file)
@@ -2150,6 +2150,9 @@ static int __init omap_vout_probe(struct platform_device *pdev)
        struct omap_dss_device *def_display;
        struct omap2video_device *vid_dev = NULL;
 
+       if (omapdss_is_initialized() == false)
+               return -EPROBE_DEFER;
+
        ret = omapdss_compat_init();
        if (ret) {
                dev_err(&pdev->dev, "failed to init dss\n");
index cadf1cc..04644e7 100644 (file)
@@ -1560,12 +1560,6 @@ static int __init_or_module emif_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, emif);
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(emif->dev, "%s: error getting memory resource\n",
-                       __func__);
-               goto error;
-       }
-
        emif->base = devm_ioremap_resource(emif->dev, res);
        if (IS_ERR(emif->base))
                goto error;
index d9aed15..d54e985 100644 (file)
@@ -579,7 +579,7 @@ config AB8500_CORE
 
 config AB8500_DEBUG
        bool "Enable debug info via debugfs"
-       depends on AB8500_CORE && DEBUG_FS
+       depends on AB8500_GPADC && DEBUG_FS
        default y if DEBUG_FS
        help
          Select this option if you want debug information using the debug
@@ -818,6 +818,7 @@ config MFD_TPS65910
 config MFD_TPS65912
        bool "TI TPS65912 Power Management chip"
        depends on GPIOLIB
+       select MFD_CORE
        help
          If you say yes here you get support for the TPS65912 series of
          PM chips.
index 8e8a016..258b367 100644 (file)
@@ -867,6 +867,15 @@ static struct resource ab8500_chargalg_resources[] = {};
 
 #ifdef CONFIG_DEBUG_FS
 static struct resource ab8500_debug_resources[] = {
+       {
+               .name   = "IRQ_AB8500",
+               /*
+                * Number will be filled in. NOTE: this is deliberately
+                * not flagged as an IRQ in ordet to avoid remapping using
+                * the irqdomain in the MFD core, so that this IRQ passes
+                * unremapped to the debug code.
+                */
+       },
        {
                .name   = "IRQ_FIRST",
                .start  = AB8500_INT_MAIN_EXT_CH_NOT_OK,
@@ -1051,6 +1060,7 @@ static struct mfd_cell ab8500_devs[] = {
        },
        {
                .name = "ab8500-gpadc",
+               .of_compatible = "stericsson,ab8500-gpadc",
                .num_resources = ARRAY_SIZE(ab8500_gpadc_resources),
                .resources = ab8500_gpadc_resources,
        },
@@ -1097,7 +1107,7 @@ static struct mfd_cell ab8500_devs[] = {
                .of_compatible = "stericsson,ab8500-denc",
        },
        {
-               .name = "ab8500-gpio",
+               .name = "pinctrl-ab8500",
                .of_compatible = "stericsson,ab8500-gpio",
        },
        {
@@ -1208,6 +1218,7 @@ static struct mfd_cell ab8505_devs[] = {
        },
        {
                .name = "ab8500-gpadc",
+               .of_compatible = "stericsson,ab8500-gpadc",
                .num_resources = ARRAY_SIZE(ab8505_gpadc_resources),
                .resources = ab8505_gpadc_resources,
        },
@@ -1234,7 +1245,7 @@ static struct mfd_cell ab8505_devs[] = {
                .name = "ab8500-leds",
        },
        {
-               .name = "ab8500-gpio",
+               .name = "pinctrl-ab8505",
        },
        {
                .name = "ab8500-usb",
@@ -1271,6 +1282,7 @@ static struct mfd_cell ab8540_devs[] = {
        },
        {
                .name = "ab8500-gpadc",
+               .of_compatible = "stericsson,ab8500-gpadc",
                .num_resources = ARRAY_SIZE(ab8505_gpadc_resources),
                .resources = ab8505_gpadc_resources,
        },
@@ -1302,7 +1314,7 @@ static struct mfd_cell ab8540_devs[] = {
                .resources = ab8500_temp_resources,
        },
        {
-               .name = "ab8500-gpio",
+               .name = "pinctrl-ab8540",
        },
        {
                .name = "ab8540-usb",
@@ -1712,6 +1724,12 @@ static int ab8500_probe(struct platform_device *pdev)
        if (ret)
                return ret;
 
+#if CONFIG_DEBUG_FS
+       /* Pass to debugfs */
+       ab8500_debug_resources[0].start = ab8500->irq;
+       ab8500_debug_resources[0].end = ab8500->irq;
+#endif
+
        if (is_ab9540(ab8500))
                ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs,
                                ARRAY_SIZE(ab9540_devs), NULL,
index b88bbbc..37b7ce4 100644 (file)
 #include <linux/ctype.h>
 #endif
 
-/* TODO: this file should not reference IRQ_DB8500_AB8500! */
-#include <mach/irqs.h>
-
 static u32 debug_bank;
 static u32 debug_address;
 
+static int irq_ab8500;
 static int irq_first;
 static int irq_last;
 static u32 *irq_count;
@@ -1589,7 +1587,7 @@ void ab8500_debug_register_interrupt(int line)
 {
        if (line < num_interrupt_lines) {
                num_interrupts[line]++;
-               if (suspend_test_wake_cause_interrupt_is_mine(IRQ_DB8500_AB8500))
+               if (suspend_test_wake_cause_interrupt_is_mine(irq_ab8500))
                        num_wake_interrupts[line]++;
        }
 }
@@ -2941,6 +2939,7 @@ static int ab8500_debug_probe(struct platform_device *plf)
        struct dentry *file;
        int ret = -ENOMEM;
        struct ab8500 *ab8500;
+       struct resource *res;
        debug_bank = AB8500_MISC;
        debug_address = AB8500_REV_REG & 0x00FF;
 
@@ -2959,6 +2958,15 @@ static int ab8500_debug_probe(struct platform_device *plf)
        if (!event_name)
                goto out_freedev_attr;
 
+       res = platform_get_resource_byname(plf, 0, "IRQ_AB8500");
+       if (!res) {
+               dev_err(&plf->dev, "AB8500 irq not found, err %d\n",
+                       irq_first);
+               ret = -ENXIO;
+               goto out_freeevent_name;
+       }
+       irq_ab8500 = res->start;
+
        irq_first = platform_get_irq_byname(plf, "IRQ_FIRST");
        if (irq_first < 0) {
                dev_err(&plf->dev, "First irq not found, err %d\n",
index 5e65b28..13f7866 100644 (file)
@@ -907,14 +907,17 @@ static int ab8500_gpadc_suspend(struct device *dev)
 static int ab8500_gpadc_resume(struct device *dev)
 {
        struct ab8500_gpadc *gpadc = dev_get_drvdata(dev);
+       int ret;
 
-       regulator_enable(gpadc->regu);
+       ret = regulator_enable(gpadc->regu);
+       if (ret)
+               dev_err(dev, "Failed to enable vtvout LDO: %d\n", ret);
 
        pm_runtime_mark_last_busy(gpadc->dev);
        pm_runtime_put_autosuspend(gpadc->dev);
 
        mutex_unlock(&gpadc->ab8500_gpadc_lock);
-       return 0;
+       return ret;
 }
 
 static int ab8500_gpadc_probe(struct platform_device *pdev)
index fbca1ce..8e0dae5 100644 (file)
@@ -23,7 +23,7 @@
 
 static struct device *sysctrl_dev;
 
-void ab8500_power_off(void)
+static void ab8500_power_off(void)
 {
        sigset_t old;
        sigset_t all;
@@ -104,7 +104,7 @@ void ab8500_restart(char mode, const char *cmd)
 
        plat = dev_get_platdata(sysctrl_dev->parent);
        pdata = plat->sysctrl;
-       if (pdata->reboot_reason_code)
+       if (pdata && pdata->reboot_reason_code)
                reason = pdata->reboot_reason_code(cmd);
        else
                pr_warn("[%s] No reboot reason set. Default reason %d\n",
@@ -188,14 +188,15 @@ static int ab8500_sysctrl_probe(struct platform_device *pdev)
 
        plat = dev_get_platdata(pdev->dev.parent);
 
-       if (!(plat && plat->sysctrl))
+       if (!plat)
                return -EINVAL;
 
-       if (plat->pm_power_off)
+       sysctrl_dev = &pdev->dev;
+
+       if (!pm_power_off)
                pm_power_off = ab8500_power_off;
 
        pdata = plat->sysctrl;
-
        if (pdata) {
                int last, ret, i, j;
 
@@ -226,6 +227,10 @@ static int ab8500_sysctrl_probe(struct platform_device *pdev)
 static int ab8500_sysctrl_remove(struct platform_device *pdev)
 {
        sysctrl_dev = NULL;
+
+       if (pm_power_off == ab8500_power_off)
+               pm_power_off = NULL;
+
        return 0;
 }
 
index 9818afb..3714acb 100644 (file)
@@ -156,7 +156,7 @@ EXPORT_SYMBOL(abx500_startup_irq_enabled);
 void abx500_dump_all_banks(void)
 {
        struct abx500_ops *ops;
-       struct device dummy_child = {0};
+       struct device dummy_child = {NULL};
        struct abx500_device_entry *dev_entry;
 
        list_for_each_entry(dev_entry, &abx500_list, list) {
index 19193cf..367ccb5 100644 (file)
@@ -120,7 +120,7 @@ static int cros_ec_spi_receive_response(struct cros_ec_device *ec_dev,
 
                for (end = ptr + EC_MSG_PREAMBLE_COUNT; ptr != end; ptr++) {
                        if (*ptr == EC_MSG_HEADER) {
-                               dev_dbg(ec_dev->dev, "msg found at %ld\n",
+                               dev_dbg(ec_dev->dev, "msg found at %zd\n",
                                        ptr - ec_dev->din);
                                break;
                        }
@@ -154,7 +154,7 @@ static int cros_ec_spi_receive_response(struct cros_ec_device *ec_dev,
                 * maximum-supported transfer size.
                 */
                todo = min(need_len, 256);
-               dev_dbg(ec_dev->dev, "loop, todo=%d, need_len=%d, ptr=%ld\n",
+               dev_dbg(ec_dev->dev, "loop, todo=%d, need_len=%d, ptr=%zd\n",
                        todo, need_len, ptr - ec_dev->din);
 
                memset(&trans, '\0', sizeof(trans));
@@ -178,7 +178,7 @@ static int cros_ec_spi_receive_response(struct cros_ec_device *ec_dev,
                need_len -= todo;
        }
 
-       dev_dbg(ec_dev->dev, "loop done, ptr=%ld\n", ptr - ec_dev->din);
+       dev_dbg(ec_dev->dev, "loop done, ptr=%zd\n", ptr - ec_dev->din);
 
        return 0;
 }
index 319b8ab..66f8097 100644 (file)
@@ -1613,6 +1613,8 @@ static unsigned long dsiclk_rate(u8 n)
 
        if (divsel == PRCM_DSI_PLLOUT_SEL_OFF)
                divsel = dsiclk[n].divsel;
+       else
+               dsiclk[n].divsel = divsel;
 
        switch (divsel) {
        case PRCM_DSI_PLLOUT_SEL_PHI_4:
@@ -3095,6 +3097,7 @@ static struct mfd_cell db8500_prcmu_devs[] = {
                .num_resources = ARRAY_SIZE(db8500_thsens_resources),
                .resources = db8500_thsens_resources,
                .platform_data = &db8500_thsens_data,
+               .pdata_size = sizeof(db8500_thsens_data),
        },
 };
 
index 5be3b5e..d8d5137 100644 (file)
@@ -414,11 +414,6 @@ static int intel_msic_probe(struct platform_device *pdev)
         * the clients via intel_msic_irq_read().
         */
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(&pdev->dev, "failed to get SRAM iomem resource\n");
-               return -ENODEV;
-       }
-
        msic->irq_base = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(msic->irq_base))
                return PTR_ERR(msic->irq_base);
index de48b4e..6f1ef63 100644 (file)
@@ -29,6 +29,8 @@
 
 #include <linux/mfd/si476x-core.h>
 
+#include <asm/unaligned.h>
+
 #define msb(x)                  ((u8)((u16) x >> 8))
 #define lsb(x)                  ((u8)((u16) x &  0x00FF))
 
@@ -150,7 +152,7 @@ enum si476x_acf_status_report_bits {
        SI476X_ACF_SOFTMUTE_INT = (1 << 0),
 
        SI476X_ACF_SMUTE        = (1 << 0),
-       SI476X_ACF_SMATTN       = 0b11111,
+       SI476X_ACF_SMATTN       = 0x1f,
        SI476X_ACF_PILOT        = (1 << 7),
        SI476X_ACF_STBLEND      = ~SI476X_ACF_PILOT,
 };
@@ -483,7 +485,7 @@ int si476x_core_cmd_get_property(struct si476x_core *core, u16 property)
        if (err < 0)
                return err;
        else
-               return be16_to_cpup((__be16 *)(resp + 2));
+               return get_unaligned_be16(resp + 2);
 }
 EXPORT_SYMBOL_GPL(si476x_core_cmd_get_property);
 
@@ -772,18 +774,18 @@ int si476x_core_cmd_am_rsq_status(struct si476x_core *core,
        if (!report)
                return err;
 
-       report->snrhint         = 0b00001000 & resp[1];
-       report->snrlint         = 0b00000100 & resp[1];
-       report->rssihint        = 0b00000010 & resp[1];
-       report->rssilint        = 0b00000001 & resp[1];
+       report->snrhint         = 0x08 & resp[1];
+       report->snrlint         = 0x04 & resp[1];
+       report->rssihint        = 0x02 & resp[1];
+       report->rssilint        = 0x01 & resp[1];
 
-       report->bltf            = 0b10000000 & resp[2];
-       report->snr_ready       = 0b00100000 & resp[2];
-       report->rssiready       = 0b00001000 & resp[2];
-       report->afcrl           = 0b00000010 & resp[2];
-       report->valid           = 0b00000001 & resp[2];
+       report->bltf            = 0x80 & resp[2];
+       report->snr_ready       = 0x20 & resp[2];
+       report->rssiready       = 0x08 & resp[2];
+       report->afcrl           = 0x02 & resp[2];
+       report->valid           = 0x01 & resp[2];
 
-       report->readfreq        = be16_to_cpup((__be16 *)(resp + 3));
+       report->readfreq        = get_unaligned_be16(resp + 3);
        report->freqoff         = resp[5];
        report->rssi            = resp[6];
        report->snr             = resp[7];
@@ -931,26 +933,26 @@ int si476x_core_cmd_fm_rds_status(struct si476x_core *core,
        if (err < 0 || report == NULL)
                return err;
 
-       report->rdstpptyint     = 0b00010000 & resp[1];
-       report->rdspiint        = 0b00001000 & resp[1];
-       report->rdssyncint      = 0b00000010 & resp[1];
-       report->rdsfifoint      = 0b00000001 & resp[1];
+       report->rdstpptyint     = 0x10 & resp[1];
+       report->rdspiint        = 0x08 & resp[1];
+       report->rdssyncint      = 0x02 & resp[1];
+       report->rdsfifoint      = 0x01 & resp[1];
 
-       report->tpptyvalid      = 0b00010000 & resp[2];
-       report->pivalid         = 0b00001000 & resp[2];
-       report->rdssync         = 0b00000010 & resp[2];
-       report->rdsfifolost     = 0b00000001 & resp[2];
+       report->tpptyvalid      = 0x10 & resp[2];
+       report->pivalid         = 0x08 & resp[2];
+       report->rdssync         = 0x02 & resp[2];
+       report->rdsfifolost     = 0x01 & resp[2];
 
-       report->tp              = 0b00100000 & resp[3];
-       report->pty             = 0b00011111 & resp[3];
+       report->tp              = 0x20 & resp[3];
+       report->pty             = 0x1f & resp[3];
 
-       report->pi              = be16_to_cpup((__be16 *)(resp + 4));
+       report->pi              = get_unaligned_be16(resp + 4);
        report->rdsfifoused     = resp[6];
 
-       report->ble[V4L2_RDS_BLOCK_A]   = 0b11000000 & resp[7];
-       report->ble[V4L2_RDS_BLOCK_B]   = 0b00110000 & resp[7];
-       report->ble[V4L2_RDS_BLOCK_C]   = 0b00001100 & resp[7];
-       report->ble[V4L2_RDS_BLOCK_D]   = 0b00000011 & resp[7];
+       report->ble[V4L2_RDS_BLOCK_A]   = 0xc0 & resp[7];
+       report->ble[V4L2_RDS_BLOCK_B]   = 0x30 & resp[7];
+       report->ble[V4L2_RDS_BLOCK_C]   = 0x0c & resp[7];
+       report->ble[V4L2_RDS_BLOCK_D]   = 0x03 & resp[7];
 
        report->rds[V4L2_RDS_BLOCK_A].block = V4L2_RDS_BLOCK_A;
        report->rds[V4L2_RDS_BLOCK_A].msb = resp[8];
@@ -991,9 +993,9 @@ int si476x_core_cmd_fm_rds_blockcount(struct si476x_core *core,
                                       SI476X_DEFAULT_TIMEOUT);
 
        if (!err) {
-               report->expected        = be16_to_cpup((__be16 *)(resp + 2));
-               report->received        = be16_to_cpup((__be16 *)(resp + 4));
-               report->uncorrectable   = be16_to_cpup((__be16 *)(resp + 6));
+               report->expected        = get_unaligned_be16(resp + 2);
+               report->received        = get_unaligned_be16(resp + 4);
+               report->uncorrectable   = get_unaligned_be16(resp + 6);
        }
 
        return err;
@@ -1005,7 +1007,7 @@ int si476x_core_cmd_fm_phase_diversity(struct si476x_core *core,
 {
        u8       resp[CMD_FM_PHASE_DIVERSITY_NRESP];
        const u8 args[CMD_FM_PHASE_DIVERSITY_NARGS] = {
-               mode & 0b111,
+               mode & 0x07,
        };
 
        return si476x_core_send_command(core, CMD_FM_PHASE_DIVERSITY,
@@ -1162,7 +1164,7 @@ static int si476x_core_cmd_am_tune_freq_a20(struct si476x_core *core,
        const int am_freq = tuneargs->freq;
        u8       resp[CMD_AM_TUNE_FREQ_NRESP];
        const u8 args[CMD_AM_TUNE_FREQ_NARGS] = {
-               (tuneargs->zifsr << 6) | (tuneargs->injside & 0b11),
+               (tuneargs->zifsr << 6) | (tuneargs->injside & 0x03),
                msb(am_freq),
                lsb(am_freq),
        };
@@ -1197,20 +1199,20 @@ static int si476x_core_cmd_fm_rsq_status_a10(struct si476x_core *core,
        if (err < 0 || report == NULL)
                return err;
 
-       report->multhint        = 0b10000000 & resp[1];
-       report->multlint        = 0b01000000 & resp[1];
-       report->snrhint         = 0b00001000 & resp[1];
-       report->snrlint         = 0b00000100 & resp[1];
-       report->rssihint        = 0b00000010 & resp[1];
-       report->rssilint        = 0b00000001 & resp[1];
+       report->multhint        = 0x80 & resp[1];
+       report->multlint        = 0x40 & resp[1];
+       report->snrhint         = 0x08 & resp[1];
+       report->snrlint         = 0x04 & resp[1];
+       report->rssihint        = 0x02 & resp[1];
+       report->rssilint        = 0x01 & resp[1];
 
-       report->bltf            = 0b10000000 & resp[2];
-       report->snr_ready       = 0b00100000 & resp[2];
-       report->rssiready       = 0b00001000 & resp[2];
-       report->afcrl           = 0b00000010 & resp[2];
-       report->valid           = 0b00000001 & resp[2];
+       report->bltf            = 0x80 & resp[2];
+       report->snr_ready       = 0x20 & resp[2];
+       report->rssiready       = 0x08 & resp[2];
+       report->afcrl           = 0x02 & resp[2];
+       report->valid           = 0x01 & resp[2];
 
-       report->readfreq        = be16_to_cpup((__be16 *)(resp + 3));
+       report->readfreq        = get_unaligned_be16(resp + 3);
        report->freqoff         = resp[5];
        report->rssi            = resp[6];
        report->snr             = resp[7];
@@ -1218,7 +1220,7 @@ static int si476x_core_cmd_fm_rsq_status_a10(struct si476x_core *core,
        report->hassi           = resp[10];
        report->mult            = resp[11];
        report->dev             = resp[12];
-       report->readantcap      = be16_to_cpup((__be16 *)(resp + 13));
+       report->readantcap      = get_unaligned_be16(resp + 13);
        report->assi            = resp[15];
        report->usn             = resp[16];
 
@@ -1251,20 +1253,20 @@ static int si476x_core_cmd_fm_rsq_status_a20(struct si476x_core *core,
        if (err < 0 || report == NULL)
                return err;
 
-       report->multhint        = 0b10000000 & resp[1];
-       report->multlint        = 0b01000000 & resp[1];
-       report->snrhint         = 0b00001000 & resp[1];
-       report->snrlint         = 0b00000100 & resp[1];
-       report->rssihint        = 0b00000010 & resp[1];
-       report->rssilint        = 0b00000001 & resp[1];
+       report->multhint        = 0x80 & resp[1];
+       report->multlint        = 0x40 & resp[1];
+       report->snrhint         = 0x08 & resp[1];
+       report->snrlint         = 0x04 & resp[1];
+       report->rssihint        = 0x02 & resp[1];
+       report->rssilint        = 0x01 & resp[1];
 
-       report->bltf            = 0b10000000 & resp[2];
-       report->snr_ready       = 0b00100000 & resp[2];
-       report->rssiready       = 0b00001000 & resp[2];
-       report->afcrl           = 0b00000010 & resp[2];
-       report->valid           = 0b00000001 & resp[2];
+       report->bltf            = 0x80 & resp[2];
+       report->snr_ready       = 0x20 & resp[2];
+       report->rssiready       = 0x08 & resp[2];
+       report->afcrl           = 0x02 & resp[2];
+       report->valid           = 0x01 & resp[2];
 
-       report->readfreq        = be16_to_cpup((__be16 *)(resp + 3));
+       report->readfreq        = get_unaligned_be16(resp + 3);
        report->freqoff         = resp[5];
        report->rssi            = resp[6];
        report->snr             = resp[7];
@@ -1272,7 +1274,7 @@ static int si476x_core_cmd_fm_rsq_status_a20(struct si476x_core *core,
        report->hassi           = resp[10];
        report->mult            = resp[11];
        report->dev             = resp[12];
-       report->readantcap      = be16_to_cpup((__be16 *)(resp + 13));
+       report->readantcap      = get_unaligned_be16(resp + 13);
        report->assi            = resp[15];
        report->usn             = resp[16];
 
@@ -1306,21 +1308,21 @@ static int si476x_core_cmd_fm_rsq_status_a30(struct si476x_core *core,
        if (err < 0 || report == NULL)
                return err;
 
-       report->multhint        = 0b10000000 & resp[1];
-       report->multlint        = 0b01000000 & resp[1];
-       report->snrhint         = 0b00001000 & resp[1];
-       report->snrlint         = 0b00000100 & resp[1];
-       report->rssihint        = 0b00000010 & resp[1];
-       report->rssilint        = 0b00000001 & resp[1];
-
-       report->bltf            = 0b10000000 & resp[2];
-       report->snr_ready       = 0b00100000 & resp[2];
-       report->rssiready       = 0b00001000 & resp[2];
-       report->injside         = 0b00000100 & resp[2];
-       report->afcrl           = 0b00000010 & resp[2];
-       report->valid           = 0b00000001 & resp[2];
-
-       report->readfreq        = be16_to_cpup((__be16 *)(resp + 3));
+       report->multhint        = 0x80 & resp[1];
+       report->multlint        = 0x40 & resp[1];
+       report->snrhint         = 0x08 & resp[1];
+       report->snrlint         = 0x04 & resp[1];
+       report->rssihint        = 0x02 & resp[1];
+       report->rssilint        = 0x01 & resp[1];
+
+       report->bltf            = 0x80 & resp[2];
+       report->snr_ready       = 0x20 & resp[2];
+       report->rssiready       = 0x08 & resp[2];
+       report->injside         = 0x04 & resp[2];
+       report->afcrl           = 0x02 & resp[2];
+       report->valid           = 0x01 & resp[2];
+
+       report->readfreq        = get_unaligned_be16(resp + 3);
        report->freqoff         = resp[5];
        report->rssi            = resp[6];
        report->snr             = resp[7];
@@ -1329,7 +1331,7 @@ static int si476x_core_cmd_fm_rsq_status_a30(struct si476x_core *core,
        report->hassi           = resp[10];
        report->mult            = resp[11];
        report->dev             = resp[12];
-       report->readantcap      = be16_to_cpup((__be16 *)(resp + 13));
+       report->readantcap      = get_unaligned_be16(resp + 13);
        report->assi            = resp[15];
        report->usn             = resp[16];
 
@@ -1337,7 +1339,7 @@ static int si476x_core_cmd_fm_rsq_status_a30(struct si476x_core *core,
        report->rdsdev          = resp[18];
        report->assidev         = resp[19];
        report->strongdev       = resp[20];
-       report->rdspi           = be16_to_cpup((__be16 *)(resp + 21));
+       report->rdspi           = get_unaligned_be16(resp + 21);
 
        return err;
 }
index c09c28f..1abd5ad 100644 (file)
@@ -154,11 +154,6 @@ static int ssc_probe(struct platform_device *pdev)
        ssc->pdata = (struct atmel_ssc_platform_data *)plat_dat;
 
        regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!regs) {
-               dev_dbg(&pdev->dev, "no mmio resource defined\n");
-               return -ENXIO;
-       }
-
        ssc->regs = devm_ioremap_resource(&pdev->dev, regs);
        if (IS_ERR(ssc->regs))
                return PTR_ERR(ssc->regs);
index 7014167..c37eeed 100644 (file)
@@ -19,7 +19,7 @@
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 
-static int irq;
+static int irq = -1;
 
 static irqreturn_t dummy_interrupt(int irq, void *dev_id)
 {
@@ -36,6 +36,10 @@ static irqreturn_t dummy_interrupt(int irq, void *dev_id)
 
 static int __init dummy_irq_init(void)
 {
+       if (irq < 0) {
+               printk(KERN_ERR "dummy-irq: no IRQ given.  Use irq=N\n");
+               return -EIO;
+       }
        if (request_irq(irq, &dummy_interrupt, IRQF_SHARED, "dummy_irq", &irq)) {
                printk(KERN_ERR "dummy-irq: cannot register IRQ %d\n", irq);
                return -EIO;
index 1e935ea..9ecd49a 100644 (file)
@@ -496,6 +496,8 @@ int mei_cl_disable_device(struct mei_cl_device *device)
                }
        }
 
+       device->event_cb = NULL;
+
        mutex_unlock(&dev->device_lock);
 
        if (!device->ops || !device->ops->disable)
index 7c44c8d..053139f 100644 (file)
@@ -489,11 +489,16 @@ static int mei_ioctl_connect_client(struct file *file,
 
        /* find ME client we're trying to connect to */
        i = mei_me_cl_by_uuid(dev, &data->in_client_uuid);
-       if (i >= 0 && !dev->me_clients[i].props.fixed_address) {
-               cl->me_client_id = dev->me_clients[i].client_id;
-               cl->state = MEI_FILE_CONNECTING;
+       if (i < 0 || dev->me_clients[i].props.fixed_address) {
+               dev_dbg(&dev->pdev->dev, "Cannot connect to FW Client UUID = %pUl\n",
+                               &data->in_client_uuid);
+               rets = -ENODEV;
+               goto end;
        }
 
+       cl->me_client_id = dev->me_clients[i].client_id;
+       cl->state = MEI_FILE_CONNECTING;
+
        dev_dbg(&dev->pdev->dev, "Connect to FW Client ID = %d\n",
                        cl->me_client_id);
        dev_dbg(&dev->pdev->dev, "FW Client - Protocol Version = %d\n",
@@ -527,11 +532,6 @@ static int mei_ioctl_connect_client(struct file *file,
                goto end;
        }
 
-       if (cl->state != MEI_FILE_CONNECTING) {
-               rets = -ENODEV;
-               goto end;
-       }
-
 
        /* prepare the output buffer */
        client = &data->out_client_properties;
@@ -543,7 +543,6 @@ static int mei_ioctl_connect_client(struct file *file,
        rets = mei_cl_connect(cl, file);
 
 end:
-       dev_dbg(&dev->pdev->dev, "free connect cb memory.");
        return rets;
 }
 
index 44d273c..0535d1e 100644 (file)
@@ -172,6 +172,7 @@ static long gru_get_config_info(unsigned long arg)
                nodesperblade = 2;
        else
                nodesperblade = 1;
+       memset(&info, 0, sizeof(info));
        info.cpus = num_online_cpus();
        info.nodes = num_online_nodes();
        info.blades = info.nodes / nodesperblade;
index ea98f7e..39c2eca 100644 (file)
@@ -4,7 +4,7 @@
 
 config VMWARE_VMCI
        tristate "VMware VMCI Driver"
-       depends on X86 && PCI && NET
+       depends on X86 && PCI
        help
          This is VMware's Virtual Machine Communication Interface.  It enables
          high-speed communication between host and guest in a virtual
index d94245d..8ff2e5e 100644 (file)
@@ -23,7 +23,7 @@
 #include <linux/pagemap.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
-#include <linux/socket.h>
+#include <linux/uio.h>
 #include <linux/wait.h>
 #include <linux/vmalloc.h>
 
index e75774f..aca59d9 100644 (file)
@@ -2230,10 +2230,15 @@ static void __exit atmci_cleanup_slot(struct atmel_mci_slot *slot,
        mmc_free_host(slot->mmc);
 }
 
-static bool atmci_filter(struct dma_chan *chan, void *slave)
+static bool atmci_filter(struct dma_chan *chan, void *pdata)
 {
-       struct mci_dma_data     *sl = slave;
+       struct mci_platform_data *sl_pdata = pdata;
+       struct mci_dma_data *sl;
 
+       if (!sl_pdata)
+               return false;
+
+       sl = sl_pdata->dma_slave;
        if (sl && find_slave_dev(sl) == chan->device->dev) {
                chan->private = slave_data_ptr(sl);
                return true;
@@ -2245,24 +2250,18 @@ static bool atmci_filter(struct dma_chan *chan, void *slave)
 static bool atmci_configure_dma(struct atmel_mci *host)
 {
        struct mci_platform_data        *pdata;
+       dma_cap_mask_t mask;
 
        if (host == NULL)
                return false;
 
        pdata = host->pdev->dev.platform_data;
 
-       if (!pdata)
-               return false;
+       dma_cap_zero(mask);
+       dma_cap_set(DMA_SLAVE, mask);
 
-       if (pdata->dma_slave && find_slave_dev(pdata->dma_slave)) {
-               dma_cap_mask_t mask;
-
-               /* Try to grab a DMA channel */
-               dma_cap_zero(mask);
-               dma_cap_set(DMA_SLAVE, mask);
-               host->dma.chan =
-                       dma_request_channel(mask, atmci_filter, pdata->dma_slave);
-       }
+       host->dma.chan = dma_request_slave_channel_compat(mask, atmci_filter, pdata,
+                                                         &host->pdev->dev, "rxtx");
        if (!host->dma.chan) {
                dev_warn(&host->pdev->dev, "no DMA channel available\n");
                return false;
index 375c109..f4f3038 100644 (file)
@@ -1130,6 +1130,7 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
        struct variant_data *variant = host->variant;
        u32 pwr = 0;
        unsigned long flags;
+       int ret;
 
        pm_runtime_get_sync(mmc_dev(mmc));
 
@@ -1161,8 +1162,12 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
                break;
        case MMC_POWER_ON:
                if (!IS_ERR(mmc->supply.vqmmc) &&
-                   !regulator_is_enabled(mmc->supply.vqmmc))
-                       regulator_enable(mmc->supply.vqmmc);
+                   !regulator_is_enabled(mmc->supply.vqmmc)) {
+                       ret = regulator_enable(mmc->supply.vqmmc);
+                       if (ret < 0)
+                               dev_err(mmc_dev(mmc),
+                                       "failed to enable vqmmc regulator\n");
+               }
 
                pwr |= MCI_PWR_ON;
                break;
index 6e44025..eccedc7 100644 (file)
@@ -161,6 +161,7 @@ struct omap_hsmmc_host {
         */
        struct  regulator       *vcc;
        struct  regulator       *vcc_aux;
+       int                     pbias_disable;
        void    __iomem         *base;
        resource_size_t         mapbase;
        spinlock_t              irq_lock; /* Prevent races with irq handler */
@@ -255,11 +256,11 @@ static int omap_hsmmc_set_power(struct device *dev, int slot, int power_on,
        if (!host->vcc)
                return 0;
        /*
-        * With DT, never turn OFF the regulator. This is because
+        * With DT, never turn OFF the regulator for MMC1. This is because
         * the pbias cell programming support is still missing when
         * booting with Device tree
         */
-       if (dev->of_node && !vdd)
+       if (host->pbias_disable && !vdd)
                return 0;
 
        if (mmc_slot(host).before_set_reg)
@@ -1520,10 +1521,10 @@ static void omap_hsmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
                        (ios->vdd == DUAL_VOLT_OCR_BIT) &&
                        /*
                         * With pbias cell programming missing, this
-                        * can't be allowed when booting with device
+                        * can't be allowed on MMC1 when booting with device
                         * tree.
                         */
-                       !host->dev->of_node) {
+                       !host->pbias_disable) {
                                /*
                                 * The mmc_select_voltage fn of the core does
                                 * not seem to set the power_mode to
@@ -1871,6 +1872,10 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
 
        omap_hsmmc_context_save(host);
 
+       /* This can be removed once we support PBIAS with DT */
+       if (host->dev->of_node && host->mapbase == 0x4809c000)
+               host->pbias_disable = 1;
+
        host->dbclk = clk_get(&pdev->dev, "mmchsdb_fck");
        /*
         * MMC can still work without debounce clock.
@@ -1906,33 +1911,41 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
 
        omap_hsmmc_conf_bus_power(host);
 
-       res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx");
-       if (!res) {
-               dev_err(mmc_dev(host->mmc), "cannot get DMA TX channel\n");
-               ret = -ENXIO;
-               goto err_irq;
-       }
-       tx_req = res->start;
+       if (!pdev->dev.of_node) {
+               res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx");
+               if (!res) {
+                       dev_err(mmc_dev(host->mmc), "cannot get DMA TX channel\n");
+                       ret = -ENXIO;
+                       goto err_irq;
+               }
+               tx_req = res->start;
 
-       res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx");
-       if (!res) {
-               dev_err(mmc_dev(host->mmc), "cannot get DMA RX channel\n");
-               ret = -ENXIO;
-               goto err_irq;
+               res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx");
+               if (!res) {
+                       dev_err(mmc_dev(host->mmc), "cannot get DMA RX channel\n");
+                       ret = -ENXIO;
+                       goto err_irq;
+               }
+               rx_req = res->start;
        }
-       rx_req = res->start;
 
        dma_cap_zero(mask);
        dma_cap_set(DMA_SLAVE, mask);
 
-       host->rx_chan = dma_request_channel(mask, omap_dma_filter_fn, &rx_req);
+       host->rx_chan =
+               dma_request_slave_channel_compat(mask, omap_dma_filter_fn,
+                                                &rx_req, &pdev->dev, "rx");
+
        if (!host->rx_chan) {
                dev_err(mmc_dev(host->mmc), "unable to obtain RX DMA engine channel %u\n", rx_req);
                ret = -ENXIO;
                goto err_irq;
        }
 
-       host->tx_chan = dma_request_channel(mask, omap_dma_filter_fn, &tx_req);
+       host->tx_chan =
+               dma_request_slave_channel_compat(mask, omap_dma_filter_fn,
+                                                &tx_req, &pdev->dev, "tx");
+
        if (!host->tx_chan) {
                dev_err(mmc_dev(host->mmc), "unable to obtain TX DMA engine channel %u\n", tx_req);
                ret = -ENXIO;
index 7bcf74b..706d9cb 100644 (file)
@@ -87,6 +87,12 @@ static const struct sdhci_ops sdhci_acpi_ops_dflt = {
        .enable_dma = sdhci_acpi_enable_dma,
 };
 
+static const struct sdhci_acpi_slot sdhci_acpi_slot_int_emmc = {
+       .caps    = MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE,
+       .caps2   = MMC_CAP2_HC_ERASE_SZ,
+       .flags   = SDHCI_ACPI_RUNTIME_PM,
+};
+
 static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sdio = {
        .quirks2 = SDHCI_QUIRK2_HOST_OFF_CARD_ON,
        .caps    = MMC_CAP_NONREMOVABLE | MMC_CAP_POWER_OFF_CARD,
@@ -94,23 +100,67 @@ static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sdio = {
        .pm_caps = MMC_PM_KEEP_POWER,
 };
 
+static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sd = {
+};
+
+struct sdhci_acpi_uid_slot {
+       const char *hid;
+       const char *uid;
+       const struct sdhci_acpi_slot *slot;
+};
+
+static const struct sdhci_acpi_uid_slot sdhci_acpi_uids[] = {
+       { "80860F14" , "1" , &sdhci_acpi_slot_int_emmc },
+       { "80860F14" , "3" , &sdhci_acpi_slot_int_sd   },
+       { "INT33BB"  , "2" , &sdhci_acpi_slot_int_sdio },
+       { "INT33C6"  , NULL, &sdhci_acpi_slot_int_sdio },
+       { "PNP0D40"  },
+       { },
+};
+
 static const struct acpi_device_id sdhci_acpi_ids[] = {
-       { "INT33C6", (kernel_ulong_t)&sdhci_acpi_slot_int_sdio },
-       { "PNP0D40" },
+       { "80860F14" },
+       { "INT33BB"  },
+       { "INT33C6"  },
+       { "PNP0D40"  },
        { },
 };
 MODULE_DEVICE_TABLE(acpi, sdhci_acpi_ids);
 
-static const struct sdhci_acpi_slot *sdhci_acpi_get_slot(const char *hid)
+static const struct sdhci_acpi_slot *sdhci_acpi_get_slot_by_ids(const char *hid,
+                                                               const char *uid)
 {
-       const struct acpi_device_id *id;
-
-       for (id = sdhci_acpi_ids; id->id[0]; id++)
-               if (!strcmp(id->id, hid))
-                       return (const struct sdhci_acpi_slot *)id->driver_data;
+       const struct sdhci_acpi_uid_slot *u;
+
+       for (u = sdhci_acpi_uids; u->hid; u++) {
+               if (strcmp(u->hid, hid))
+                       continue;
+               if (!u->uid)
+                       return u->slot;
+               if (uid && !strcmp(u->uid, uid))
+                       return u->slot;
+       }
        return NULL;
 }
 
+static const struct sdhci_acpi_slot *sdhci_acpi_get_slot(acpi_handle handle,
+                                                        const char *hid)
+{
+       const struct sdhci_acpi_slot *slot;
+       struct acpi_device_info *info;
+       const char *uid = NULL;
+       acpi_status status;
+
+       status = acpi_get_object_info(handle, &info);
+       if (!ACPI_FAILURE(status) && (info->valid & ACPI_VALID_UID))
+               uid = info->unique_id.string;
+
+       slot = sdhci_acpi_get_slot_by_ids(hid, uid);
+
+       kfree(info);
+       return slot;
+}
+
 static int sdhci_acpi_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
@@ -148,7 +198,7 @@ static int sdhci_acpi_probe(struct platform_device *pdev)
 
        c = sdhci_priv(host);
        c->host = host;
-       c->slot = sdhci_acpi_get_slot(hid);
+       c->slot = sdhci_acpi_get_slot(handle, hid);
        c->pdev = pdev;
        c->use_runtime_pm = sdhci_acpi_flag(c, SDHCI_ACPI_RUNTIME_PM);
 
@@ -202,6 +252,7 @@ static int sdhci_acpi_probe(struct platform_device *pdev)
                goto err_free;
 
        if (c->use_runtime_pm) {
+               pm_runtime_set_active(dev);
                pm_suspend_ignore_children(dev, 1);
                pm_runtime_set_autosuspend_delay(dev, 50);
                pm_runtime_use_autosuspend(dev);
index 67d6dde..d5f0d59 100644 (file)
@@ -85,6 +85,12 @@ struct pltfm_imx_data {
        struct clk *clk_ipg;
        struct clk *clk_ahb;
        struct clk *clk_per;
+       enum {
+               NO_CMD_PENDING,      /* no multiblock command pending*/
+               MULTIBLK_IN_PROCESS, /* exact multiblock cmd in process */
+               WAIT_FOR_INT,        /* sent CMD12, waiting for response INT */
+       } multiblock_status;
+
 };
 
 static struct platform_device_id imx_esdhc_devtype[] = {
@@ -154,6 +160,8 @@ static inline void esdhc_clrset_le(struct sdhci_host *host, u32 mask, u32 val, i
 
 static u32 esdhc_readl_le(struct sdhci_host *host, int reg)
 {
+       struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+       struct pltfm_imx_data *imx_data = pltfm_host->priv;
        u32 val = readl(host->ioaddr + reg);
 
        if (unlikely(reg == SDHCI_CAPABILITIES)) {
@@ -175,6 +183,18 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg)
                        val &= ~ESDHC_INT_VENDOR_SPEC_DMA_ERR;
                        val |= SDHCI_INT_ADMA_ERROR;
                }
+
+               /*
+                * mask off the interrupt we get in response to the manually
+                * sent CMD12
+                */
+               if ((imx_data->multiblock_status == WAIT_FOR_INT) &&
+                   ((val & SDHCI_INT_RESPONSE) == SDHCI_INT_RESPONSE)) {
+                       val &= ~SDHCI_INT_RESPONSE;
+                       writel(SDHCI_INT_RESPONSE, host->ioaddr +
+                                                  SDHCI_INT_STATUS);
+                       imx_data->multiblock_status = NO_CMD_PENDING;
+               }
        }
 
        return val;
@@ -211,6 +231,15 @@ static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg)
                        v = readl(host->ioaddr + ESDHC_VENDOR_SPEC);
                        v &= ~ESDHC_VENDOR_SPEC_SDIO_QUIRK;
                        writel(v, host->ioaddr + ESDHC_VENDOR_SPEC);
+
+                       if (imx_data->multiblock_status == MULTIBLK_IN_PROCESS)
+                       {
+                               /* send a manual CMD12 with RESPTYP=none */
+                               data = MMC_STOP_TRANSMISSION << 24 |
+                                      SDHCI_CMD_ABORTCMD << 16;
+                               writel(data, host->ioaddr + SDHCI_TRANSFER_MODE);
+                               imx_data->multiblock_status = WAIT_FOR_INT;
+                       }
        }
 
        if (unlikely(reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE)) {
@@ -277,11 +306,13 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
                }
                return;
        case SDHCI_COMMAND:
-               if ((host->cmd->opcode == MMC_STOP_TRANSMISSION ||
-                    host->cmd->opcode == MMC_SET_BLOCK_COUNT) &&
-                   (imx_data->flags & ESDHC_FLAG_MULTIBLK_NO_INT))
+               if (host->cmd->opcode == MMC_STOP_TRANSMISSION)
                        val |= SDHCI_CMD_ABORTCMD;
 
+               if ((host->cmd->opcode == MMC_SET_BLOCK_COUNT) &&
+                   (imx_data->flags & ESDHC_FLAG_MULTIBLK_NO_INT))
+                       imx_data->multiblock_status = MULTIBLK_IN_PROCESS;
+
                if (is_imx6q_usdhc(imx_data))
                        writel(val << 16,
                               host->ioaddr + SDHCI_TRANSFER_MODE);
@@ -324,8 +355,10 @@ static void esdhc_writeb_le(struct sdhci_host *host, u8 val, int reg)
                /*
                 * Do not touch buswidth bits here. This is done in
                 * esdhc_pltfm_bus_width.
+                * Do not touch the D3CD bit either which is used for the
+                * SDIO interrupt errata workaround.
                 */
-               mask = 0xffff & ~ESDHC_CTRL_BUSWIDTH_MASK;
+               mask = 0xffff & ~(ESDHC_CTRL_BUSWIDTH_MASK | ESDHC_CTRL_D3CD);
 
                esdhc_clrset_le(host, mask, new_val, reg);
                return;
index 0012d3f..701d06d 100644 (file)
@@ -33,6 +33,9 @@
  */
 #define PCI_DEVICE_ID_INTEL_PCH_SDIO0  0x8809
 #define PCI_DEVICE_ID_INTEL_PCH_SDIO1  0x880a
+#define PCI_DEVICE_ID_INTEL_BYT_EMMC   0x0f14
+#define PCI_DEVICE_ID_INTEL_BYT_SDIO   0x0f15
+#define PCI_DEVICE_ID_INTEL_BYT_SD     0x0f16
 
 /*
  * PCI registers
@@ -304,6 +307,33 @@ static const struct sdhci_pci_fixes sdhci_intel_pch_sdio = {
        .probe_slot     = pch_hc_probe_slot,
 };
 
+static int byt_emmc_probe_slot(struct sdhci_pci_slot *slot)
+{
+       slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE;
+       slot->host->mmc->caps2 |= MMC_CAP2_HC_ERASE_SZ;
+       return 0;
+}
+
+static int byt_sdio_probe_slot(struct sdhci_pci_slot *slot)
+{
+       slot->host->mmc->caps |= MMC_CAP_POWER_OFF_CARD | MMC_CAP_NONREMOVABLE;
+       return 0;
+}
+
+static const struct sdhci_pci_fixes sdhci_intel_byt_emmc = {
+       .allow_runtime_pm = true,
+       .probe_slot     = byt_emmc_probe_slot,
+};
+
+static const struct sdhci_pci_fixes sdhci_intel_byt_sdio = {
+       .quirks2        = SDHCI_QUIRK2_HOST_OFF_CARD_ON,
+       .allow_runtime_pm = true,
+       .probe_slot     = byt_sdio_probe_slot,
+};
+
+static const struct sdhci_pci_fixes sdhci_intel_byt_sd = {
+};
+
 /* O2Micro extra registers */
 #define O2_SD_LOCK_WP          0xD3
 #define O2_SD_MULTI_VCC3V      0xEE
@@ -855,6 +885,30 @@ static const struct pci_device_id pci_ids[] = {
                .driver_data    = (kernel_ulong_t)&sdhci_intel_pch_sdio,
        },
 
+       {
+               .vendor         = PCI_VENDOR_ID_INTEL,
+               .device         = PCI_DEVICE_ID_INTEL_BYT_EMMC,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .driver_data    = (kernel_ulong_t)&sdhci_intel_byt_emmc,
+       },
+
+       {
+               .vendor         = PCI_VENDOR_ID_INTEL,
+               .device         = PCI_DEVICE_ID_INTEL_BYT_SDIO,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .driver_data    = (kernel_ulong_t)&sdhci_intel_byt_sdio,
+       },
+
+       {
+               .vendor         = PCI_VENDOR_ID_INTEL,
+               .device         = PCI_DEVICE_ID_INTEL_BYT_SD,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .driver_data    = (kernel_ulong_t)&sdhci_intel_byt_sd,
+       },
+
        {
                .vendor         = PCI_VENDOR_ID_O2,
                .device         = PCI_DEVICE_ID_O2_8120,
index a94facb..fd1df5e 100644 (file)
@@ -672,11 +672,6 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
        }
 
        rc = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (rc == NULL) {
-               dev_err(&pdev->dev, "No memory resource found for device!\r\n");
-               return -ENXIO;
-       }
-
        host->io_base = devm_ioremap_resource(&pdev->dev, rc);
        if (IS_ERR(host->io_base))
                return PTR_ERR(host->io_base);
index fc58d11..390061d 100644 (file)
@@ -2360,14 +2360,15 @@ int bond_3ad_set_carrier(struct bonding *bond)
 }
 
 /**
- * bond_3ad_get_active_agg_info - get information of the active aggregator
+ * __bond_3ad_get_active_agg_info - get information of the active aggregator
  * @bond: bonding struct to work on
  * @ad_info: ad_info struct to fill with the bond's info
  *
  * Returns:   0 on success
  *          < 0 on error
  */
-int bond_3ad_get_active_agg_info(struct bonding *bond, struct ad_info *ad_info)
+int __bond_3ad_get_active_agg_info(struct bonding *bond,
+                                  struct ad_info *ad_info)
 {
        struct aggregator *aggregator = NULL;
        struct port *port;
@@ -2391,6 +2392,18 @@ int bond_3ad_get_active_agg_info(struct bonding *bond, struct ad_info *ad_info)
        return -1;
 }
 
+/* Wrapper used to hold bond->lock so no slave manipulation can occur */
+int bond_3ad_get_active_agg_info(struct bonding *bond, struct ad_info *ad_info)
+{
+       int ret;
+
+       read_lock(&bond->lock);
+       ret = __bond_3ad_get_active_agg_info(bond, ad_info);
+       read_unlock(&bond->lock);
+
+       return ret;
+}
+
 int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
 {
        struct slave *slave, *start_at;
@@ -2402,8 +2415,8 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
        struct ad_info ad_info;
        int res = 1;
 
-       if (bond_3ad_get_active_agg_info(bond, &ad_info)) {
-               pr_debug("%s: Error: bond_3ad_get_active_agg_info failed\n",
+       if (__bond_3ad_get_active_agg_info(bond, &ad_info)) {
+               pr_debug("%s: Error: __bond_3ad_get_active_agg_info failed\n",
                         dev->name);
                goto out;
        }
index 0cfaa4a..5d91ad0 100644 (file)
@@ -273,6 +273,8 @@ void bond_3ad_adapter_speed_changed(struct slave *slave);
 void bond_3ad_adapter_duplex_changed(struct slave *slave);
 void bond_3ad_handle_link_change(struct slave *slave, char link);
 int  bond_3ad_get_active_agg_info(struct bonding *bond, struct ad_info *ad_info);
+int  __bond_3ad_get_active_agg_info(struct bonding *bond,
+                                   struct ad_info *ad_info);
 int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev);
 int bond_3ad_lacpdu_recv(const struct sk_buff *skb, struct bonding *bond,
                         struct slave *slave);
index d0aade0..29b846c 100644 (file)
@@ -1362,6 +1362,7 @@ static netdev_features_t bond_fix_features(struct net_device *dev,
                                                     slave->dev->features,
                                                     mask);
        }
+       features = netdev_add_tso_features(features, mask);
 
 out:
        read_unlock(&bond->lock);
@@ -2555,8 +2556,8 @@ static void bond_arp_send(struct net_device *slave_dev, int arp_op, __be32 dest_
 {
        struct sk_buff *skb;
 
-       pr_debug("arp %d on slave %s: dst %x src %x vid %d\n", arp_op,
-                slave_dev->name, dest_ip, src_ip, vlan_id);
+       pr_debug("arp %d on slave %s: dst %pI4 src %pI4 vid %d\n", arp_op,
+                slave_dev->name, &dest_ip, &src_ip, vlan_id);
 
        skb = arp_create(arp_op, ETH_P_ARP, dest_ip, slave_dev, src_ip,
                         NULL, slave_dev->dev_addr, NULL);
@@ -2588,7 +2589,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
                __be32 addr;
                if (!targets[i])
                        break;
-               pr_debug("basa: target %x\n", targets[i]);
+               pr_debug("basa: target %pI4\n", &targets[i]);
                if (!bond_vlan_used(bond)) {
                        pr_debug("basa: empty vlan: arp_send\n");
                        addr = bond_confirm_addr(bond->dev, targets[i], 0);
@@ -4470,7 +4471,7 @@ int bond_parse_parm(const char *buf, const struct bond_parm_tbl *tbl)
 
 static int bond_check_params(struct bond_params *params)
 {
-       int arp_validate_value, fail_over_mac_value, primary_reselect_value;
+       int arp_validate_value, fail_over_mac_value, primary_reselect_value, i;
 
        /*
         * Convert string parameters.
@@ -4650,19 +4651,18 @@ static int bond_check_params(struct bond_params *params)
                arp_interval = BOND_LINK_ARP_INTERV;
        }
 
-       for (arp_ip_count = 0;
-            (arp_ip_count < BOND_MAX_ARP_TARGETS) && arp_ip_target[arp_ip_count];
-            arp_ip_count++) {
+       for (arp_ip_count = 0, i = 0;
+            (arp_ip_count < BOND_MAX_ARP_TARGETS) && arp_ip_target[i]; i++) {
                /* not complete check, but should be good enough to
                   catch mistakes */
-               __be32 ip = in_aton(arp_ip_target[arp_ip_count]);
-               if (!isdigit(arp_ip_target[arp_ip_count][0]) ||
-                   ip == 0 || ip == htonl(INADDR_BROADCAST)) {
+               __be32 ip = in_aton(arp_ip_target[i]);
+               if (!isdigit(arp_ip_target[i][0]) || ip == 0 ||
+                   ip == htonl(INADDR_BROADCAST)) {
                        pr_warning("Warning: bad arp_ip_target module parameter (%s), ARP monitoring will not be performed\n",
-                                  arp_ip_target[arp_ip_count]);
+                                  arp_ip_target[i]);
                        arp_interval = 0;
                } else {
-                       arp_target[arp_ip_count] = ip;
+                       arp_target[arp_ip_count++] = ip;
                }
        }
 
@@ -4696,8 +4696,6 @@ static int bond_check_params(struct bond_params *params)
        if (miimon) {
                pr_info("MII link monitoring set to %d ms\n", miimon);
        } else if (arp_interval) {
-               int i;
-
                pr_info("ARP monitoring set to %d ms, validate %s, with %d target(s):",
                        arp_interval,
                        arp_validate_tbl[arp_validate_value].modename,
index 94d06f1..4060d41 100644 (file)
@@ -130,7 +130,7 @@ static void bond_info_show_master(struct seq_file *seq)
                seq_printf(seq, "Aggregator selection policy (ad_select): %s\n",
                           ad_select_tbl[bond->params.ad_select].modename);
 
-               if (bond_3ad_get_active_agg_info(bond, &ad_info)) {
+               if (__bond_3ad_get_active_agg_info(bond, &ad_info)) {
                        seq_printf(seq, "bond %s has no active aggregator\n",
                                   bond->dev->name);
                } else {
index ea7a388..d7434e0 100644 (file)
@@ -316,6 +316,9 @@ static ssize_t bonding_store_mode(struct device *d,
        int new_value, ret = count;
        struct bonding *bond = to_bond(d);
 
+       if (!rtnl_trylock())
+               return restart_syscall();
+
        if (bond->dev->flags & IFF_UP) {
                pr_err("unable to update mode of %s because interface is up.\n",
                       bond->dev->name);
@@ -352,6 +355,7 @@ static ssize_t bonding_store_mode(struct device *d,
                bond->dev->name, bond_mode_tbl[new_value].modename,
                new_value);
 out:
+       rtnl_unlock();
        return ret;
 }
 static DEVICE_ATTR(mode, S_IRUGO | S_IWUSR,
@@ -1315,7 +1319,6 @@ static ssize_t bonding_show_mii_status(struct device *d,
 }
 static DEVICE_ATTR(mii_status, S_IRUGO, bonding_show_mii_status, NULL);
 
-
 /*
  * Show current 802.3ad aggregator ID.
  */
@@ -1329,7 +1332,7 @@ static ssize_t bonding_show_ad_aggregator(struct device *d,
        if (bond->params.mode == BOND_MODE_8023AD) {
                struct ad_info ad_info;
                count = sprintf(buf, "%d\n",
-                               (bond_3ad_get_active_agg_info(bond, &ad_info))
+                               bond_3ad_get_active_agg_info(bond, &ad_info)
                                ?  0 : ad_info.aggregator_id);
        }
 
@@ -1351,7 +1354,7 @@ static ssize_t bonding_show_ad_num_ports(struct device *d,
        if (bond->params.mode == BOND_MODE_8023AD) {
                struct ad_info ad_info;
                count = sprintf(buf, "%d\n",
-                               (bond_3ad_get_active_agg_info(bond, &ad_info))
+                               bond_3ad_get_active_agg_info(bond, &ad_info)
                                ?  0 : ad_info.ports);
        }
 
@@ -1373,7 +1376,7 @@ static ssize_t bonding_show_ad_actor_key(struct device *d,
        if (bond->params.mode == BOND_MODE_8023AD) {
                struct ad_info ad_info;
                count = sprintf(buf, "%d\n",
-                               (bond_3ad_get_active_agg_info(bond, &ad_info))
+                               bond_3ad_get_active_agg_info(bond, &ad_info)
                                ?  0 : ad_info.actor_key);
        }
 
@@ -1395,7 +1398,7 @@ static ssize_t bonding_show_ad_partner_key(struct device *d,
        if (bond->params.mode == BOND_MODE_8023AD) {
                struct ad_info ad_info;
                count = sprintf(buf, "%d\n",
-                               (bond_3ad_get_active_agg_info(bond, &ad_info))
+                               bond_3ad_get_active_agg_info(bond, &ad_info)
                                ?  0 : ad_info.partner_key);
        }
 
index 7ffc756..5470980 100644 (file)
@@ -43,7 +43,7 @@ config CAIF_HSI
 
 config CAIF_VIRTIO
        tristate "CAIF virtio transport driver"
-       depends on CAIF
+       depends on CAIF && HAS_DMA
        select VHOST_RING
        select VIRTIO
        select GENERIC_ALLOCATOR
index 9b74d1e..6aa7b32 100644 (file)
@@ -612,9 +612,15 @@ static int esd_usb2_start(struct esd_usb2_net_priv *priv)
 {
        struct esd_usb2 *dev = priv->usb2;
        struct net_device *netdev = priv->netdev;
-       struct esd_usb2_msg msg;
+       struct esd_usb2_msg *msg;
        int err, i;
 
+       msg = kmalloc(sizeof(*msg), GFP_KERNEL);
+       if (!msg) {
+               err = -ENOMEM;
+               goto out;
+       }
+
        /*
         * Enable all IDs
         * The IDADD message takes up to 64 32 bit bitmasks (2048 bits).
@@ -628,33 +634,32 @@ static int esd_usb2_start(struct esd_usb2_net_priv *priv)
         * the number of the starting bitmask (0..64) to the filter.option
         * field followed by only some bitmasks.
         */
-       msg.msg.hdr.cmd = CMD_IDADD;
-       msg.msg.hdr.len = 2 + ESD_MAX_ID_SEGMENT;
-       msg.msg.filter.net = priv->index;
-       msg.msg.filter.option = ESD_ID_ENABLE; /* start with segment 0 */
+       msg->msg.hdr.cmd = CMD_IDADD;
+       msg->msg.hdr.len = 2 + ESD_MAX_ID_SEGMENT;
+       msg->msg.filter.net = priv->index;
+       msg->msg.filter.option = ESD_ID_ENABLE; /* start with segment 0 */
        for (i = 0; i < ESD_MAX_ID_SEGMENT; i++)
-               msg.msg.filter.mask[i] = cpu_to_le32(0xffffffff);
+               msg->msg.filter.mask[i] = cpu_to_le32(0xffffffff);
        /* enable 29bit extended IDs */
-       msg.msg.filter.mask[ESD_MAX_ID_SEGMENT] = cpu_to_le32(0x00000001);
+       msg->msg.filter.mask[ESD_MAX_ID_SEGMENT] = cpu_to_le32(0x00000001);
 
-       err = esd_usb2_send_msg(dev, &msg);
+       err = esd_usb2_send_msg(dev, msg);
        if (err)
-               goto failed;
+               goto out;
 
        err = esd_usb2_setup_rx_urbs(dev);
        if (err)
-               goto failed;
+               goto out;
 
        priv->can.state = CAN_STATE_ERROR_ACTIVE;
 
-       return 0;
-
-failed:
+out:
        if (err == -ENODEV)
                netif_device_detach(netdev);
+       if (err)
+               netdev_err(netdev, "couldn't start device: %d\n", err);
 
-       netdev_err(netdev, "couldn't start device: %d\n", err);
-
+       kfree(msg);
        return err;
 }
 
@@ -833,26 +838,30 @@ nourbmem:
 static int esd_usb2_close(struct net_device *netdev)
 {
        struct esd_usb2_net_priv *priv = netdev_priv(netdev);
-       struct esd_usb2_msg msg;
+       struct esd_usb2_msg *msg;
        int i;
 
+       msg = kmalloc(sizeof(*msg), GFP_KERNEL);
+       if (!msg)
+               return -ENOMEM;
+
        /* Disable all IDs (see esd_usb2_start()) */
-       msg.msg.hdr.cmd = CMD_IDADD;
-       msg.msg.hdr.len = 2 + ESD_MAX_ID_SEGMENT;
-       msg.msg.filter.net = priv->index;
-       msg.msg.filter.option = ESD_ID_ENABLE; /* start with segment 0 */
+       msg->msg.hdr.cmd = CMD_IDADD;
+       msg->msg.hdr.len = 2 + ESD_MAX_ID_SEGMENT;
+       msg->msg.filter.net = priv->index;
+       msg->msg.filter.option = ESD_ID_ENABLE; /* start with segment 0 */
        for (i = 0; i <= ESD_MAX_ID_SEGMENT; i++)
-               msg.msg.filter.mask[i] = 0;
-       if (esd_usb2_send_msg(priv->usb2, &msg) < 0)
+               msg->msg.filter.mask[i] = 0;
+       if (esd_usb2_send_msg(priv->usb2, msg) < 0)
                netdev_err(netdev, "sending idadd message failed\n");
 
        /* set CAN controller to reset mode */
-       msg.msg.hdr.len = 2;
-       msg.msg.hdr.cmd = CMD_SETBAUD;
-       msg.msg.setbaud.net = priv->index;
-       msg.msg.setbaud.rsvd = 0;
-       msg.msg.setbaud.baud = cpu_to_le32(ESD_USB2_NO_BAUDRATE);
-       if (esd_usb2_send_msg(priv->usb2, &msg) < 0)
+       msg->msg.hdr.len = 2;
+       msg->msg.hdr.cmd = CMD_SETBAUD;
+       msg->msg.setbaud.net = priv->index;
+       msg->msg.setbaud.rsvd = 0;
+       msg->msg.setbaud.baud = cpu_to_le32(ESD_USB2_NO_BAUDRATE);
+       if (esd_usb2_send_msg(priv->usb2, msg) < 0)
                netdev_err(netdev, "sending setbaud message failed\n");
 
        priv->can.state = CAN_STATE_STOPPED;
@@ -861,6 +870,8 @@ static int esd_usb2_close(struct net_device *netdev)
 
        close_candev(netdev);
 
+       kfree(msg);
+
        return 0;
 }
 
@@ -886,7 +897,8 @@ static int esd_usb2_set_bittiming(struct net_device *netdev)
 {
        struct esd_usb2_net_priv *priv = netdev_priv(netdev);
        struct can_bittiming *bt = &priv->can.bittiming;
-       struct esd_usb2_msg msg;
+       struct esd_usb2_msg *msg;
+       int err;
        u32 canbtr;
        int sjw_shift;
 
@@ -912,15 +924,22 @@ static int esd_usb2_set_bittiming(struct net_device *netdev)
        if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
                canbtr |= ESD_USB2_3_SAMPLES;
 
-       msg.msg.hdr.len = 2;
-       msg.msg.hdr.cmd = CMD_SETBAUD;
-       msg.msg.setbaud.net = priv->index;
-       msg.msg.setbaud.rsvd = 0;
-       msg.msg.setbaud.baud = cpu_to_le32(canbtr);
+       msg = kmalloc(sizeof(*msg), GFP_KERNEL);
+       if (!msg)
+               return -ENOMEM;
+
+       msg->msg.hdr.len = 2;
+       msg->msg.hdr.cmd = CMD_SETBAUD;
+       msg->msg.setbaud.net = priv->index;
+       msg->msg.setbaud.rsvd = 0;
+       msg->msg.setbaud.baud = cpu_to_le32(canbtr);
 
        netdev_info(netdev, "setting BTR=%#x\n", canbtr);
 
-       return esd_usb2_send_msg(priv->usb2, &msg);
+       err = esd_usb2_send_msg(priv->usb2, msg);
+
+       kfree(msg);
+       return err;
 }
 
 static int esd_usb2_get_berr_counter(const struct net_device *netdev,
@@ -1022,7 +1041,7 @@ static int esd_usb2_probe(struct usb_interface *intf,
                         const struct usb_device_id *id)
 {
        struct esd_usb2 *dev;
-       struct esd_usb2_msg msg;
+       struct esd_usb2_msg *msg;
        int i, err;
 
        dev = kzalloc(sizeof(*dev), GFP_KERNEL);
@@ -1037,27 +1056,33 @@ static int esd_usb2_probe(struct usb_interface *intf,
 
        usb_set_intfdata(intf, dev);
 
+       msg = kmalloc(sizeof(*msg), GFP_KERNEL);
+       if (!msg) {
+               err = -ENOMEM;
+               goto free_msg;
+       }
+
        /* query number of CAN interfaces (nets) */
-       msg.msg.hdr.cmd = CMD_VERSION;
-       msg.msg.hdr.len = 2;
-       msg.msg.version.rsvd = 0;
-       msg.msg.version.flags = 0;
-       msg.msg.version.drv_version = 0;
+       msg->msg.hdr.cmd = CMD_VERSION;
+       msg->msg.hdr.len = 2;
+       msg->msg.version.rsvd = 0;
+       msg->msg.version.flags = 0;
+       msg->msg.version.drv_version = 0;
 
-       err = esd_usb2_send_msg(dev, &msg);
+       err = esd_usb2_send_msg(dev, msg);
        if (err < 0) {
                dev_err(&intf->dev, "sending version message failed\n");
-               goto free_dev;
+               goto free_msg;
        }
 
-       err = esd_usb2_wait_msg(dev, &msg);
+       err = esd_usb2_wait_msg(dev, msg);
        if (err < 0) {
                dev_err(&intf->dev, "no version message answer\n");
-               goto free_dev;
+               goto free_msg;
        }
 
-       dev->net_count = (int)msg.msg.version_reply.nets;
-       dev->version = le32_to_cpu(msg.msg.version_reply.version);
+       dev->net_count = (int)msg->msg.version_reply.nets;
+       dev->version = le32_to_cpu(msg->msg.version_reply.version);
 
        if (device_create_file(&intf->dev, &dev_attr_firmware))
                dev_err(&intf->dev,
@@ -1075,10 +1100,10 @@ static int esd_usb2_probe(struct usb_interface *intf,
        for (i = 0; i < dev->net_count; i++)
                esd_usb2_probe_one_net(intf, i);
 
-       return 0;
-
-free_dev:
-       kfree(dev);
+free_msg:
+       kfree(msg);
+       if (err)
+               kfree(dev);
 done:
        return err;
 }
index 45cb9f3..3b95465 100644 (file)
 #define KVASER_CTRL_MODE_SELFRECEPTION 3
 #define KVASER_CTRL_MODE_OFF           4
 
+/* log message */
+#define KVASER_EXTENDED_FRAME          BIT(31)
+
 struct kvaser_msg_simple {
        u8 tid;
        u8 channel;
@@ -817,8 +820,13 @@ static void kvaser_usb_rx_can_msg(const struct kvaser_usb *dev,
        priv = dev->nets[channel];
        stats = &priv->netdev->stats;
 
-       if (msg->u.rx_can.flag & (MSG_FLAG_ERROR_FRAME | MSG_FLAG_NERR |
-                                 MSG_FLAG_OVERRUN)) {
+       if ((msg->u.rx_can.flag & MSG_FLAG_ERROR_FRAME) &&
+           (msg->id == CMD_LOG_MESSAGE)) {
+               kvaser_usb_rx_error(dev, msg);
+               return;
+       } else if (msg->u.rx_can.flag & (MSG_FLAG_ERROR_FRAME |
+                                        MSG_FLAG_NERR |
+                                        MSG_FLAG_OVERRUN)) {
                kvaser_usb_rx_can_err(priv, msg);
                return;
        } else if (msg->u.rx_can.flag & ~MSG_FLAG_REMOTE_FRAME) {
@@ -834,22 +842,40 @@ static void kvaser_usb_rx_can_msg(const struct kvaser_usb *dev,
                return;
        }
 
-       cf->can_id = ((msg->u.rx_can.msg[0] & 0x1f) << 6) |
-                    (msg->u.rx_can.msg[1] & 0x3f);
-       cf->can_dlc = get_can_dlc(msg->u.rx_can.msg[5]);
+       if (msg->id == CMD_LOG_MESSAGE) {
+               cf->can_id = le32_to_cpu(msg->u.log_message.id);
+               if (cf->can_id & KVASER_EXTENDED_FRAME)
+                       cf->can_id &= CAN_EFF_MASK | CAN_EFF_FLAG;
+               else
+                       cf->can_id &= CAN_SFF_MASK;
 
-       if (msg->id == CMD_RX_EXT_MESSAGE) {
-               cf->can_id <<= 18;
-               cf->can_id |= ((msg->u.rx_can.msg[2] & 0x0f) << 14) |
-                             ((msg->u.rx_can.msg[3] & 0xff) << 6) |
-                             (msg->u.rx_can.msg[4] & 0x3f);
-               cf->can_id |= CAN_EFF_FLAG;
-       }
+               cf->can_dlc = get_can_dlc(msg->u.log_message.dlc);
 
-       if (msg->u.rx_can.flag & MSG_FLAG_REMOTE_FRAME)
-               cf->can_id |= CAN_RTR_FLAG;
-       else
-               memcpy(cf->data, &msg->u.rx_can.msg[6], cf->can_dlc);
+               if (msg->u.log_message.flags & MSG_FLAG_REMOTE_FRAME)
+                       cf->can_id |= CAN_RTR_FLAG;
+               else
+                       memcpy(cf->data, &msg->u.log_message.data,
+                              cf->can_dlc);
+       } else {
+               cf->can_id = ((msg->u.rx_can.msg[0] & 0x1f) << 6) |
+                            (msg->u.rx_can.msg[1] & 0x3f);
+
+               if (msg->id == CMD_RX_EXT_MESSAGE) {
+                       cf->can_id <<= 18;
+                       cf->can_id |= ((msg->u.rx_can.msg[2] & 0x0f) << 14) |
+                                     ((msg->u.rx_can.msg[3] & 0xff) << 6) |
+                                     (msg->u.rx_can.msg[4] & 0x3f);
+                       cf->can_id |= CAN_EFF_FLAG;
+               }
+
+               cf->can_dlc = get_can_dlc(msg->u.rx_can.msg[5]);
+
+               if (msg->u.rx_can.flag & MSG_FLAG_REMOTE_FRAME)
+                       cf->can_id |= CAN_RTR_FLAG;
+               else
+                       memcpy(cf->data, &msg->u.rx_can.msg[6],
+                              cf->can_dlc);
+       }
 
        netif_rx(skb);
 
@@ -911,6 +937,7 @@ static void kvaser_usb_handle_message(const struct kvaser_usb *dev,
 
        case CMD_RX_STD_MESSAGE:
        case CMD_RX_EXT_MESSAGE:
+       case CMD_LOG_MESSAGE:
                kvaser_usb_rx_can_msg(dev, msg);
                break;
 
@@ -919,11 +946,6 @@ static void kvaser_usb_handle_message(const struct kvaser_usb *dev,
                kvaser_usb_rx_error(dev, msg);
                break;
 
-       case CMD_LOG_MESSAGE:
-               if (msg->u.log_message.flags & MSG_FLAG_ERROR_FRAME)
-                       kvaser_usb_rx_error(dev, msg);
-               break;
-
        case CMD_TX_ACKNOWLEDGE:
                kvaser_usb_tx_acknowledge(dev, msg);
                break;
index 30d79bf..8ee9d15 100644 (file)
@@ -504,15 +504,24 @@ static int pcan_usb_pro_restart_async(struct peak_usb_device *dev,
        return usb_submit_urb(urb, GFP_ATOMIC);
 }
 
-static void pcan_usb_pro_drv_loaded(struct peak_usb_device *dev, int loaded)
+static int pcan_usb_pro_drv_loaded(struct peak_usb_device *dev, int loaded)
 {
-       u8 buffer[16];
+       u8 *buffer;
+       int err;
+
+       buffer = kmalloc(PCAN_USBPRO_FCT_DRVLD_REQ_LEN, GFP_KERNEL);
+       if (!buffer)
+               return -ENOMEM;
 
        buffer[0] = 0;
        buffer[1] = !!loaded;
 
-       pcan_usb_pro_send_req(dev, PCAN_USBPRO_REQ_FCT,
-                             PCAN_USBPRO_FCT_DRVLD, buffer, sizeof(buffer));
+       err = pcan_usb_pro_send_req(dev, PCAN_USBPRO_REQ_FCT,
+                                   PCAN_USBPRO_FCT_DRVLD, buffer,
+                                   PCAN_USBPRO_FCT_DRVLD_REQ_LEN);
+       kfree(buffer);
+
+       return err;
 }
 
 static inline
@@ -851,21 +860,24 @@ static int pcan_usb_pro_stop(struct peak_usb_device *dev)
  */
 static int pcan_usb_pro_init(struct peak_usb_device *dev)
 {
-       struct pcan_usb_pro_interface *usb_if;
        struct pcan_usb_pro_device *pdev =
                        container_of(dev, struct pcan_usb_pro_device, dev);
+       struct pcan_usb_pro_interface *usb_if = NULL;
+       struct pcan_usb_pro_fwinfo *fi = NULL;
+       struct pcan_usb_pro_blinfo *bi = NULL;
+       int err;
 
        /* do this for 1st channel only */
        if (!dev->prev_siblings) {
-               struct pcan_usb_pro_fwinfo fi;
-               struct pcan_usb_pro_blinfo bi;
-               int err;
-
                /* allocate netdevices common structure attached to first one */
                usb_if = kzalloc(sizeof(struct pcan_usb_pro_interface),
                                 GFP_KERNEL);
-               if (!usb_if)
-                       return -ENOMEM;
+               fi = kmalloc(sizeof(struct pcan_usb_pro_fwinfo), GFP_KERNEL);
+               bi = kmalloc(sizeof(struct pcan_usb_pro_blinfo), GFP_KERNEL);
+               if (!usb_if || !fi || !bi) {
+                       err = -ENOMEM;
+                       goto err_out;
+               }
 
                /* number of ts msgs to ignore before taking one into account */
                usb_if->cm_ignore_count = 5;
@@ -877,34 +889,34 @@ static int pcan_usb_pro_init(struct peak_usb_device *dev)
                 */
                err = pcan_usb_pro_send_req(dev, PCAN_USBPRO_REQ_INFO,
                                            PCAN_USBPRO_INFO_FW,
-                                           &fi, sizeof(fi));
+                                           fi, sizeof(*fi));
                if (err) {
-                       kfree(usb_if);
                        dev_err(dev->netdev->dev.parent,
                                "unable to read %s firmware info (err %d)\n",
                                pcan_usb_pro.name, err);
-                       return err;
+                       goto err_out;
                }
 
                err = pcan_usb_pro_send_req(dev, PCAN_USBPRO_REQ_INFO,
                                            PCAN_USBPRO_INFO_BL,
-                                           &bi, sizeof(bi));
+                                           bi, sizeof(*bi));
                if (err) {
-                       kfree(usb_if);
                        dev_err(dev->netdev->dev.parent,
                                "unable to read %s bootloader info (err %d)\n",
                                pcan_usb_pro.name, err);
-                       return err;
+                       goto err_out;
                }
 
+               /* tell the device the can driver is running */
+               err = pcan_usb_pro_drv_loaded(dev, 1);
+               if (err)
+                       goto err_out;
+
                dev_info(dev->netdev->dev.parent,
                     "PEAK-System %s hwrev %u serial %08X.%08X (%u channels)\n",
                     pcan_usb_pro.name,
-                    bi.hw_rev, bi.serial_num_hi, bi.serial_num_lo,
+                    bi->hw_rev, bi->serial_num_hi, bi->serial_num_lo,
                     pcan_usb_pro.ctrl_count);
-
-               /* tell the device the can driver is running */
-               pcan_usb_pro_drv_loaded(dev, 1);
        } else {
                usb_if = pcan_usb_pro_dev_if(dev->prev_siblings);
        }
@@ -916,6 +928,13 @@ static int pcan_usb_pro_init(struct peak_usb_device *dev)
        pcan_usb_pro_set_led(dev, 0, 1);
 
        return 0;
+
+ err_out:
+       kfree(bi);
+       kfree(fi);
+       kfree(usb_if);
+
+       return err;
 }
 
 static void pcan_usb_pro_exit(struct peak_usb_device *dev)
index a869918..32275af 100644 (file)
@@ -29,6 +29,7 @@
 
 /* Vendor Request value for XXX_FCT */
 #define PCAN_USBPRO_FCT_DRVLD          5 /* tell device driver is loaded */
+#define PCAN_USBPRO_FCT_DRVLD_REQ_LEN  16
 
 /* PCAN_USBPRO_INFO_BL vendor request record type */
 struct __packed pcan_usb_pro_blinfo {
index de570a8..072c6f1 100644 (file)
@@ -632,7 +632,6 @@ struct vortex_private {
                pm_state_valid:1,                               /* pci_dev->saved_config_space has sane contents */
                open:1,
                medialock:1,
-               must_free_region:1,                             /* Flag: if zero, Cardbus owns the I/O region */
                large_frames:1,                 /* accept large frames */
                handling_irq:1;                 /* private in_irq indicator */
        /* {get|set}_wol operations are already serialized by rtnl.
@@ -1012,6 +1011,12 @@ static int vortex_init_one(struct pci_dev *pdev,
        if (rc < 0)
                goto out;
 
+       rc = pci_request_regions(pdev, DRV_NAME);
+       if (rc < 0) {
+               pci_disable_device(pdev);
+               goto out;
+       }
+
        unit = vortex_cards_found;
 
        if (global_use_mmio < 0 && (unit >= MAX_UNITS || use_mmio[unit] < 0)) {
@@ -1027,6 +1032,7 @@ static int vortex_init_one(struct pci_dev *pdev,
        if (!ioaddr) /* If mapping fails, fall-back to BAR 0... */
                ioaddr = pci_iomap(pdev, 0, 0);
        if (!ioaddr) {
+               pci_release_regions(pdev);
                pci_disable_device(pdev);
                rc = -ENOMEM;
                goto out;
@@ -1036,6 +1042,7 @@ static int vortex_init_one(struct pci_dev *pdev,
                           ent->driver_data, unit);
        if (rc < 0) {
                pci_iounmap(pdev, ioaddr);
+               pci_release_regions(pdev);
                pci_disable_device(pdev);
                goto out;
        }
@@ -1178,11 +1185,6 @@ static int vortex_probe1(struct device *gendev, void __iomem *ioaddr, int irq,
 
        /* PCI-only startup logic */
        if (pdev) {
-               /* EISA resources already marked, so only PCI needs to do this here */
-               /* Ignore return value, because Cardbus drivers already allocate for us */
-               if (request_region(dev->base_addr, vci->io_size, print_name) != NULL)
-                       vp->must_free_region = 1;
-
                /* enable bus-mastering if necessary */
                if (vci->flags & PCI_USES_MASTER)
                        pci_set_master(pdev);
@@ -1220,7 +1222,7 @@ static int vortex_probe1(struct device *gendev, void __iomem *ioaddr, int irq,
                                           &vp->rx_ring_dma);
        retval = -ENOMEM;
        if (!vp->rx_ring)
-               goto free_region;
+               goto free_device;
 
        vp->tx_ring = (struct boom_tx_desc *)(vp->rx_ring + RX_RING_SIZE);
        vp->tx_ring_dma = vp->rx_ring_dma + sizeof(struct boom_rx_desc) * RX_RING_SIZE;
@@ -1484,9 +1486,7 @@ free_ring:
                                                        + sizeof(struct boom_tx_desc) * TX_RING_SIZE,
                                                vp->rx_ring,
                                                vp->rx_ring_dma);
-free_region:
-       if (vp->must_free_region)
-               release_region(dev->base_addr, vci->io_size);
+free_device:
        free_netdev(dev);
        pr_err(PFX "vortex_probe1 fails.  Returns %d\n", retval);
 out:
@@ -3254,8 +3254,9 @@ static void vortex_remove_one(struct pci_dev *pdev)
                                                        + sizeof(struct boom_tx_desc) * TX_RING_SIZE,
                                                vp->rx_ring,
                                                vp->rx_ring_dma);
-       if (vp->must_free_region)
-               release_region(dev->base_addr, vp->io_size);
+
+       pci_release_regions(pdev);
+
        free_netdev(dev);
 }
 
index b8fbe26..638e554 100644 (file)
@@ -3192,11 +3192,11 @@ static u32 bnx2x_xmit_type(struct bnx2x *bp, struct sk_buff *skb)
                rc |= XMIT_CSUM_TCP;
 
        if (skb_is_gso_v6(skb)) {
-               rc |= (XMIT_GSO_V6 | XMIT_CSUM_TCP | XMIT_CSUM_V6);
+               rc |= (XMIT_GSO_V6 | XMIT_CSUM_TCP);
                if (rc & XMIT_CSUM_ENC)
                        rc |= XMIT_GSO_ENC_V6;
        } else if (skb_is_gso(skb)) {
-               rc |= (XMIT_GSO_V4 | XMIT_CSUM_V4 | XMIT_CSUM_TCP);
+               rc |= (XMIT_GSO_V4 | XMIT_CSUM_TCP);
                if (rc & XMIT_CSUM_ENC)
                        rc |= XMIT_GSO_ENC_V4;
        }
@@ -3313,6 +3313,7 @@ static void bnx2x_set_pbd_gso_e2(struct sk_buff *skb, u32 *parsing_data,
  */
 static void bnx2x_set_pbd_gso(struct sk_buff *skb,
                              struct eth_tx_parse_bd_e1x *pbd,
+                             struct eth_tx_start_bd *tx_start_bd,
                              u32 xmit_type)
 {
        pbd->lso_mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
@@ -3326,11 +3327,14 @@ static void bnx2x_set_pbd_gso(struct sk_buff *skb,
                                                   ip_hdr(skb)->daddr,
                                                   0, IPPROTO_TCP, 0));
 
-       } else
+               /* GSO on 57710/57711 needs FW to calculate IP checksum */
+               tx_start_bd->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_IP_CSUM;
+       } else {
                pbd->tcp_pseudo_csum =
                        bswab16(~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
                                                 &ipv6_hdr(skb)->daddr,
                                                 0, IPPROTO_TCP, 0));
+       }
 
        pbd->global_data |=
                cpu_to_le16(ETH_TX_PARSE_BD_E1X_PSEUDO_CS_WITHOUT_LEN);
@@ -3479,19 +3483,18 @@ static void bnx2x_update_pbds_gso_enc(struct sk_buff *skb,
 {
        u16 hlen_w = 0;
        u8 outerip_off, outerip_len = 0;
+
        /* from outer IP to transport */
        hlen_w = (skb_inner_transport_header(skb) -
                  skb_network_header(skb)) >> 1;
 
        /* transport len */
-       if (xmit_type & XMIT_CSUM_TCP)
-               hlen_w += inner_tcp_hdrlen(skb) >> 1;
-       else
-               hlen_w += sizeof(struct udphdr) >> 1;
+       hlen_w += inner_tcp_hdrlen(skb) >> 1;
 
        pbd2->fw_ip_hdr_to_payload_w = hlen_w;
 
-       if (xmit_type & XMIT_CSUM_ENC_V4) {
+       /* outer IP header info */
+       if (xmit_type & XMIT_CSUM_V4) {
                struct iphdr *iph = ip_hdr(skb);
                pbd2->fw_ip_csum_wo_len_flags_frag =
                        bswab16(csum_fold((~iph->check) -
@@ -3814,7 +3817,7 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
                        bnx2x_set_pbd_gso_e2(skb, &pbd_e2_parsing_data,
                                             xmit_type);
                else
-                       bnx2x_set_pbd_gso(skb, pbd_e1x, xmit_type);
+                       bnx2x_set_pbd_gso(skb, pbd_e1x, first_bd, xmit_type);
        }
 
        /* Set the PBD's parsing_data field if not zero
index 728d42a..0f493c8 100644 (file)
@@ -94,10 +94,10 @@ static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits)
 
 #define DRV_MODULE_NAME                "tg3"
 #define TG3_MAJ_NUM                    3
-#define TG3_MIN_NUM                    131
+#define TG3_MIN_NUM                    132
 #define DRV_MODULE_VERSION     \
        __stringify(TG3_MAJ_NUM) "." __stringify(TG3_MIN_NUM)
-#define DRV_MODULE_RELDATE     "April 09, 2013"
+#define DRV_MODULE_RELDATE     "May 21, 2013"
 
 #define RESET_KIND_SHUTDOWN    0
 #define RESET_KIND_INIT                1
@@ -2957,6 +2957,31 @@ static int tg3_5700_link_polarity(struct tg3 *tp, u32 speed)
        return 0;
 }
 
+static bool tg3_phy_power_bug(struct tg3 *tp)
+{
+       switch (tg3_asic_rev(tp)) {
+       case ASIC_REV_5700:
+       case ASIC_REV_5704:
+               return true;
+       case ASIC_REV_5780:
+               if (tp->phy_flags & TG3_PHYFLG_MII_SERDES)
+                       return true;
+               return false;
+       case ASIC_REV_5717:
+               if (!tp->pci_fn)
+                       return true;
+               return false;
+       case ASIC_REV_5719:
+       case ASIC_REV_5720:
+               if ((tp->phy_flags & TG3_PHYFLG_PHY_SERDES) &&
+                   !tp->pci_fn)
+                       return true;
+               return false;
+       }
+
+       return false;
+}
+
 static void tg3_power_down_phy(struct tg3 *tp, bool do_low_power)
 {
        u32 val;
@@ -3016,12 +3041,7 @@ static void tg3_power_down_phy(struct tg3 *tp, bool do_low_power)
        /* The PHY should not be powered down on some chips because
         * of bugs.
         */
-       if (tg3_asic_rev(tp) == ASIC_REV_5700 ||
-           tg3_asic_rev(tp) == ASIC_REV_5704 ||
-           (tg3_asic_rev(tp) == ASIC_REV_5780 &&
-            (tp->phy_flags & TG3_PHYFLG_MII_SERDES)) ||
-           (tg3_asic_rev(tp) == ASIC_REV_5717 &&
-            !tp->pci_fn))
+       if (tg3_phy_power_bug(tp))
                return;
 
        if (tg3_chip_rev(tp) == CHIPREV_5784_AX ||
@@ -7428,6 +7448,20 @@ static inline int tg3_4g_overflow_test(dma_addr_t mapping, int len)
        return (base > 0xffffdcc0) && (base + len + 8 < base);
 }
 
+/* Test for TSO DMA buffers that cross into regions which are within MSS bytes
+ * of any 4GB boundaries: 4G, 8G, etc
+ */
+static inline int tg3_4g_tso_overflow_test(struct tg3 *tp, dma_addr_t mapping,
+                                          u32 len, u32 mss)
+{
+       if (tg3_asic_rev(tp) == ASIC_REV_5762 && mss) {
+               u32 base = (u32) mapping & 0xffffffff;
+
+               return ((base + len + (mss & 0x3fff)) < base);
+       }
+       return 0;
+}
+
 /* Test for DMA addresses > 40-bit */
 static inline int tg3_40bit_overflow_test(struct tg3 *tp, dma_addr_t mapping,
                                          int len)
@@ -7464,6 +7498,9 @@ static bool tg3_tx_frag_set(struct tg3_napi *tnapi, u32 *entry, u32 *budget,
        if (tg3_4g_overflow_test(map, len))
                hwbug = true;
 
+       if (tg3_4g_tso_overflow_test(tp, map, len, mss))
+               hwbug = true;
+
        if (tg3_40bit_overflow_test(tp, map, len))
                hwbug = true;
 
@@ -8874,6 +8911,10 @@ static int tg3_chip_reset(struct tg3 *tp)
                tg3_halt_cpu(tp, RX_CPU_BASE);
        }
 
+       err = tg3_poll_fw(tp);
+       if (err)
+               return err;
+
        tw32(GRC_MODE, tp->grc_mode);
 
        if (tg3_chip_rev_id(tp) == CHIPREV_ID_5705_A0) {
@@ -8904,10 +8945,6 @@ static int tg3_chip_reset(struct tg3 *tp)
 
        tg3_ape_unlock(tp, TG3_APE_LOCK_GRC);
 
-       err = tg3_poll_fw(tp);
-       if (err)
-               return err;
-
        tg3_mdio_start(tp);
 
        if (tg3_flag(tp, PCI_EXPRESS) &&
@@ -9431,6 +9468,14 @@ static void tg3_rss_write_indir_tbl(struct tg3 *tp)
        }
 }
 
+static inline u32 tg3_lso_rd_dma_workaround_bit(struct tg3 *tp)
+{
+       if (tg3_asic_rev(tp) == ASIC_REV_5719)
+               return TG3_LSO_RD_DMA_TX_LENGTH_WA_5719;
+       else
+               return TG3_LSO_RD_DMA_TX_LENGTH_WA_5720;
+}
+
 /* tp->lock is held. */
 static int tg3_reset_hw(struct tg3 *tp, bool reset_phy)
 {
@@ -10116,16 +10161,17 @@ static int tg3_reset_hw(struct tg3 *tp, bool reset_phy)
        tw32_f(RDMAC_MODE, rdmac_mode);
        udelay(40);
 
-       if (tg3_asic_rev(tp) == ASIC_REV_5719) {
+       if (tg3_asic_rev(tp) == ASIC_REV_5719 ||
+           tg3_asic_rev(tp) == ASIC_REV_5720) {
                for (i = 0; i < TG3_NUM_RDMA_CHANNELS; i++) {
                        if (tr32(TG3_RDMA_LENGTH + (i << 2)) > TG3_MAX_MTU(tp))
                                break;
                }
                if (i < TG3_NUM_RDMA_CHANNELS) {
                        val = tr32(TG3_LSO_RD_DMA_CRPTEN_CTRL);
-                       val |= TG3_LSO_RD_DMA_TX_LENGTH_WA;
+                       val |= tg3_lso_rd_dma_workaround_bit(tp);
                        tw32(TG3_LSO_RD_DMA_CRPTEN_CTRL, val);
-                       tg3_flag_set(tp, 5719_RDMA_BUG);
+                       tg3_flag_set(tp, 5719_5720_RDMA_BUG);
                }
        }
 
@@ -10489,15 +10535,15 @@ static void tg3_periodic_fetch_stats(struct tg3 *tp)
        TG3_STAT_ADD32(&sp->tx_ucast_packets, MAC_TX_STATS_UCAST);
        TG3_STAT_ADD32(&sp->tx_mcast_packets, MAC_TX_STATS_MCAST);
        TG3_STAT_ADD32(&sp->tx_bcast_packets, MAC_TX_STATS_BCAST);
-       if (unlikely(tg3_flag(tp, 5719_RDMA_BUG) &&
+       if (unlikely(tg3_flag(tp, 5719_5720_RDMA_BUG) &&
                     (sp->tx_ucast_packets.low + sp->tx_mcast_packets.low +
                      sp->tx_bcast_packets.low) > TG3_NUM_RDMA_CHANNELS)) {
                u32 val;
 
                val = tr32(TG3_LSO_RD_DMA_CRPTEN_CTRL);
-               val &= ~TG3_LSO_RD_DMA_TX_LENGTH_WA;
+               val &= ~tg3_lso_rd_dma_workaround_bit(tp);
                tw32(TG3_LSO_RD_DMA_CRPTEN_CTRL, val);
-               tg3_flag_clear(tp, 5719_RDMA_BUG);
+               tg3_flag_clear(tp, 5719_5720_RDMA_BUG);
        }
 
        TG3_STAT_ADD32(&sp->rx_octets, MAC_RX_STATS_OCTETS);
index 9b2d3ac..ff6e30e 100644 (file)
 #define TG3_LSO_RD_DMA_CRPTEN_CTRL     0x00004910
 #define TG3_LSO_RD_DMA_CRPTEN_CTRL_BLEN_BD_4K   0x00030000
 #define TG3_LSO_RD_DMA_CRPTEN_CTRL_BLEN_LSO_4K  0x000c0000
-#define TG3_LSO_RD_DMA_TX_LENGTH_WA     0x02000000
+#define TG3_LSO_RD_DMA_TX_LENGTH_WA_5719        0x02000000
+#define TG3_LSO_RD_DMA_TX_LENGTH_WA_5720        0x00200000
 /* 0x4914 --> 0x4be0 unused */
 
 #define TG3_NUM_RDMA_CHANNELS          4
@@ -3059,7 +3060,7 @@ enum TG3_FLAGS {
        TG3_FLAG_APE_HAS_NCSI,
        TG3_FLAG_TX_TSTAMP_EN,
        TG3_FLAG_4K_FIFO_LIMIT,
-       TG3_FLAG_5719_RDMA_BUG,
+       TG3_FLAG_5719_5720_RDMA_BUG,
        TG3_FLAG_RESET_TASK_PENDING,
        TG3_FLAG_PTP_CAPABLE,
        TG3_FLAG_5705_PLUS,
index ce4a030..07f7ef0 100644 (file)
@@ -3236,9 +3236,10 @@ bnad_init(struct bnad *bnad,
 
        sprintf(bnad->wq_name, "%s_wq_%d", BNAD_NAME, bnad->id);
        bnad->work_q = create_singlethread_workqueue(bnad->wq_name);
-
-       if (!bnad->work_q)
+       if (!bnad->work_q) {
+               iounmap(bnad->bar0);
                return -ENOMEM;
+       }
 
        return 0;
 }
index 1194446..768285e 100644 (file)
@@ -22,7 +22,7 @@ if NET_CADENCE
 
 config ARM_AT91_ETHER
        tristate "AT91RM9200 Ethernet support"
-       depends on GENERIC_HARDIRQS
+       depends on GENERIC_HARDIRQS && HAS_DMA
        select NET_CORE
        select MACB
        ---help---
@@ -31,6 +31,7 @@ config ARM_AT91_ETHER
 
 config MACB
        tristate "Cadence MACB/GEM support"
+       depends on HAS_DMA
        select PHYLIB
        ---help---
          The Cadence MACB ethernet interface is found on many Atmel AT32 and
index 6be513d..c89aa41 100644 (file)
@@ -485,7 +485,8 @@ static void macb_tx_interrupt(struct macb *bp)
        status = macb_readl(bp, TSR);
        macb_writel(bp, TSR, status);
 
-       macb_writel(bp, ISR, MACB_BIT(TCOMP));
+       if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
+               macb_writel(bp, ISR, MACB_BIT(TCOMP));
 
        netdev_vdbg(bp->dev, "macb_tx_interrupt status = 0x%03lx\n",
                (unsigned long)status);
@@ -738,7 +739,8 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
                         * now.
                         */
                        macb_writel(bp, IDR, MACB_RX_INT_FLAGS);
-                       macb_writel(bp, ISR, MACB_BIT(RCOMP));
+                       if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
+                               macb_writel(bp, ISR, MACB_BIT(RCOMP));
 
                        if (napi_schedule_prep(&bp->napi)) {
                                netdev_vdbg(bp->dev, "scheduling RX softirq\n");
@@ -1062,6 +1064,17 @@ static void macb_configure_dma(struct macb *bp)
        }
 }
 
+/*
+ * Configure peripheral capacities according to integration options used
+ */
+static void macb_configure_caps(struct macb *bp)
+{
+       if (macb_is_gem(bp)) {
+               if (GEM_BF(IRQCOR, gem_readl(bp, DCFG1)) == 0)
+                       bp->caps |= MACB_CAPS_ISR_CLEAR_ON_WRITE;
+       }
+}
+
 static void macb_init_hw(struct macb *bp)
 {
        u32 config;
@@ -1084,6 +1097,7 @@ static void macb_init_hw(struct macb *bp)
        bp->duplex = DUPLEX_HALF;
 
        macb_configure_dma(bp);
+       macb_configure_caps(bp);
 
        /* Initialize TX and RX buffers */
        macb_writel(bp, RBQP, bp->rx_ring_dma);
index 993d703..548c0ec 100644 (file)
 #define MACB_REV_SIZE                          16
 
 /* Bitfields in DCFG1. */
+#define GEM_IRQCOR_OFFSET                      23
+#define GEM_IRQCOR_SIZE                                1
 #define GEM_DBWDEF_OFFSET                      25
 #define GEM_DBWDEF_SIZE                                3
 
 #define MACB_MAN_READ                          2
 #define MACB_MAN_CODE                          2
 
+/* Capability mask bits */
+#define MACB_CAPS_ISR_CLEAR_ON_WRITE           0x1
+
 /* Bit manipulation macros */
 #define MACB_BIT(name)                                 \
        (1 << MACB_##name##_OFFSET)
@@ -574,6 +579,8 @@ struct macb {
        unsigned int            speed;
        unsigned int            duplex;
 
+       u32                     caps;
+
        phy_interface_t         phy_interface;
 
        /* AT91RM9200 transmit */
index aba435c..184a063 100644 (file)
@@ -1,6 +1,6 @@
 config NET_CALXEDA_XGMAC
        tristate "Calxeda 1G/10G XGMAC Ethernet driver"
-       depends on HAS_IOMEM
+       depends on HAS_IOMEM && HAS_DMA
        select CRC32
        help
          This is the driver for the XGMAC Ethernet IP block found on Calxeda
index f544b29..0a51068 100644 (file)
@@ -262,6 +262,7 @@ struct be_rx_compl_info {
        u8 ipv6;
        u8 vtm;
        u8 pkt_type;
+       u8 ip_frag;
 };
 
 struct be_rx_obj {
index fd7b547..1db2df6 100644 (file)
@@ -562,7 +562,7 @@ int lancer_test_and_set_rdy_state(struct be_adapter *adapter)
 
        resource_error = lancer_provisioning_error(adapter);
        if (resource_error)
-               return -1;
+               return -EAGAIN;
 
        status = lancer_wait_ready(adapter);
        if (!status) {
@@ -590,8 +590,8 @@ int lancer_test_and_set_rdy_state(struct be_adapter *adapter)
         * when PF provisions resources.
         */
        resource_error = lancer_provisioning_error(adapter);
-       if (status == -1 && !resource_error)
-               adapter->eeh_error = true;
+       if (resource_error)
+               status = -EAGAIN;
 
        return status;
 }
@@ -2976,22 +2976,17 @@ static struct be_nic_resource_desc *be_get_nic_desc(u8 *buf, u32 desc_count,
        for (i = 0; i < desc_count; i++) {
                desc->desc_len = desc->desc_len ? : RESOURCE_DESC_SIZE;
                if (((void *)desc + desc->desc_len) >
-                   (void *)(buf + max_buf_size)) {
-                       desc = NULL;
-                       break;
-               }
+                   (void *)(buf + max_buf_size))
+                       return NULL;
 
                if (desc->desc_type == NIC_RESOURCE_DESC_TYPE_V0 ||
                    desc->desc_type == NIC_RESOURCE_DESC_TYPE_V1)
-                       break;
+                       return desc;
 
                desc = (void *)desc + desc->desc_len;
        }
 
-       if (!desc || i == MAX_RESOURCE_DESC)
-               return NULL;
-
-       return desc;
+       return NULL;
 }
 
 /* Uses Mbox */
index 3c1099b..8780183 100644 (file)
@@ -356,7 +356,7 @@ struct amap_eth_rx_compl_v0 {
        u8 ip_version;          /* dword 1 */
        u8 macdst[6];           /* dword 1 */
        u8 vtp;                 /* dword 1 */
-       u8 rsvd0;               /* dword 1 */
+       u8 ip_frag;             /* dword 1 */
        u8 fragndx[10];         /* dword 1 */
        u8 ct[2];               /* dword 1 */
        u8 sw;                  /* dword 1 */
index a444110..8bc1b21 100644 (file)
@@ -780,26 +780,18 @@ static struct sk_buff *be_insert_vlan_in_pkt(struct be_adapter *adapter,
        if (unlikely(!skb))
                return skb;
 
-       if (vlan_tx_tag_present(skb)) {
+       if (vlan_tx_tag_present(skb))
                vlan_tag = be_get_tx_vlan_tag(adapter, skb);
-               skb = __vlan_put_tag(skb, htons(ETH_P_8021Q), vlan_tag);
-               if (skb)
-                       skb->vlan_tci = 0;
-       }
-
-       if (qnq_async_evt_rcvd(adapter) && adapter->pvid) {
-               if (!vlan_tag)
-                       vlan_tag = adapter->pvid;
-               if (skip_hw_vlan)
-                       *skip_hw_vlan = true;
-       }
+       else if (qnq_async_evt_rcvd(adapter) && adapter->pvid)
+               vlan_tag = adapter->pvid;
 
        if (vlan_tag) {
                skb = __vlan_put_tag(skb, htons(ETH_P_8021Q), vlan_tag);
                if (unlikely(!skb))
                        return skb;
-
                skb->vlan_tci = 0;
+               if (skip_hw_vlan)
+                       *skip_hw_vlan = true;
        }
 
        /* Insert the outer VLAN, if any */
@@ -1607,6 +1599,8 @@ static void be_parse_rx_compl_v0(struct be_eth_rx_compl *compl,
                                               compl);
        }
        rxcp->port = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, port, compl);
+       rxcp->ip_frag = AMAP_GET_BITS(struct amap_eth_rx_compl_v0,
+                                     ip_frag, compl);
 }
 
 static struct be_rx_compl_info *be_rx_compl_get(struct be_rx_obj *rxo)
@@ -1628,6 +1622,9 @@ static struct be_rx_compl_info *be_rx_compl_get(struct be_rx_obj *rxo)
        else
                be_parse_rx_compl_v0(compl, rxcp);
 
+       if (rxcp->ip_frag)
+               rxcp->l4_csum = 0;
+
        if (rxcp->vlanf) {
                /* vlanf could be wrongly set in some cards.
                 * ignore if vtm is not set */
@@ -2176,7 +2173,7 @@ static irqreturn_t be_msix(int irq, void *dev)
 
 static inline bool do_gro(struct be_rx_compl_info *rxcp)
 {
-       return (rxcp->tcpf && !rxcp->err) ? true : false;
+       return (rxcp->tcpf && !rxcp->err && rxcp->l4_csum) ? true : false;
 }
 
 static int be_process_rx(struct be_rx_obj *rxo, struct napi_struct *napi,
@@ -4101,6 +4098,7 @@ static int be_get_initial_config(struct be_adapter *adapter)
 
 static int lancer_recover_func(struct be_adapter *adapter)
 {
+       struct device *dev = &adapter->pdev->dev;
        int status;
 
        status = lancer_test_and_set_rdy_state(adapter);
@@ -4112,8 +4110,7 @@ static int lancer_recover_func(struct be_adapter *adapter)
 
        be_clear(adapter);
 
-       adapter->hw_error = false;
-       adapter->fw_timeout = false;
+       be_clear_all_error(adapter);
 
        status = be_setup(adapter);
        if (status)
@@ -4125,13 +4122,13 @@ static int lancer_recover_func(struct be_adapter *adapter)
                        goto err;
        }
 
-       dev_err(&adapter->pdev->dev,
-               "Adapter SLIPORT recovery succeeded\n");
+       dev_err(dev, "Error recovery successful\n");
        return 0;
 err:
-       if (adapter->eeh_error)
-               dev_err(&adapter->pdev->dev,
-                       "Adapter SLIPORT recovery failed\n");
+       if (status == -EAGAIN)
+               dev_err(dev, "Waiting for resource provisioning\n");
+       else
+               dev_err(dev, "Error recovery failed\n");
 
        return status;
 }
@@ -4140,28 +4137,27 @@ static void be_func_recovery_task(struct work_struct *work)
 {
        struct be_adapter *adapter =
                container_of(work, struct be_adapter,  func_recovery_work.work);
-       int status;
+       int status = 0;
 
        be_detect_error(adapter);
 
        if (adapter->hw_error && lancer_chip(adapter)) {
 
-               if (adapter->eeh_error)
-                       goto out;
-
                rtnl_lock();
                netif_device_detach(adapter->netdev);
                rtnl_unlock();
 
                status = lancer_recover_func(adapter);
-
                if (!status)
                        netif_device_attach(adapter->netdev);
        }
 
-out:
-       schedule_delayed_work(&adapter->func_recovery_work,
-                             msecs_to_jiffies(1000));
+       /* In Lancer, for all errors other than provisioning error (-EAGAIN),
+        * no need to attempt further recovery.
+        */
+       if (!status || status == -EAGAIN)
+               schedule_delayed_work(&adapter->func_recovery_work,
+                                     msecs_to_jiffies(1000));
 }
 
 static void be_worker(struct work_struct *work)
@@ -4444,20 +4440,19 @@ static pci_ers_result_t be_eeh_err_detected(struct pci_dev *pdev,
 
        dev_err(&adapter->pdev->dev, "EEH error detected\n");
 
-       adapter->eeh_error = true;
-
-       cancel_delayed_work_sync(&adapter->func_recovery_work);
+       if (!adapter->eeh_error) {
+               adapter->eeh_error = true;
 
-       rtnl_lock();
-       netif_device_detach(netdev);
-       rtnl_unlock();
+               cancel_delayed_work_sync(&adapter->func_recovery_work);
 
-       if (netif_running(netdev)) {
                rtnl_lock();
-               be_close(netdev);
+               netif_device_detach(netdev);
+               if (netif_running(netdev))
+                       be_close(netdev);
                rtnl_unlock();
+
+               be_clear(adapter);
        }
-       be_clear(adapter);
 
        if (state == pci_channel_io_perm_failure)
                return PCI_ERS_RESULT_DISCONNECT;
@@ -4482,7 +4477,6 @@ static pci_ers_result_t be_eeh_reset(struct pci_dev *pdev)
        int status;
 
        dev_info(&adapter->pdev->dev, "EEH reset\n");
-       be_clear_all_error(adapter);
 
        status = pci_enable_device(pdev);
        if (status)
@@ -4500,6 +4494,7 @@ static pci_ers_result_t be_eeh_reset(struct pci_dev *pdev)
                return PCI_ERS_RESULT_DISCONNECT;
 
        pci_cleanup_aer_uncorrect_error_status(pdev);
+       be_clear_all_error(adapter);
        return PCI_ERS_RESULT_RECOVERED;
 }
 
index aff0310..a667015 100644 (file)
@@ -87,6 +87,8 @@
 #define FEC_QUIRK_HAS_GBIT             (1 << 3)
 /* Controller has extend desc buffer */
 #define FEC_QUIRK_HAS_BUFDESC_EX       (1 << 4)
+/* Controller has hardware checksum support */
+#define FEC_QUIRK_HAS_CSUM             (1 << 5)
 
 static struct platform_device_id fec_devtype[] = {
        {
@@ -105,9 +107,9 @@ static struct platform_device_id fec_devtype[] = {
        }, {
                .name = "imx6q-fec",
                .driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT |
-                               FEC_QUIRK_HAS_BUFDESC_EX,
+                               FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM,
        }, {
-               .name = "mvf-fec",
+               .name = "mvf600-fec",
                .driver_data = FEC_QUIRK_ENET_MAC,
        }, {
                /* sentinel */
@@ -120,7 +122,7 @@ enum imx_fec_type {
        IMX27_FEC,      /* runs on i.mx27/35/51 */
        IMX28_FEC,
        IMX6Q_FEC,
-       MVF_FEC,
+       MVF600_FEC,
 };
 
 static const struct of_device_id fec_dt_ids[] = {
@@ -128,7 +130,7 @@ static const struct of_device_id fec_dt_ids[] = {
        { .compatible = "fsl,imx27-fec", .data = &fec_devtype[IMX27_FEC], },
        { .compatible = "fsl,imx28-fec", .data = &fec_devtype[IMX28_FEC], },
        { .compatible = "fsl,imx6q-fec", .data = &fec_devtype[IMX6Q_FEC], },
-       { .compatible = "fsl,mvf-fec", .data = &fec_devtype[MVF_FEC], },
+       { .compatible = "fsl,mvf600-fec", .data = &fec_devtype[MVF600_FEC], },
        { /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, fec_dt_ids);
@@ -449,7 +451,7 @@ fec_restart(struct net_device *ndev, int duplex)
                netif_device_detach(ndev);
                napi_disable(&fep->napi);
                netif_stop_queue(ndev);
-               netif_tx_lock(ndev);
+               netif_tx_lock_bh(ndev);
        }
 
        /* Whack a reset.  We should wait for this. */
@@ -614,10 +616,10 @@ fec_restart(struct net_device *ndev, int duplex)
        writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
 
        if (netif_running(ndev)) {
-               netif_device_attach(ndev);
-               napi_enable(&fep->napi);
+               netif_tx_unlock_bh(ndev);
                netif_wake_queue(ndev);
-               netif_tx_unlock(ndev);
+               napi_enable(&fep->napi);
+               netif_device_attach(ndev);
        }
 }
 
@@ -1036,6 +1038,18 @@ static void fec_get_mac(struct net_device *ndev)
                iap = &tmpaddr[0];
        }
 
+       /*
+        * 5) random mac address
+        */
+       if (!is_valid_ether_addr(iap)) {
+               /* Report it and use a random ethernet address instead */
+               netdev_err(ndev, "Invalid MAC address: %pM\n", iap);
+               eth_hw_addr_random(ndev);
+               netdev_info(ndev, "Using random MAC address: %pM\n",
+                           ndev->dev_addr);
+               return;
+       }
+
        memcpy(ndev->dev_addr, iap, ETH_ALEN);
 
        /* Adjust MAC if using macaddr */
@@ -1744,6 +1758,8 @@ static const struct net_device_ops fec_netdev_ops = {
 static int fec_enet_init(struct net_device *ndev)
 {
        struct fec_enet_private *fep = netdev_priv(ndev);
+       const struct platform_device_id *id_entry =
+                               platform_get_device_id(fep->pdev);
        struct bufdesc *cbd_base;
 
        /* Allocate memory for buffer descriptors. */
@@ -1775,12 +1791,14 @@ static int fec_enet_init(struct net_device *ndev)
        writel(FEC_RX_DISABLED_IMASK, fep->hwp + FEC_IMASK);
        netif_napi_add(ndev, &fep->napi, fec_enet_rx_napi, FEC_NAPI_WEIGHT);
 
-       /* enable hw accelerator */
-       ndev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM
-                       | NETIF_F_RXCSUM);
-       ndev->hw_features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM
-                       | NETIF_F_RXCSUM);
-       fep->csum_flags |= FLAG_RX_CSUM_ENABLED;
+       if (id_entry->driver_data & FEC_QUIRK_HAS_CSUM) {
+               /* enable hw accelerator */
+               ndev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM
+                               | NETIF_F_RXCSUM);
+               ndev->hw_features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM
+                               | NETIF_F_RXCSUM);
+               fep->csum_flags |= FLAG_RX_CSUM_ENABLED;
+       }
 
        fec_restart(ndev, 0);
 
index 576e4b8..083ea2b 100644 (file)
@@ -524,6 +524,7 @@ static int gianfar_ptp_probe(struct platform_device *dev)
        return 0;
 
 no_clock:
+       iounmap(etsects->regs);
 no_ioremap:
        release_resource(etsects->rsrc);
 no_resource:
index 4989481..d300a0c 100644 (file)
@@ -359,10 +359,26 @@ static int emac_reset(struct emac_instance *dev)
        }
 
 #ifdef CONFIG_PPC_DCR_NATIVE
-       /* Enable internal clock source */
-       if (emac_has_feature(dev, EMAC_FTR_460EX_PHY_CLK_FIX))
-               dcri_clrset(SDR0, SDR0_ETH_CFG,
-                           0, SDR0_ETH_CFG_ECS << dev->cell_index);
+       /*
+        * PPC460EX/GT Embedded Processor Advanced User's Manual
+        * section 28.10.1 Mode Register 0 (EMACx_MR0) states:
+        * Note: The PHY must provide a TX Clk in order to perform a soft reset
+        * of the EMAC. If none is present, select the internal clock
+        * (SDR0_ETH_CFG[EMACx_PHY_CLK] = 1).
+        * After a soft reset, select the external clock.
+        */
+       if (emac_has_feature(dev, EMAC_FTR_460EX_PHY_CLK_FIX)) {
+               if (dev->phy_address == 0xffffffff &&
+                   dev->phy_map == 0xffffffff) {
+                       /* No PHY: select internal loop clock before reset */
+                       dcri_clrset(SDR0, SDR0_ETH_CFG,
+                                   0, SDR0_ETH_CFG_ECS << dev->cell_index);
+               } else {
+                       /* PHY present: select external clock before reset */
+                       dcri_clrset(SDR0, SDR0_ETH_CFG,
+                                   SDR0_ETH_CFG_ECS << dev->cell_index, 0);
+               }
+       }
 #endif
 
        out_be32(&p->mr0, EMAC_MR0_SRST);
@@ -370,10 +386,14 @@ static int emac_reset(struct emac_instance *dev)
                --n;
 
 #ifdef CONFIG_PPC_DCR_NATIVE
-        /* Enable external clock source */
-       if (emac_has_feature(dev, EMAC_FTR_460EX_PHY_CLK_FIX))
-               dcri_clrset(SDR0, SDR0_ETH_CFG,
-                           SDR0_ETH_CFG_ECS << dev->cell_index, 0);
+       if (emac_has_feature(dev, EMAC_FTR_460EX_PHY_CLK_FIX)) {
+               if (dev->phy_address == 0xffffffff &&
+                   dev->phy_map == 0xffffffff) {
+                       /* No PHY: restore external clock source after reset */
+                       dcri_clrset(SDR0, SDR0_ETH_CFG,
+                                   SDR0_ETH_CFG_ECS << dev->cell_index, 0);
+               }
+       }
 #endif
 
        if (n) {
index 6ce0273..abb300a 100644 (file)
@@ -195,57 +195,57 @@ enum ipg_regs {
 /* TFD data structure masks. */
 
 /* TFDList, TFC */
-#define        IPG_TFC_RSVD_MASK                       0x0000FFFF9FFFFFFF
-#define        IPG_TFC_FRAMEID                         0x000000000000FFFF
-#define        IPG_TFC_WORDALIGN                       0x0000000000030000
-#define        IPG_TFC_WORDALIGNTODWORD                0x0000000000000000
-#define        IPG_TFC_WORDALIGNTOWORD                 0x0000000000020000
-#define        IPG_TFC_WORDALIGNDISABLED               0x0000000000030000
-#define        IPG_TFC_TCPCHECKSUMENABLE               0x0000000000040000
-#define        IPG_TFC_UDPCHECKSUMENABLE               0x0000000000080000
-#define        IPG_TFC_IPCHECKSUMENABLE                0x0000000000100000
-#define        IPG_TFC_FCSAPPENDDISABLE                0x0000000000200000
-#define        IPG_TFC_TXINDICATE                      0x0000000000400000
-#define        IPG_TFC_TXDMAINDICATE                   0x0000000000800000
-#define        IPG_TFC_FRAGCOUNT                       0x000000000F000000
-#define        IPG_TFC_VLANTAGINSERT                   0x0000000010000000
-#define        IPG_TFC_TFDDONE                         0x0000000080000000
-#define        IPG_TFC_VID                             0x00000FFF00000000
-#define        IPG_TFC_CFI                             0x0000100000000000
-#define        IPG_TFC_USERPRIORITY                    0x0000E00000000000
+#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                       0xFFFF00FFFFFFFFFF
-#define        IPG_TFI_FRAGADDR                        0x000000FFFFFFFFFF
-#define        IPG_TFI_FRAGLEN                         0xFFFF000000000000LL
+#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                       0x0000FFFFFFFFFFFF
-#define        IPG_RFS_RXFRAMELEN                      0x000000000000FFFF
-#define        IPG_RFS_RXFIFOOVERRUN                   0x0000000000010000
-#define        IPG_RFS_RXRUNTFRAME                     0x0000000000020000
-#define        IPG_RFS_RXALIGNMENTERROR                0x0000000000040000
-#define        IPG_RFS_RXFCSERROR                      0x0000000000080000
-#define        IPG_RFS_RXOVERSIZEDFRAME                0x0000000000100000
-#define        IPG_RFS_RXLENGTHERROR                   0x0000000000200000
-#define        IPG_RFS_VLANDETECTED                    0x0000000000400000
-#define        IPG_RFS_TCPDETECTED                     0x0000000000800000
-#define        IPG_RFS_TCPERROR                        0x0000000001000000
-#define        IPG_RFS_UDPDETECTED                     0x0000000002000000
-#define        IPG_RFS_UDPERROR                        0x0000000004000000
-#define        IPG_RFS_IPDETECTED                      0x0000000008000000
-#define        IPG_RFS_IPERROR                         0x0000000010000000
-#define        IPG_RFS_FRAMESTART                      0x0000000020000000
-#define        IPG_RFS_FRAMEEND                        0x0000000040000000
-#define        IPG_RFS_RFDDONE                         0x0000000080000000
-#define        IPG_RFS_TCI                             0x0000FFFF00000000
+#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                       0xFFFF00FFFFFFFFFF
-#define        IPG_RFI_FRAGADDR                        0x000000FFFFFFFFFF
-#define        IPG_RFI_FRAGLEN                         0xFFFF000000000000LL
+#define        IPG_RFI_RSVD_MASK                       0xFFFF00FFFFFFFFFFULL
+#define        IPG_RFI_FRAGADDR                        0x000000FFFFFFFFFFULL
+#define        IPG_RFI_FRAGLEN                         0xFFFF000000000000ULL
 
 /* I/O Register masks. */
 
index d0afeea..2ad1494 100644 (file)
@@ -867,7 +867,7 @@ static int txq_reclaim(struct tx_queue *txq, int budget, int force)
        struct netdev_queue *nq = netdev_get_tx_queue(mp->dev, txq->index);
        int reclaimed;
 
-       __netif_tx_lock(nq, smp_processor_id());
+       __netif_tx_lock_bh(nq);
 
        reclaimed = 0;
        while (reclaimed < budget && txq->tx_desc_count > 0) {
@@ -913,7 +913,7 @@ static int txq_reclaim(struct tx_queue *txq, int budget, int force)
                dev_kfree_skb(skb);
        }
 
-       __netif_tx_unlock(nq);
+       __netif_tx_unlock_bh(nq);
 
        if (reclaimed < budget)
                mp->work_tx &= ~(1 << txq->index);
@@ -2745,7 +2745,7 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
 
        INIT_WORK(&mp->tx_timeout_task, tx_timeout_task);
 
-       netif_napi_add(dev, &mp->napi, mv643xx_eth_poll, 128);
+       netif_napi_add(dev, &mp->napi, mv643xx_eth_poll, NAPI_POLL_WEIGHT);
 
        init_timer(&mp->rx_oom);
        mp->rx_oom.data = (unsigned long)mp;
index 1df56cc..0e572a5 100644 (file)
@@ -222,8 +222,6 @@ static int mlx4_comm_cmd_poll(struct mlx4_dev *dev, u8 cmd, u16 param,
                 * FLR process. The only non-zero result in the RESET command
                 * is MLX4_DELAY_RESET_SLAVE*/
                if ((MLX4_COMM_CMD_RESET == cmd)) {
-                       mlx4_warn(dev, "Got slave FLRed from Communication"
-                                 " channel (ret:0x%x)\n", ret_from_pending);
                        err = MLX4_DELAY_RESET_SLAVE;
                } else {
                        mlx4_warn(dev, "Communication channel timed out\n");
index b35f947..89c47ea 100644 (file)
@@ -1323,6 +1323,7 @@ static void mlx4_en_auto_moderation(struct mlx4_en_priv *priv)
                        priv->last_moder_time[ring] = moder_time;
                        cq = &priv->rx_cq[ring];
                        cq->moder_time = moder_time;
+                       cq->moder_cnt = priv->rx_frames;
                        err = mlx4_en_set_cq_moder(priv, cq);
                        if (err)
                                en_err(priv, "Failed modifying moderation for cq:%d\n",
@@ -2118,6 +2119,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
        struct mlx4_en_priv *priv;
        int i;
        int err;
+       u64 mac_u64;
 
        dev = alloc_etherdev_mqs(sizeof(struct mlx4_en_priv),
                                 MAX_TX_RINGS, MAX_RX_RINGS);
@@ -2191,10 +2193,17 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
        dev->addr_len = ETH_ALEN;
        mlx4_en_u64_to_mac(dev->dev_addr, mdev->dev->caps.def_mac[priv->port]);
        if (!is_valid_ether_addr(dev->dev_addr)) {
-               en_err(priv, "Port: %d, invalid mac burned: %pM, quiting\n",
-                      priv->port, dev->dev_addr);
-               err = -EINVAL;
-               goto out;
+               if (mlx4_is_slave(priv->mdev->dev)) {
+                       eth_hw_addr_random(dev);
+                       en_warn(priv, "Assigned random MAC address %pM\n", dev->dev_addr);
+                       mac_u64 = mlx4_en_mac_to_u64(dev->dev_addr);
+                       mdev->dev->caps.def_mac[priv->port] = mac_u64;
+               } else {
+                       en_err(priv, "Port: %d, invalid mac burned: %pM, quiting\n",
+                              priv->port, dev->dev_addr);
+                       err = -EINVAL;
+                       goto out;
+               }
        }
 
        memcpy(priv->prev_mac, dev->dev_addr, sizeof(priv->prev_mac));
index 91f2b2c..d3f5086 100644 (file)
@@ -60,7 +60,7 @@ void mlx4_en_fill_qp_context(struct mlx4_en_priv *priv, int size, int stride,
        context->pri_path.sched_queue = 0x83 | (priv->port - 1) << 6;
        if (user_prio >= 0) {
                context->pri_path.sched_queue |= user_prio << 3;
-               context->pri_path.feup = 1 << 6;
+               context->pri_path.feup = MLX4_FEUP_FORCE_ETH_UP;
        }
        context->pri_path.counter_index = 0xff;
        context->cqn_send = cpu_to_be32(cqn);
index b147bdd..2c97901 100644 (file)
@@ -131,7 +131,9 @@ static void dump_dev_cap_flags2(struct mlx4_dev *dev, u64 flags)
                [2] = "RSS XOR Hash Function support",
                [3] = "Device manage flow steering support",
                [4] = "Automatic MAC reassignment support",
-               [5] = "Time stamping support"
+               [5] = "Time stamping support",
+               [6] = "VST (control vlan insertion/stripping) support",
+               [7] = "FSM (MAC anti-spoofing) support"
        };
        int i;
 
@@ -838,12 +840,16 @@ int mlx4_QUERY_PORT_wrapper(struct mlx4_dev *dev, int slave,
                           MLX4_CMD_NATIVE);
 
        if (!err && dev->caps.function != slave) {
-               /* set slave default_mac address */
-               MLX4_GET(def_mac, outbox->buf, QUERY_PORT_MAC_OFFSET);
-               def_mac += slave << 8;
                /* if config MAC in DB use it */
                if (priv->mfunc.master.vf_oper[slave].vport[vhcr->in_modifier].state.mac)
                        def_mac = priv->mfunc.master.vf_oper[slave].vport[vhcr->in_modifier].state.mac;
+               else {
+                       /* set slave default_mac address */
+                       MLX4_GET(def_mac, outbox->buf, QUERY_PORT_MAC_OFFSET);
+                       def_mac += slave << 8;
+                       priv->mfunc.master.vf_admin[slave].vport[vhcr->in_modifier].mac = def_mac;
+               }
+
                MLX4_PUT(outbox->buf, def_mac, QUERY_PORT_MAC_OFFSET);
 
                /* get port type - currently only eth is enabled */
index 0d32a82..2f4a260 100644 (file)
@@ -1290,7 +1290,6 @@ static int mlx4_init_slave(struct mlx4_dev *dev)
 {
        struct mlx4_priv *priv = mlx4_priv(dev);
        u64 dma = (u64) priv->mfunc.vhcr_dma;
-       int num_of_reset_retries = NUM_OF_RESET_RETRIES;
        int ret_from_reset = 0;
        u32 slave_read;
        u32 cmd_channel_ver;
@@ -1304,18 +1303,10 @@ static int mlx4_init_slave(struct mlx4_dev *dev)
         * NUM_OF_RESET_RETRIES times before leaving.*/
        if (ret_from_reset) {
                if (MLX4_DELAY_RESET_SLAVE == ret_from_reset) {
-                       msleep(SLEEP_TIME_IN_RESET);
-                       while (ret_from_reset && num_of_reset_retries) {
-                               mlx4_warn(dev, "slave is currently in the"
-                                         "middle of FLR. retrying..."
-                                         "(try num:%d)\n",
-                                         (NUM_OF_RESET_RETRIES -
-                                          num_of_reset_retries  + 1));
-                               ret_from_reset =
-                                       mlx4_comm_cmd(dev, MLX4_COMM_CMD_RESET,
-                                                     0, MLX4_COMM_TIME);
-                               num_of_reset_retries = num_of_reset_retries - 1;
-                       }
+                       mlx4_warn(dev, "slave is currently in the "
+                                 "middle of FLR. Deferring probe.\n");
+                       mutex_unlock(&priv->cmd.slave_cmd_mutex);
+                       return -EPROBE_DEFER;
                } else
                        goto err;
        }
@@ -1526,7 +1517,8 @@ static int mlx4_init_hca(struct mlx4_dev *dev)
        } else {
                err = mlx4_init_slave(dev);
                if (err) {
-                       mlx4_err(dev, "Failed to initialize slave\n");
+                       if (err != -EPROBE_DEFER)
+                               mlx4_err(dev, "Failed to initialize slave\n");
                        return err;
                }
 
index e12e0d2..1157f02 100644 (file)
@@ -372,24 +372,29 @@ static int update_vport_qp_param(struct mlx4_dev *dev,
                if (MLX4_QP_ST_RC == qp_type)
                        return -EINVAL;
 
+               /* force strip vlan by clear vsd */
+               qpc->param3 &= ~cpu_to_be32(MLX4_STRIP_VLAN);
+               if (0 != vp_oper->state.default_vlan) {
+                       qpc->pri_path.vlan_control =
+                               MLX4_VLAN_CTRL_ETH_TX_BLOCK_TAGGED |
+                               MLX4_VLAN_CTRL_ETH_RX_BLOCK_PRIO_TAGGED |
+                               MLX4_VLAN_CTRL_ETH_RX_BLOCK_UNTAGGED;
+               } else { /* priority tagged */
+                       qpc->pri_path.vlan_control =
+                               MLX4_VLAN_CTRL_ETH_TX_BLOCK_TAGGED |
+                               MLX4_VLAN_CTRL_ETH_RX_BLOCK_TAGGED;
+               }
+
+               qpc->pri_path.fvl_rx |= MLX4_FVL_RX_FORCE_ETH_VLAN;
                qpc->pri_path.vlan_index = vp_oper->vlan_idx;
-               qpc->pri_path.fl = (1 << 6) | (1 << 2); /* set cv bit and hide_cqe_vlan bit*/
-               qpc->pri_path.feup |= 1 << 3; /* set fvl bit */
+               qpc->pri_path.fl |= MLX4_FL_CV | MLX4_FL_ETH_HIDE_CQE_VLAN;
+               qpc->pri_path.feup |= MLX4_FEUP_FORCE_ETH_UP | MLX4_FVL_FORCE_ETH_VLAN;
                qpc->pri_path.sched_queue &= 0xC7;
                qpc->pri_path.sched_queue |= (vp_oper->state.default_qos) << 3;
-               mlx4_dbg(dev, "qp %d  port %d Q 0x%x set vlan to %d vidx %d feup %x fl %x\n",
-                        be32_to_cpu(qpc->local_qpn) & 0xffffff, port,
-                        (int)(qpc->pri_path.sched_queue), vp_oper->state.default_vlan,
-                        vp_oper->vlan_idx, (int)(qpc->pri_path.feup),
-                        (int)(qpc->pri_path.fl));
        }
        if (vp_oper->state.spoofchk) {
-               qpc->pri_path.feup |= 1 << 5; /* set fsm bit */;
+               qpc->pri_path.feup |= MLX4_FSM_FORCE_ETH_SRC_MAC;
                qpc->pri_path.grh_mylmc = (0x80 & qpc->pri_path.grh_mylmc) + vp_oper->mac_idx;
-               mlx4_dbg(dev, "spoof qp %d  port %d feup  0x%x, myLmc 0x%x mindx %d\n",
-                        be32_to_cpu(qpc->local_qpn) & 0xffffff, port,
-                        (int)qpc->pri_path.feup, (int)qpc->pri_path.grh_mylmc,
-                        vp_oper->mac_idx);
        }
        return 0;
 }
index 90c253b..c1b693c 100644 (file)
@@ -429,6 +429,7 @@ struct qlcnic_hardware_context {
 
        u16 port_type;
        u16 board_type;
+       u16 supported_type;
 
        u16 link_speed;
        u16 link_duplex;
@@ -906,8 +907,11 @@ struct qlcnic_ipaddr {
 #define QLCNIC_FW_HANG                 0x4000
 #define QLCNIC_FW_LRO_MSS_CAP          0x8000
 #define QLCNIC_TX_INTR_SHARED          0x10000
+#define QLCNIC_APP_CHANGED_FLAGS       0x20000
 #define QLCNIC_IS_MSI_FAMILY(adapter) \
        ((adapter)->flags & (QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED))
+#define QLCNIC_IS_TSO_CAPABLE(adapter)  \
+       ((adapter)->ahw->capabilities & QLCNIC_FW_CAPABILITY_TSO)
 
 #define QLCNIC_DEF_NUM_STS_DESC_RINGS  4
 #define QLCNIC_MSIX_TBL_SPACE          8192
@@ -1033,6 +1037,7 @@ struct qlcnic_adapter {
        spinlock_t rx_mac_learn_lock;
        u32 file_prd_off;       /*File fw product offset*/
        u32 fw_version;
+       u32 offload_flags;
        const struct firmware *fw;
 };
 
@@ -1514,6 +1519,7 @@ void qlcnic_create_diag_entries(struct qlcnic_adapter *adapter);
 void qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter);
 void qlcnic_82xx_add_sysfs(struct qlcnic_adapter *adapter);
 void qlcnic_82xx_remove_sysfs(struct qlcnic_adapter *adapter);
+int qlcnic_82xx_get_settings(struct qlcnic_adapter *, struct ethtool_cmd *);
 
 int qlcnicvf_config_bridged_mode(struct qlcnic_adapter *, u32);
 int qlcnicvf_config_led(struct qlcnic_adapter *, u32, u32);
@@ -1540,6 +1546,8 @@ void qlcnic_add_lb_filter(struct qlcnic_adapter *, struct sk_buff *, int, u16);
 int qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter);
 int qlcnic_read_mac_addr(struct qlcnic_adapter *);
 int qlcnic_setup_netdev(struct qlcnic_adapter *, struct net_device *, int);
+void qlcnic_set_netdev_features(struct qlcnic_adapter *,
+                               struct qlcnic_esw_func_cfg *);
 void qlcnic_sriov_vf_schedule_multi(struct net_device *);
 void qlcnic_vf_add_mc_list(struct net_device *, u16);
 
index ea790a9..b4ff1e3 100644 (file)
@@ -696,15 +696,14 @@ u32 qlcnic_83xx_mac_rcode(struct qlcnic_adapter *adapter)
        return 1;
 }
 
-u32 qlcnic_83xx_mbx_poll(struct qlcnic_adapter *adapter)
+u32 qlcnic_83xx_mbx_poll(struct qlcnic_adapter *adapter, u32 *wait_time)
 {
        u32 data;
-       unsigned long wait_time = 0;
        struct qlcnic_hardware_context *ahw = adapter->ahw;
        /* wait for mailbox completion */
        do {
                data = QLCRDX(ahw, QLCNIC_FW_MBX_CTRL);
-               if (++wait_time > QLCNIC_MBX_TIMEOUT) {
+               if (++(*wait_time) > QLCNIC_MBX_TIMEOUT) {
                        data = QLCNIC_RCODE_TIMEOUT;
                        break;
                }
@@ -720,8 +719,8 @@ int qlcnic_83xx_mbx_op(struct qlcnic_adapter *adapter,
        u16 opcode;
        u8 mbx_err_code;
        unsigned long flags;
-       u32 rsp, mbx_val, fw_data, rsp_num, mbx_cmd;
        struct qlcnic_hardware_context *ahw = adapter->ahw;
+       u32 rsp, mbx_val, fw_data, rsp_num, mbx_cmd, wait_time = 0;
 
        opcode = LSW(cmd->req.arg[0]);
        if (!test_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status)) {
@@ -754,15 +753,13 @@ int qlcnic_83xx_mbx_op(struct qlcnic_adapter *adapter,
        /* Signal FW about the impending command */
        QLCWRX(ahw, QLCNIC_HOST_MBX_CTRL, QLCNIC_SET_OWNER);
 poll:
-       rsp = qlcnic_83xx_mbx_poll(adapter);
+       rsp = qlcnic_83xx_mbx_poll(adapter, &wait_time);
        if (rsp != QLCNIC_RCODE_TIMEOUT) {
                /* Get the FW response data */
                fw_data = readl(QLCNIC_MBX_FW(ahw, 0));
                if (fw_data &  QLCNIC_MBX_ASYNC_EVENT) {
                        __qlcnic_83xx_process_aen(adapter);
-                       mbx_val = QLCRDX(ahw, QLCNIC_HOST_MBX_CTRL);
-                       if (mbx_val)
-                               goto poll;
+                       goto poll;
                }
                mbx_err_code = QLCNIC_MBX_STATUS(fw_data);
                rsp_num = QLCNIC_MBX_NUM_REGS(fw_data);
@@ -1276,11 +1273,13 @@ out:
        return err;
 }
 
-static int qlcnic_83xx_diag_alloc_res(struct net_device *netdev, int test)
+static int qlcnic_83xx_diag_alloc_res(struct net_device *netdev, int test,
+                                     int num_sds_ring)
 {
        struct qlcnic_adapter *adapter = netdev_priv(netdev);
        struct qlcnic_host_sds_ring *sds_ring;
        struct qlcnic_host_rds_ring *rds_ring;
+       u16 adapter_state = adapter->is_up;
        u8 ring;
        int ret;
 
@@ -1304,6 +1303,10 @@ static int qlcnic_83xx_diag_alloc_res(struct net_device *netdev, int test)
        ret = qlcnic_fw_create_ctx(adapter);
        if (ret) {
                qlcnic_detach(adapter);
+               if (adapter_state == QLCNIC_ADAPTER_UP_MAGIC) {
+                       adapter->max_sds_rings = num_sds_ring;
+                       qlcnic_attach(adapter);
+               }
                netif_device_attach(netdev);
                return ret;
        }
@@ -1596,7 +1599,8 @@ int qlcnic_83xx_loopback_test(struct net_device *netdev, u8 mode)
        if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
                return -EBUSY;
 
-       ret = qlcnic_83xx_diag_alloc_res(netdev, QLCNIC_LOOPBACK_TEST);
+       ret = qlcnic_83xx_diag_alloc_res(netdev, QLCNIC_LOOPBACK_TEST,
+                                        max_sds_rings);
        if (ret)
                goto fail_diag_alloc;
 
@@ -2830,6 +2834,23 @@ int qlcnic_83xx_test_link(struct qlcnic_adapter *adapter)
                        break;
                }
                config = cmd.rsp.arg[3];
+               if (QLC_83XX_SFP_PRESENT(config)) {
+                       switch (ahw->module_type) {
+                       case LINKEVENT_MODULE_OPTICAL_UNKNOWN:
+                       case LINKEVENT_MODULE_OPTICAL_SRLR:
+                       case LINKEVENT_MODULE_OPTICAL_LRM:
+                       case LINKEVENT_MODULE_OPTICAL_SFP_1G:
+                               ahw->supported_type = PORT_FIBRE;
+                               break;
+                       case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE:
+                       case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN:
+                       case LINKEVENT_MODULE_TWINAX:
+                               ahw->supported_type = PORT_TP;
+                               break;
+                       default:
+                               ahw->supported_type = PORT_OTHER;
+                       }
+               }
                if (config & 1)
                        err = 1;
        }
@@ -2838,7 +2859,8 @@ out:
        return config;
 }
 
-int qlcnic_83xx_get_settings(struct qlcnic_adapter *adapter)
+int qlcnic_83xx_get_settings(struct qlcnic_adapter *adapter,
+                            struct ethtool_cmd *ecmd)
 {
        u32 config = 0;
        int status = 0;
@@ -2851,6 +2873,54 @@ int qlcnic_83xx_get_settings(struct qlcnic_adapter *adapter)
        ahw->module_type = QLC_83XX_SFP_MODULE_TYPE(config);
        /* hard code until there is a way to get it from flash */
        ahw->board_type = QLCNIC_BRDTYPE_83XX_10G;
+
+       if (netif_running(adapter->netdev) && ahw->has_link_events) {
+               ethtool_cmd_speed_set(ecmd, ahw->link_speed);
+               ecmd->duplex = ahw->link_duplex;
+               ecmd->autoneg = ahw->link_autoneg;
+       } else {
+               ethtool_cmd_speed_set(ecmd, SPEED_UNKNOWN);
+               ecmd->duplex = DUPLEX_UNKNOWN;
+               ecmd->autoneg = AUTONEG_DISABLE;
+       }
+
+       if (ahw->port_type == QLCNIC_XGBE) {
+               ecmd->supported = SUPPORTED_1000baseT_Full;
+               ecmd->advertising = ADVERTISED_1000baseT_Full;
+       } else {
+               ecmd->supported = (SUPPORTED_10baseT_Half |
+                                  SUPPORTED_10baseT_Full |
+                                  SUPPORTED_100baseT_Half |
+                                  SUPPORTED_100baseT_Full |
+                                  SUPPORTED_1000baseT_Half |
+                                  SUPPORTED_1000baseT_Full);
+               ecmd->advertising = (ADVERTISED_100baseT_Half |
+                                    ADVERTISED_100baseT_Full |
+                                    ADVERTISED_1000baseT_Half |
+                                    ADVERTISED_1000baseT_Full);
+       }
+
+       switch (ahw->supported_type) {
+       case PORT_FIBRE:
+               ecmd->supported |= SUPPORTED_FIBRE;
+               ecmd->advertising |= ADVERTISED_FIBRE;
+               ecmd->port = PORT_FIBRE;
+               ecmd->transceiver = XCVR_EXTERNAL;
+               break;
+       case PORT_TP:
+               ecmd->supported |= SUPPORTED_TP;
+               ecmd->advertising |= ADVERTISED_TP;
+               ecmd->port = PORT_TP;
+               ecmd->transceiver = XCVR_INTERNAL;
+               break;
+       default:
+               ecmd->supported |= SUPPORTED_FIBRE;
+               ecmd->advertising |= ADVERTISED_FIBRE;
+               ecmd->port = PORT_OTHER;
+               ecmd->transceiver = XCVR_EXTERNAL;
+               break;
+       }
+       ecmd->phy_address = ahw->physical_port;
        return status;
 }
 
@@ -3046,7 +3116,8 @@ int qlcnic_83xx_interrupt_test(struct net_device *netdev)
        if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
                return -EIO;
 
-       ret = qlcnic_83xx_diag_alloc_res(netdev, QLCNIC_INTERRUPT_TEST);
+       ret = qlcnic_83xx_diag_alloc_res(netdev, QLCNIC_INTERRUPT_TEST,
+                                        max_sds_rings);
        if (ret)
                goto fail_diag_irq;
 
index 1f1d85e..f5db67f 100644 (file)
@@ -603,7 +603,7 @@ int qlcnic_83xx_get_vnic_pf_info(struct qlcnic_adapter *, struct qlcnic_info *);
 
 void qlcnic_83xx_get_minidump_template(struct qlcnic_adapter *);
 void qlcnic_83xx_get_stats(struct qlcnic_adapter *adapter, u64 *data);
-int qlcnic_83xx_get_settings(struct qlcnic_adapter *);
+int qlcnic_83xx_get_settings(struct qlcnic_adapter *, struct ethtool_cmd *);
 int qlcnic_83xx_set_settings(struct qlcnic_adapter *, struct ethtool_cmd *);
 void qlcnic_83xx_get_pauseparam(struct qlcnic_adapter *,
                                struct ethtool_pauseparam *);
@@ -620,7 +620,7 @@ int qlcnic_83xx_flash_test(struct qlcnic_adapter *);
 int qlcnic_83xx_enable_flash_write(struct qlcnic_adapter *);
 int qlcnic_83xx_disable_flash_write(struct qlcnic_adapter *);
 u32 qlcnic_83xx_mac_rcode(struct qlcnic_adapter *);
-u32 qlcnic_83xx_mbx_poll(struct qlcnic_adapter *);
+u32 qlcnic_83xx_mbx_poll(struct qlcnic_adapter *, u32 *);
 void qlcnic_83xx_enable_mbx_poll(struct qlcnic_adapter *);
 void qlcnic_83xx_disable_mbx_poll(struct qlcnic_adapter *);
 #endif
index ab1d8d9..5e7fb1d 100644 (file)
@@ -382,8 +382,6 @@ static int qlcnic_83xx_idc_tx_soft_reset(struct qlcnic_adapter *adapter)
        clear_bit(__QLCNIC_RESETTING, &adapter->state);
        dev_err(&adapter->pdev->dev, "%s:\n", __func__);
 
-       adapter->netdev->trans_start = jiffies;
-
        return 0;
 }
 
@@ -435,10 +433,6 @@ static void qlcnic_83xx_idc_attach_driver(struct qlcnic_adapter *adapter)
        }
 done:
        netif_device_attach(netdev);
-       if (netif_running(netdev)) {
-               netif_carrier_on(netdev);
-               netif_wake_queue(netdev);
-       }
 }
 
 static int qlcnic_83xx_idc_enter_failed_state(struct qlcnic_adapter *adapter,
@@ -642,15 +636,21 @@ static int qlcnic_83xx_idc_reattach_driver(struct qlcnic_adapter *adapter)
 
 static void qlcnic_83xx_idc_update_idc_params(struct qlcnic_adapter *adapter)
 {
+       struct qlcnic_hardware_context *ahw = adapter->ahw;
+
        qlcnic_83xx_idc_update_drv_presence_reg(adapter, 1, 1);
-       clear_bit(__QLCNIC_RESETTING, &adapter->state);
        set_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status);
        qlcnic_83xx_idc_update_audit_reg(adapter, 0, 1);
        set_bit(QLC_83XX_MODULE_LOADED, &adapter->ahw->idc.status);
-       adapter->ahw->idc.quiesce_req = 0;
-       adapter->ahw->idc.delay = QLC_83XX_IDC_FW_POLL_DELAY;
-       adapter->ahw->idc.err_code = 0;
-       adapter->ahw->idc.collect_dump = 0;
+
+       ahw->idc.quiesce_req = 0;
+       ahw->idc.delay = QLC_83XX_IDC_FW_POLL_DELAY;
+       ahw->idc.err_code = 0;
+       ahw->idc.collect_dump = 0;
+       ahw->reset_context = 0;
+       adapter->tx_timeo_cnt = 0;
+
+       clear_bit(__QLCNIC_RESETTING, &adapter->state);
 }
 
 /**
@@ -851,6 +851,7 @@ static int qlcnic_83xx_idc_ready_state(struct qlcnic_adapter *adapter)
        /* Check for soft reset request */
        if (ahw->reset_context &&
            !(val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY)) {
+               adapter->ahw->reset_context = 0;
                qlcnic_83xx_idc_tx_soft_reset(adapter);
                return ret;
        }
@@ -914,6 +915,7 @@ static int qlcnic_83xx_idc_need_quiesce_state(struct qlcnic_adapter *adapter)
 static int qlcnic_83xx_idc_failed_state(struct qlcnic_adapter *adapter)
 {
        dev_err(&adapter->pdev->dev, "%s: please restart!!\n", __func__);
+       clear_bit(__QLCNIC_RESETTING, &adapter->state);
        adapter->ahw->idc.err_code = -EIO;
 
        return 0;
index 08efb46..f67652d 100644 (file)
@@ -131,12 +131,13 @@ static const char qlcnic_83xx_rx_stats_strings[][ETH_GSTRING_LEN] = {
        "ctx_lro_pkt_cnt",
        "ctx_ip_csum_error",
        "ctx_rx_pkts_wo_ctx",
-       "ctx_rx_pkts_dropped_wo_sts",
+       "ctx_rx_pkts_drop_wo_sds_on_card",
+       "ctx_rx_pkts_drop_wo_sds_on_host",
        "ctx_rx_osized_pkts",
        "ctx_rx_pkts_dropped_wo_rds",
        "ctx_rx_unexpected_mcast_pkts",
        "ctx_invalid_mac_address",
-       "ctx_rx_rds_ring_prim_attemoted",
+       "ctx_rx_rds_ring_prim_attempted",
        "ctx_rx_rds_ring_prim_success",
        "ctx_num_lro_flows_added",
        "ctx_num_lro_flows_removed",
@@ -251,6 +252,18 @@ static int
 qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
 {
        struct qlcnic_adapter *adapter = netdev_priv(dev);
+
+       if (qlcnic_82xx_check(adapter))
+               return qlcnic_82xx_get_settings(adapter, ecmd);
+       else if (qlcnic_83xx_check(adapter))
+               return qlcnic_83xx_get_settings(adapter, ecmd);
+
+       return -EIO;
+}
+
+int qlcnic_82xx_get_settings(struct qlcnic_adapter *adapter,
+                            struct ethtool_cmd *ecmd)
+{
        struct qlcnic_hardware_context *ahw = adapter->ahw;
        u32 speed, reg;
        int check_sfp_module = 0;
@@ -276,10 +289,7 @@ qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
 
        } else if (adapter->ahw->port_type == QLCNIC_XGBE) {
                u32 val = 0;
-               if (qlcnic_83xx_check(adapter))
-                       qlcnic_83xx_get_settings(adapter);
-               else
-                       val = QLCRD32(adapter, QLCNIC_PORT_MODE_ADDR);
+               val = QLCRD32(adapter, QLCNIC_PORT_MODE_ADDR);
 
                if (val == QLCNIC_PORT_MODE_802_3_AP) {
                        ecmd->supported = SUPPORTED_1000baseT_Full;
@@ -289,16 +299,13 @@ qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
                        ecmd->advertising = ADVERTISED_10000baseT_Full;
                }
 
-               if (netif_running(dev) && adapter->ahw->has_link_events) {
-                       if (qlcnic_82xx_check(adapter)) {
-                               reg = QLCRD32(adapter,
-                                             P3P_LINK_SPEED_REG(pcifn));
-                               speed = P3P_LINK_SPEED_VAL(pcifn, reg);
-                               ahw->link_speed = speed * P3P_LINK_SPEED_MHZ;
-                       }
-                       ethtool_cmd_speed_set(ecmd, adapter->ahw->link_speed);
-                       ecmd->autoneg = adapter->ahw->link_autoneg;
-                       ecmd->duplex = adapter->ahw->link_duplex;
+               if (netif_running(adapter->netdev) && ahw->has_link_events) {
+                       reg = QLCRD32(adapter, P3P_LINK_SPEED_REG(pcifn));
+                       speed = P3P_LINK_SPEED_VAL(pcifn, reg);
+                       ahw->link_speed = speed * P3P_LINK_SPEED_MHZ;
+                       ethtool_cmd_speed_set(ecmd, ahw->link_speed);
+                       ecmd->autoneg = ahw->link_autoneg;
+                       ecmd->duplex = ahw->link_duplex;
                        goto skip;
                }
 
@@ -340,8 +347,8 @@ skip:
        case QLCNIC_BRDTYPE_P3P_10G_SFP_QT:
                ecmd->advertising |= ADVERTISED_TP;
                ecmd->supported |= SUPPORTED_TP;
-               check_sfp_module = netif_running(dev) &&
-                                  adapter->ahw->has_link_events;
+               check_sfp_module = netif_running(adapter->netdev) &&
+                                  ahw->has_link_events;
        case QLCNIC_BRDTYPE_P3P_10G_XFP:
                ecmd->supported |= SUPPORTED_FIBRE;
                ecmd->advertising |= ADVERTISED_FIBRE;
@@ -355,8 +362,8 @@ skip:
                        ecmd->advertising |=
                                (ADVERTISED_FIBRE | ADVERTISED_TP);
                        ecmd->port = PORT_FIBRE;
-                       check_sfp_module = netif_running(dev) &&
-                                          adapter->ahw->has_link_events;
+                       check_sfp_module = netif_running(adapter->netdev) &&
+                                          ahw->has_link_events;
                } else {
                        ecmd->autoneg = AUTONEG_ENABLE;
                        ecmd->supported |= (SUPPORTED_TP | SUPPORTED_Autoneg);
@@ -365,13 +372,6 @@ skip:
                        ecmd->port = PORT_TP;
                }
                break;
-       case QLCNIC_BRDTYPE_83XX_10G:
-               ecmd->autoneg = AUTONEG_DISABLE;
-               ecmd->supported |= (SUPPORTED_FIBRE | SUPPORTED_TP);
-               ecmd->advertising |= (ADVERTISED_FIBRE | ADVERTISED_TP);
-               ecmd->port = PORT_FIBRE;
-               check_sfp_module = netif_running(dev) && ahw->has_link_events;
-               break;
        default:
                dev_err(&adapter->pdev->dev, "Unsupported board model %d\n",
                        adapter->ahw->board_type);
index 6a6512b..106a12f 100644 (file)
@@ -973,16 +973,57 @@ int qlcnic_change_mtu(struct net_device *netdev, int mtu)
        return rc;
 }
 
+static netdev_features_t qlcnic_process_flags(struct qlcnic_adapter *adapter,
+                                             netdev_features_t features)
+{
+       u32 offload_flags = adapter->offload_flags;
+
+       if (offload_flags & BIT_0) {
+               features |= NETIF_F_RXCSUM | NETIF_F_IP_CSUM |
+                           NETIF_F_IPV6_CSUM;
+               adapter->rx_csum = 1;
+               if (QLCNIC_IS_TSO_CAPABLE(adapter)) {
+                       if (!(offload_flags & BIT_1))
+                               features &= ~NETIF_F_TSO;
+                       else
+                               features |= NETIF_F_TSO;
+
+                       if (!(offload_flags & BIT_2))
+                               features &= ~NETIF_F_TSO6;
+                       else
+                               features |= NETIF_F_TSO6;
+               }
+       } else {
+               features &= ~(NETIF_F_RXCSUM |
+                             NETIF_F_IP_CSUM |
+                             NETIF_F_IPV6_CSUM);
+
+               if (QLCNIC_IS_TSO_CAPABLE(adapter))
+                       features &= ~(NETIF_F_TSO | NETIF_F_TSO6);
+               adapter->rx_csum = 0;
+       }
+
+       return features;
+}
 
 netdev_features_t qlcnic_fix_features(struct net_device *netdev,
        netdev_features_t features)
 {
        struct qlcnic_adapter *adapter = netdev_priv(netdev);
+       netdev_features_t changed;
 
-       if ((adapter->flags & QLCNIC_ESWITCH_ENABLED) &&
-           qlcnic_82xx_check(adapter)) {
-               netdev_features_t changed = features ^ netdev->features;
-               features ^= changed & (NETIF_F_ALL_CSUM | NETIF_F_RXCSUM);
+       if (qlcnic_82xx_check(adapter) &&
+           (adapter->flags & QLCNIC_ESWITCH_ENABLED)) {
+               if (adapter->flags & QLCNIC_APP_CHANGED_FLAGS) {
+                       features = qlcnic_process_flags(adapter, features);
+               } else {
+                       changed = features ^ netdev->features;
+                       features ^= changed & (NETIF_F_RXCSUM |
+                                              NETIF_F_IP_CSUM |
+                                              NETIF_F_IPV6_CSUM |
+                                              NETIF_F_TSO |
+                                              NETIF_F_TSO6);
+               }
        }
 
        if (!(features & NETIF_F_RXCSUM))
index 95b1b57..b6818f4 100644 (file)
@@ -134,7 +134,7 @@ struct qlcnic_mailbox_metadata {
 
 #define QLCNIC_SET_OWNER        1
 #define QLCNIC_CLR_OWNER        0
-#define QLCNIC_MBX_TIMEOUT      10000
+#define QLCNIC_MBX_TIMEOUT      5000
 
 #define QLCNIC_MBX_RSP_OK      1
 #define QLCNIC_MBX_PORT_RSP_OK 0x1a
index 264d5a4..aeb26a8 100644 (file)
@@ -37,24 +37,24 @@ MODULE_PARM_DESC(qlcnic_mac_learn,
                 "Mac Filter (0=learning is disabled, 1=Driver learning is enabled, 2=FDB learning is enabled)");
 
 int qlcnic_use_msi = 1;
-MODULE_PARM_DESC(use_msi, "MSI interrupt (0=disabled, 1=enabled");
+MODULE_PARM_DESC(use_msi, "MSI interrupt (0=disabled, 1=enabled)");
 module_param_named(use_msi, qlcnic_use_msi, int, 0444);
 
 int qlcnic_use_msi_x = 1;
-MODULE_PARM_DESC(use_msi_x, "MSI-X interrupt (0=disabled, 1=enabled");
+MODULE_PARM_DESC(use_msi_x, "MSI-X interrupt (0=disabled, 1=enabled)");
 module_param_named(use_msi_x, qlcnic_use_msi_x, int, 0444);
 
 int qlcnic_auto_fw_reset = 1;
-MODULE_PARM_DESC(auto_fw_reset, "Auto firmware reset (0=disabled, 1=enabled");
+MODULE_PARM_DESC(auto_fw_reset, "Auto firmware reset (0=disabled, 1=enabled)");
 module_param_named(auto_fw_reset, qlcnic_auto_fw_reset, int, 0644);
 
 int qlcnic_load_fw_file;
-MODULE_PARM_DESC(load_fw_file, "Load firmware from (0=flash, 1=file");
+MODULE_PARM_DESC(load_fw_file, "Load firmware from (0=flash, 1=file)");
 module_param_named(load_fw_file, qlcnic_load_fw_file, int, 0444);
 
 int qlcnic_config_npars;
 module_param(qlcnic_config_npars, int, 0444);
-MODULE_PARM_DESC(qlcnic_config_npars, "Configure NPARs (0=disabled, 1=enabled");
+MODULE_PARM_DESC(qlcnic_config_npars, "Configure NPARs (0=disabled, 1=enabled)");
 
 static int qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
 static void qlcnic_remove(struct pci_dev *pdev);
@@ -84,14 +84,9 @@ static int qlcnic_start_firmware(struct qlcnic_adapter *);
 static void qlcnic_free_lb_filters_mem(struct qlcnic_adapter *adapter);
 static void qlcnic_dev_set_npar_ready(struct qlcnic_adapter *);
 static int qlcnicvf_start_firmware(struct qlcnic_adapter *);
-static void qlcnic_set_netdev_features(struct qlcnic_adapter *,
-                               struct qlcnic_esw_func_cfg *);
 static int qlcnic_vlan_rx_add(struct net_device *, __be16, u16);
 static int qlcnic_vlan_rx_del(struct net_device *, __be16, u16);
 
-#define QLCNIC_IS_TSO_CAPABLE(adapter) \
-       ((adapter)->ahw->capabilities & QLCNIC_FW_CAPABILITY_TSO)
-
 static u32 qlcnic_vlan_tx_check(struct qlcnic_adapter *adapter)
 {
        struct qlcnic_hardware_context *ahw = adapter->ahw;
@@ -308,6 +303,23 @@ int qlcnic_read_mac_addr(struct qlcnic_adapter *adapter)
        return 0;
 }
 
+static void qlcnic_delete_adapter_mac(struct qlcnic_adapter *adapter)
+{
+       struct qlcnic_mac_list_s *cur;
+       struct list_head *head;
+
+       list_for_each(head, &adapter->mac_list) {
+               cur = list_entry(head, struct qlcnic_mac_list_s, list);
+               if (!memcmp(adapter->mac_addr, cur->mac_addr, ETH_ALEN)) {
+                       qlcnic_sre_macaddr_change(adapter, cur->mac_addr,
+                                                 0, QLCNIC_MAC_DEL);
+                       list_del(&cur->list);
+                       kfree(cur);
+                       return;
+               }
+       }
+}
+
 static int qlcnic_set_mac(struct net_device *netdev, void *p)
 {
        struct qlcnic_adapter *adapter = netdev_priv(netdev);
@@ -322,11 +334,15 @@ static int qlcnic_set_mac(struct net_device *netdev, void *p)
        if (!is_valid_ether_addr(addr->sa_data))
                return -EINVAL;
 
+       if (!memcmp(adapter->mac_addr, addr->sa_data, ETH_ALEN))
+               return 0;
+
        if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
                netif_device_detach(netdev);
                qlcnic_napi_disable(adapter);
        }
 
+       qlcnic_delete_adapter_mac(adapter);
        memcpy(adapter->mac_addr, addr->sa_data, netdev->addr_len);
        memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
        qlcnic_set_multi(adapter->netdev);
@@ -1053,8 +1069,6 @@ void qlcnic_set_eswitch_port_features(struct qlcnic_adapter *adapter,
 
        if (!esw_cfg->promisc_mode)
                adapter->flags |= QLCNIC_PROMISC_DISABLED;
-
-       qlcnic_set_netdev_features(adapter, esw_cfg);
 }
 
 int qlcnic_set_eswitch_port_config(struct qlcnic_adapter *adapter)
@@ -1069,51 +1083,23 @@ int qlcnic_set_eswitch_port_config(struct qlcnic_adapter *adapter)
                        return -EIO;
        qlcnic_set_vlan_config(adapter, &esw_cfg);
        qlcnic_set_eswitch_port_features(adapter, &esw_cfg);
+       qlcnic_set_netdev_features(adapter, &esw_cfg);
 
        return 0;
 }
 
-static void
-qlcnic_set_netdev_features(struct qlcnic_adapter *adapter,
-               struct qlcnic_esw_func_cfg *esw_cfg)
+void qlcnic_set_netdev_features(struct qlcnic_adapter *adapter,
+                               struct qlcnic_esw_func_cfg *esw_cfg)
 {
        struct net_device *netdev = adapter->netdev;
-       unsigned long features, vlan_features;
 
        if (qlcnic_83xx_check(adapter))
                return;
 
-       features = (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_RXCSUM |
-                   NETIF_F_IPV6_CSUM | NETIF_F_GRO);
-       vlan_features = (NETIF_F_SG | NETIF_F_IP_CSUM |
-                       NETIF_F_IPV6_CSUM);
-
-       if (QLCNIC_IS_TSO_CAPABLE(adapter)) {
-               features |= (NETIF_F_TSO | NETIF_F_TSO6);
-               vlan_features |= (NETIF_F_TSO | NETIF_F_TSO6);
-       }
-
-       if (netdev->features & NETIF_F_LRO)
-               features |= NETIF_F_LRO;
-
-       if (esw_cfg->offload_flags & BIT_0) {
-               netdev->features |= features;
-               adapter->rx_csum = 1;
-               if (!(esw_cfg->offload_flags & BIT_1)) {
-                       netdev->features &= ~NETIF_F_TSO;
-                       features &= ~NETIF_F_TSO;
-               }
-               if (!(esw_cfg->offload_flags & BIT_2)) {
-                       netdev->features &= ~NETIF_F_TSO6;
-                       features &= ~NETIF_F_TSO6;
-               }
-       } else {
-               netdev->features &= ~features;
-               features &= ~features;
-               adapter->rx_csum = 0;
-       }
-
-       netdev->vlan_features = (features & vlan_features);
+       adapter->offload_flags = esw_cfg->offload_flags;
+       adapter->flags |= QLCNIC_APP_CHANGED_FLAGS;
+       netdev_update_features(netdev);
+       adapter->flags &= ~QLCNIC_APP_CHANGED_FLAGS;
 }
 
 static int
@@ -1995,8 +1981,10 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        pci_enable_pcie_error_reporting(pdev);
 
        ahw = kzalloc(sizeof(struct qlcnic_hardware_context), GFP_KERNEL);
-       if (!ahw)
+       if (!ahw) {
+               err = -ENOMEM;
                goto err_out_free_res;
+       }
 
        switch (ent->device) {
        case PCI_DEVICE_ID_QLOGIC_QLE824X:
@@ -2032,6 +2020,7 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        adapter->qlcnic_wq = create_singlethread_workqueue("qlcnic");
        if (adapter->qlcnic_wq == NULL) {
+               err = -ENOMEM;
                dev_err(&pdev->dev, "Failed to create workqueue\n");
                goto err_out_free_netdev;
        }
@@ -2112,6 +2101,10 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                        goto err_out_disable_msi;
        }
 
+       err = qlcnic_get_act_pci_func(adapter);
+       if (err)
+               goto err_out_disable_mbx_intr;
+
        err = qlcnic_setup_netdev(adapter, netdev, pci_using_dac);
        if (err)
                goto err_out_disable_mbx_intr;
@@ -2141,9 +2134,6 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                break;
        }
 
-       if (qlcnic_get_act_pci_func(adapter))
-               goto err_out_disable_mbx_intr;
-
        if (adapter->drv_mac_learn)
                qlcnic_alloc_lb_filters_mem(adapter);
 
@@ -2481,12 +2471,17 @@ static void qlcnic_tx_timeout(struct net_device *netdev)
        if (test_bit(__QLCNIC_RESETTING, &adapter->state))
                return;
 
-       dev_err(&netdev->dev, "transmit timeout, resetting.\n");
-
-       if (++adapter->tx_timeo_cnt >= QLCNIC_MAX_TX_TIMEOUTS)
-               adapter->need_fw_reset = 1;
-       else
+       if (++adapter->tx_timeo_cnt >= QLCNIC_MAX_TX_TIMEOUTS) {
+               netdev_info(netdev, "Tx timeout, reset the adapter.\n");
+               if (qlcnic_82xx_check(adapter))
+                       adapter->need_fw_reset = 1;
+               else if (qlcnic_83xx_check(adapter))
+                       qlcnic_83xx_idc_request_reset(adapter,
+                                                     QLCNIC_FORCE_FW_DUMP_KEY);
+       } else {
+               netdev_info(netdev, "Tx timeout, reset adapter context.\n");
                adapter->ahw->reset_context = 1;
+       }
 }
 
 static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev)
@@ -3123,10 +3118,8 @@ qlcnic_check_health(struct qlcnic_adapter *adapter)
                if (adapter->need_fw_reset)
                        goto detach;
 
-               if (adapter->ahw->reset_context && qlcnic_auto_fw_reset) {
+               if (adapter->ahw->reset_context && qlcnic_auto_fw_reset)
                        qlcnic_reset_hw_context(adapter);
-                       adapter->netdev->trans_start = jiffies;
-               }
 
                return 0;
        }
index 44d547d..196b2d1 100644 (file)
@@ -280,9 +280,9 @@ void qlcnic_sriov_cleanup(struct qlcnic_adapter *adapter)
 static int qlcnic_sriov_post_bc_msg(struct qlcnic_adapter *adapter, u32 *hdr,
                                    u32 *pay, u8 pci_func, u8 size)
 {
+       u32 rsp, mbx_val, fw_data, rsp_num, mbx_cmd, val, wait_time = 0;
        struct qlcnic_hardware_context *ahw = adapter->ahw;
        unsigned long flags;
-       u32 rsp, mbx_val, fw_data, rsp_num, mbx_cmd, val;
        u16 opcode;
        u8 mbx_err_code;
        int i, j;
@@ -330,15 +330,13 @@ static int qlcnic_sriov_post_bc_msg(struct qlcnic_adapter *adapter, u32 *hdr,
         * assume something is wrong.
         */
 poll:
-       rsp = qlcnic_83xx_mbx_poll(adapter);
+       rsp = qlcnic_83xx_mbx_poll(adapter, &wait_time);
        if (rsp != QLCNIC_RCODE_TIMEOUT) {
                /* Get the FW response data */
                fw_data = readl(QLCNIC_MBX_FW(ahw, 0));
                if (fw_data &  QLCNIC_MBX_ASYNC_EVENT) {
                        __qlcnic_83xx_process_aen(adapter);
-                       mbx_val = QLCRDX(ahw, QLCNIC_HOST_MBX_CTRL);
-                       if (mbx_val)
-                               goto poll;
+                       goto poll;
                }
                mbx_err_code = QLCNIC_MBX_STATUS(fw_data);
                rsp_num = QLCNIC_MBX_NUM_REGS(fw_data);
@@ -1736,7 +1734,6 @@ static int qlcnic_sriov_vf_handle_context_reset(struct qlcnic_adapter *adapter)
 
        if (!qlcnic_sriov_vf_reinit_driver(adapter)) {
                qlcnic_sriov_vf_attach(adapter);
-               adapter->netdev->trans_start = jiffies;
                adapter->tx_timeo_cnt = 0;
                adapter->reset_ctx_cnt = 0;
                adapter->fw_fail_cnt = 0;
index c81be2d..1a66ccd 100644 (file)
@@ -1133,9 +1133,6 @@ static int qlcnic_sriov_validate_linkevent(struct qlcnic_vf_info *vf,
        if ((cmd->req.arg[1] >> 16) != vf->rx_ctx_id)
                return -EINVAL;
 
-       if (!(cmd->req.arg[1] & BIT_8))
-               return -EINVAL;
-
        return 0;
 }
 
index 4e22e79..e7a2fe2 100644 (file)
@@ -544,6 +544,9 @@ static ssize_t qlcnic_sysfs_write_esw_config(struct file *file,
                switch (esw_cfg[i].op_mode) {
                case QLCNIC_PORT_DEFAULTS:
                        qlcnic_set_eswitch_port_features(adapter, &esw_cfg[i]);
+                       rtnl_lock();
+                       qlcnic_set_netdev_features(adapter, &esw_cfg[i]);
+                       rtnl_unlock();
                        break;
                case QLCNIC_ADD_VLAN:
                        qlcnic_set_vlan_config(adapter, &esw_cfg[i]);
index 87463bc..f87cc21 100644 (file)
@@ -1106,6 +1106,7 @@ static int ql_get_next_chunk(struct ql_adapter *qdev, struct rx_ring *rx_ring,
                if (pci_dma_mapping_error(qdev->pdev, map)) {
                        __free_pages(rx_ring->pg_chunk.page,
                                        qdev->lbq_buf_order);
+                       rx_ring->pg_chunk.page = NULL;
                        netif_err(qdev, drv, qdev->ndev,
                                  "PCI mapping failed.\n");
                        return -ENOMEM;
@@ -2777,6 +2778,12 @@ static void ql_free_lbq_buffers(struct ql_adapter *qdev, struct rx_ring *rx_ring
                        curr_idx = 0;
 
        }
+       if (rx_ring->pg_chunk.page) {
+               pci_unmap_page(qdev->pdev, rx_ring->pg_chunk.map,
+                       ql_lbq_block_size(qdev), PCI_DMA_FROMDEVICE);
+               put_page(rx_ring->pg_chunk.page);
+               rx_ring->pg_chunk.page = NULL;
+       }
 }
 
 static void ql_free_sbq_buffers(struct ql_adapter *qdev, struct rx_ring *rx_ring)
@@ -4710,6 +4717,7 @@ static int qlge_probe(struct pci_dev *pdev,
                dev_err(&pdev->dev, "net device registration failed.\n");
                ql_release_all(pdev);
                pci_disable_device(pdev);
+               free_netdev(ndev);
                return err;
        }
        /* Start up the timer to trigger EEH if
index 7d1fb9a..0352345 100644 (file)
@@ -1136,6 +1136,7 @@ static void cp_clean_rings (struct cp_private *cp)
                        cp->dev->stats.tx_dropped++;
                }
        }
+       netdev_reset_queue(cp->dev);
 
        memset(cp->rx_ring, 0, sizeof(struct cp_desc) * CP_RX_RING_SIZE);
        memset(cp->tx_ring, 0, sizeof(struct cp_desc) * CP_TX_RING_SIZE);
index 79c520b..393f961 100644 (file)
@@ -5856,7 +5856,20 @@ err_out:
        return -EIO;
 }
 
-static inline void rtl8169_tso_csum(struct rtl8169_private *tp,
+static bool rtl_skb_pad(struct sk_buff *skb)
+{
+       if (skb_padto(skb, ETH_ZLEN))
+               return false;
+       skb_put(skb, ETH_ZLEN - skb->len);
+       return true;
+}
+
+static bool rtl_test_hw_pad_bug(struct rtl8169_private *tp, struct sk_buff *skb)
+{
+       return skb->len < ETH_ZLEN && tp->mac_version == RTL_GIGA_MAC_VER_34;
+}
+
+static inline bool rtl8169_tso_csum(struct rtl8169_private *tp,
                                    struct sk_buff *skb, u32 *opts)
 {
        const struct rtl_tx_desc_info *info = tx_desc_info + tp->txd_version;
@@ -5869,13 +5882,20 @@ static inline void rtl8169_tso_csum(struct rtl8169_private *tp,
        } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
                const struct iphdr *ip = ip_hdr(skb);
 
+               if (unlikely(rtl_test_hw_pad_bug(tp, skb)))
+                       return skb_checksum_help(skb) == 0 && rtl_skb_pad(skb);
+
                if (ip->protocol == IPPROTO_TCP)
                        opts[offset] |= info->checksum.tcp;
                else if (ip->protocol == IPPROTO_UDP)
                        opts[offset] |= info->checksum.udp;
                else
                        WARN_ON_ONCE(1);
+       } else {
+               if (unlikely(rtl_test_hw_pad_bug(tp, skb)))
+                       return rtl_skb_pad(skb);
        }
+       return true;
 }
 
 static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
@@ -5896,17 +5916,15 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
                goto err_stop_0;
        }
 
-       /* 8168evl does not automatically pad to minimum length. */
-       if (unlikely(tp->mac_version == RTL_GIGA_MAC_VER_34 &&
-                    skb->len < ETH_ZLEN)) {
-               if (skb_padto(skb, ETH_ZLEN))
-                       goto err_update_stats;
-               skb_put(skb, ETH_ZLEN - skb->len);
-       }
-
        if (unlikely(le32_to_cpu(txd->opts1) & DescOwn))
                goto err_stop_0;
 
+       opts[1] = cpu_to_le32(rtl8169_tx_vlan_tag(skb));
+       opts[0] = DescOwn;
+
+       if (!rtl8169_tso_csum(tp, skb, opts))
+               goto err_update_stats;
+
        len = skb_headlen(skb);
        mapping = dma_map_single(d, skb->data, len, DMA_TO_DEVICE);
        if (unlikely(dma_mapping_error(d, mapping))) {
@@ -5918,11 +5936,6 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
        tp->tx_skb[entry].len = len;
        txd->addr = cpu_to_le64(mapping);
 
-       opts[1] = cpu_to_le32(rtl8169_tx_vlan_tag(skb));
-       opts[0] = DescOwn;
-
-       rtl8169_tso_csum(tp, skb, opts);
-
        frags = rtl8169_xmit_frags(tp, skb, opts);
        if (frags < 0)
                goto err_dma_1;
index 33dc6f2..b4479b5 100644 (file)
@@ -897,8 +897,8 @@ static int sh_eth_check_reset(struct net_device *ndev)
                mdelay(1);
                cnt--;
        }
-       if (cnt < 0) {
-               pr_err("Device reset fail\n");
+       if (cnt <= 0) {
+               pr_err("Device reset failed\n");
                ret = -ETIMEDOUT;
        }
        return ret;
@@ -2745,11 +2745,6 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
        if (mdp->cd->tsu) {
                struct resource *rtsu;
                rtsu = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-               if (!rtsu) {
-                       dev_err(&pdev->dev, "Not found TSU resource\n");
-                       ret = -ENODEV;
-                       goto out_release;
-               }
                mdp->tsu_addr = devm_ioremap_resource(&pdev->dev, rtsu);
                if (IS_ERR(mdp->tsu_addr)) {
                        ret = PTR_ERR(mdp->tsu_addr);
index 01b9920..39e4cb3 100644 (file)
@@ -638,14 +638,16 @@ static void efx_start_datapath(struct efx_nic *efx)
                           EFX_MAX_FRAME_LEN(efx->net_dev->mtu) +
                           efx->type->rx_buffer_padding);
        rx_buf_len = (sizeof(struct efx_rx_page_state) +
-                     EFX_PAGE_IP_ALIGN + efx->rx_dma_len);
+                     NET_IP_ALIGN + efx->rx_dma_len);
        if (rx_buf_len <= PAGE_SIZE) {
                efx->rx_scatter = false;
                efx->rx_buffer_order = 0;
        } else if (efx->type->can_rx_scatter) {
+               BUILD_BUG_ON(EFX_RX_USR_BUF_SIZE % L1_CACHE_BYTES);
                BUILD_BUG_ON(sizeof(struct efx_rx_page_state) +
-                            EFX_PAGE_IP_ALIGN + EFX_RX_USR_BUF_SIZE >
-                            PAGE_SIZE / 2);
+                            2 * ALIGN(NET_IP_ALIGN + EFX_RX_USR_BUF_SIZE,
+                                      EFX_RX_BUF_ALIGNMENT) >
+                            PAGE_SIZE);
                efx->rx_scatter = true;
                efx->rx_dma_len = EFX_RX_USR_BUF_SIZE;
                efx->rx_buffer_order = 0;
index 9bd433a..39d6bd7 100644 (file)
 /* Maximum possible MTU the driver supports */
 #define EFX_MAX_MTU (9 * 1024)
 
-/* Size of an RX scatter buffer.  Small enough to pack 2 into a 4K page. */
-#define EFX_RX_USR_BUF_SIZE 1824
+/* Size of an RX scatter buffer.  Small enough to pack 2 into a 4K page,
+ * and should be a multiple of the cache line size.
+ */
+#define EFX_RX_USR_BUF_SIZE    (2048 - 256)
+
+/* If possible, we should ensure cache line alignment at start and end
+ * of every buffer.  Otherwise, we just need to ensure 4-byte
+ * alignment of the network header.
+ */
+#if NET_IP_ALIGN == 0
+#define EFX_RX_BUF_ALIGNMENT   L1_CACHE_BYTES
+#else
+#define EFX_RX_BUF_ALIGNMENT   4
+#endif
 
 /* Forward declare Precision Time Protocol (PTP) support structure. */
 struct efx_ptp_data;
@@ -467,25 +479,12 @@ enum nic_state {
        STATE_RECOVERY = 3,     /* device recovering from PCI error */
 };
 
-/*
- * Alignment of page-allocated RX buffers
- *
- * Controls the number of bytes inserted at the start of an RX buffer.
- * This is the equivalent of NET_IP_ALIGN [which controls the alignment
- * of the skb->head for hardware DMA].
- */
-#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
-#define EFX_PAGE_IP_ALIGN 0
-#else
-#define EFX_PAGE_IP_ALIGN NET_IP_ALIGN
-#endif
-
 /*
  * Alignment of the skb->head which wraps a page-allocated RX buffer
  *
  * The skb allocated to wrap an rx_buffer can have this alignment. Since
  * the data is memcpy'd from the rx_buf, it does not need to be equal to
- * EFX_PAGE_IP_ALIGN.
+ * NET_IP_ALIGN.
  */
 #define EFX_PAGE_SKB_ALIGN 2
 
index e73e30b..a7dfe36 100644 (file)
@@ -93,8 +93,8 @@ static inline void efx_sync_rx_buffer(struct efx_nic *efx,
 
 void efx_rx_config_page_split(struct efx_nic *efx)
 {
-       efx->rx_page_buf_step = ALIGN(efx->rx_dma_len + EFX_PAGE_IP_ALIGN,
-                                     L1_CACHE_BYTES);
+       efx->rx_page_buf_step = ALIGN(efx->rx_dma_len + NET_IP_ALIGN,
+                                     EFX_RX_BUF_ALIGNMENT);
        efx->rx_bufs_per_page = efx->rx_buffer_order ? 1 :
                ((PAGE_SIZE - sizeof(struct efx_rx_page_state)) /
                 efx->rx_page_buf_step);
@@ -188,9 +188,9 @@ static int efx_init_rx_buffers(struct efx_rx_queue *rx_queue)
                do {
                        index = rx_queue->added_count & rx_queue->ptr_mask;
                        rx_buf = efx_rx_buffer(rx_queue, index);
-                       rx_buf->dma_addr = dma_addr + EFX_PAGE_IP_ALIGN;
+                       rx_buf->dma_addr = dma_addr + NET_IP_ALIGN;
                        rx_buf->page = page;
-                       rx_buf->page_offset = page_offset + EFX_PAGE_IP_ALIGN;
+                       rx_buf->page_offset = page_offset + NET_IP_ALIGN;
                        rx_buf->len = efx->rx_dma_len;
                        rx_buf->flags = 0;
                        ++rx_queue->added_count;
index f695a50..43c1f32 100644 (file)
@@ -1,6 +1,6 @@
 config STMMAC_ETH
        tristate "STMicroelectronics 10/100/1000 Ethernet driver"
-       depends on HAS_IOMEM
+       depends on HAS_IOMEM && HAS_DMA
        select NET_CORE
        select MII
        select PHYLIB
index 12aec17..b2275d1 100644 (file)
@@ -449,10 +449,9 @@ static int davinci_mdio_suspend(struct device *dev)
        __raw_writel(ctrl, &data->regs->control);
        wait_for_idle(data);
 
-       pm_runtime_put_sync(data->dev);
-
        data->suspended = true;
        spin_unlock(&data->lock);
+       pm_runtime_put_sync(data->dev);
 
        return 0;
 }
@@ -462,9 +461,9 @@ static int davinci_mdio_resume(struct device *dev)
        struct davinci_mdio_data *data = dev_get_drvdata(dev);
        u32 ctrl;
 
-       spin_lock(&data->lock);
        pm_runtime_get_sync(data->dev);
 
+       spin_lock(&data->lock);
        /* restart the scan state machine */
        ctrl = __raw_readl(&data->regs->control);
        ctrl |= CONTROL_ENABLE;
index 919b983..b7268b3 100644 (file)
@@ -946,7 +946,8 @@ static int xemaclite_open(struct net_device *dev)
                phy_write(lp->phy_dev, MII_CTRL1000, 0);
 
                /* Advertise only 10 and 100mbps full/half duplex speeds */
-               phy_write(lp->phy_dev, MII_ADVERTISE, ADVERTISE_ALL);
+               phy_write(lp->phy_dev, MII_ADVERTISE, ADVERTISE_ALL |
+                         ADVERTISE_CSMA);
 
                /* Restart auto negotiation */
                bmcr = phy_read(lp->phy_dev, MII_BMCR);
index 088c554..ab2307b 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/inetdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
+#include <linux/if_vlan.h>
 #include <linux/in.h>
 #include <linux/slab.h>
 #include <net/arp.h>
@@ -284,7 +285,7 @@ int netvsc_recv_callback(struct hv_device *device_obj,
 
        skb->protocol = eth_type_trans(skb, net);
        skb->ip_summed = CHECKSUM_NONE;
-       skb->vlan_tci = packet->vlan_tci;
+       __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), packet->vlan_tci);
 
        net->stats.rx_packets++;
        net->stats.rx_bytes += packet->total_data_buflen;
index d5a141c..1c502bb 100644 (file)
@@ -229,7 +229,8 @@ static rx_handler_result_t macvlan_handle_frame(struct sk_buff **pskb)
        }
 
        if (port->passthru)
-               vlan = list_first_entry(&port->vlans, struct macvlan_dev, list);
+               vlan = list_first_or_null_rcu(&port->vlans,
+                                             struct macvlan_dev, list);
        else
                vlan = macvlan_hash_lookup(port, eth->h_dest);
        if (vlan == NULL)
@@ -814,7 +815,7 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
        if (err < 0)
                goto upper_dev_unlink;
 
-       list_add_tail(&vlan->list, &port->vlans);
+       list_add_tail_rcu(&vlan->list, &port->vlans);
        netif_stacked_transfer_operstate(lowerdev, dev);
 
        return 0;
@@ -842,7 +843,7 @@ void macvlan_dellink(struct net_device *dev, struct list_head *head)
 {
        struct macvlan_dev *vlan = netdev_priv(dev);
 
-       list_del(&vlan->list);
+       list_del_rcu(&vlan->list);
        unregister_netdevice_queue(dev, head);
        netdev_upper_dev_unlink(vlan->lowerdev, dev);
 }
index ed947dd..f3cdf64 100644 (file)
@@ -375,6 +375,8 @@ static void ntb_netdev_remove(struct pci_dev *pdev)
        if (dev == NULL)
                return;
 
+       list_del(&dev->list);
+
        ndev = dev->ndev;
 
        unregister_netdev(ndev);
index c14f147..38f0b31 100644 (file)
@@ -1044,7 +1044,7 @@ int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable)
                adv = mmd_eee_adv_to_ethtool_adv_t(eee_adv);
                lp = mmd_eee_adv_to_ethtool_adv_t(eee_lp);
                idx = phy_find_setting(phydev->speed, phydev->duplex);
-               if ((lp & adv & settings[idx].setting))
+               if (!(lp & adv & settings[idx].setting))
                        goto eee_exit;
 
                if (clk_stop_enable) {
index 7c43261..b305105 100644 (file)
@@ -1092,8 +1092,8 @@ static int team_port_add(struct team *team, struct net_device *port_dev)
        }
 
        port->index = -1;
-       team_port_enable(team, port);
        list_add_tail_rcu(&port->list, &team->port_list);
+       team_port_enable(team, port);
        __team_compute_features(team);
        __team_port_change_port_added(port, !!netif_carrier_ok(port_dev));
        __team_options_change_check(team);
@@ -2374,7 +2374,8 @@ static int team_nl_send_port_list_get(struct team *team, u32 portid, u32 seq,
        bool incomplete;
        int i;
 
-       port = list_first_entry(&team->port_list, struct team_port, list);
+       port = list_first_entry_or_null(&team->port_list,
+                                       struct team_port, list);
 
 start_again:
        err = __send_and_alloc_skb(&skb, team, portid, send_func);
@@ -2402,8 +2403,8 @@ start_again:
                err = team_nl_fill_one_port_get(skb, one_port);
                if (err)
                        goto errout;
-       } else {
-               list_for_each_entry(port, &team->port_list, list) {
+       } else if (port) {
+               list_for_each_entry_from(port, &team->port_list, list) {
                        err = team_nl_fill_one_port_get(skb, port);
                        if (err) {
                                if (err == -EMSGSIZE) {
index 5ca14d4..7f032e2 100644 (file)
@@ -28,6 +28,8 @@ static bool rnd_transmit(struct team *team, struct sk_buff *skb)
 
        port_index = random_N(team->en_port_count);
        port = team_get_port_by_index_rcu(team, port_index);
+       if (unlikely(!port))
+               goto drop;
        port = team_get_first_port_txable_rcu(team, port);
        if (unlikely(!port))
                goto drop;
index d268e4d..472623f 100644 (file)
@@ -32,6 +32,8 @@ static bool rr_transmit(struct team *team, struct sk_buff *skb)
 
        port_index = rr_priv(team)->sent_packets++ % team->en_port_count;
        port = team_get_port_by_index_rcu(team, port_index);
+       if (unlikely(!port))
+               goto drop;
        port = team_get_first_port_txable_rcu(team, port);
        if (unlikely(!port))
                goto drop;
index f042b03..bfa9bb4 100644 (file)
@@ -352,7 +352,7 @@ static u16 tun_select_queue(struct net_device *dev, struct sk_buff *skb)
        u32 numqueues = 0;
 
        rcu_read_lock();
-       numqueues = tun->numqueues;
+       numqueues = ACCESS_ONCE(tun->numqueues);
 
        txq = skb_get_rxhash(skb);
        if (txq) {
@@ -1585,6 +1585,10 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
                else
                        return -EINVAL;
 
+               if (!!(ifr->ifr_flags & IFF_MULTI_QUEUE) !=
+                   !!(tun->flags & TUN_TAP_MQ))
+                       return -EINVAL;
+
                if (tun_not_capable(tun))
                        return -EPERM;
                err = security_tun_dev_open(tun->security);
@@ -2155,6 +2159,8 @@ static int tun_chr_open(struct inode *inode, struct file * file)
        set_bit(SOCK_EXTERNALLY_ALLOCATED, &tfile->socket.flags);
        INIT_LIST_HEAD(&tfile->next);
 
+       sock_set_flag(&tfile->sk, SOCK_ZEROCOPY);
+
        return 0;
 }
 
index 078795f..04ee044 100644 (file)
@@ -627,6 +627,12 @@ static const struct usb_device_id  products [] = {
        .driver_info = 0,
 },
 
+/* Huawei E1820 - handled by qmi_wwan */
+{
+       USB_DEVICE_INTERFACE_NUMBER(HUAWEI_VENDOR_ID, 0x14ac, 1),
+       .driver_info = 0,
+},
+
 /* Realtek RTL8152 Based USB 2.0 Ethernet Adapters */
 #if defined(CONFIG_USB_RTL8152) || defined(CONFIG_USB_RTL8152_MODULE)
 {
index cf887c2..d095d0d 100644 (file)
@@ -519,6 +519,7 @@ static const struct usb_device_id products[] = {
        /* 3. Combined interface devices matching on interface number */
        {QMI_FIXED_INTF(0x0408, 0xea42, 4)},    /* Yota / Megafon M100-1 */
        {QMI_FIXED_INTF(0x12d1, 0x140c, 1)},    /* Huawei E173 */
+       {QMI_FIXED_INTF(0x12d1, 0x14ac, 1)},    /* Huawei E1820 */
        {QMI_FIXED_INTF(0x19d2, 0x0002, 1)},
        {QMI_FIXED_INTF(0x19d2, 0x0012, 1)},
        {QMI_FIXED_INTF(0x19d2, 0x0017, 3)},
@@ -582,6 +583,7 @@ static const struct usb_device_id products[] = {
        {QMI_FIXED_INTF(0x1bbb, 0x011e, 4)},    /* Telekom Speedstick LTE II (Alcatel One Touch L100V LTE) */
        {QMI_FIXED_INTF(0x2357, 0x0201, 4)},    /* TP-LINK HSUPA Modem MA180 */
        {QMI_FIXED_INTF(0x1bc7, 0x1200, 5)},    /* Telit LE920 */
+       {QMI_FIXED_INTF(0x1e2d, 0x12d1, 4)},    /* Cinterion PLxx */
 
        /* 4. Gobi 1000 devices */
        {QMI_GOBI1K_DEVICE(0x05c6, 0x9212)},    /* Acer Gobi Modem Device */
index a491d3a..6cbdac6 100644 (file)
@@ -130,19 +130,23 @@ struct rtl8150 {
        struct usb_device *udev;
        struct tasklet_struct tl;
        struct net_device *netdev;
-       struct urb *rx_urb, *tx_urb, *intr_urb, *ctrl_urb;
+       struct urb *rx_urb, *tx_urb, *intr_urb;
        struct sk_buff *tx_skb, *rx_skb;
        struct sk_buff *rx_skb_pool[RX_SKB_POOL_SIZE];
        spinlock_t rx_pool_lock;
        struct usb_ctrlrequest dr;
        int intr_interval;
-       __le16 rx_creg;
        u8 *intr_buff;
        u8 phy;
 };
 
 typedef struct rtl8150 rtl8150_t;
 
+struct async_req {
+       struct usb_ctrlrequest dr;
+       u16 rx_creg;
+};
+
 static const char driver_name [] = "rtl8150";
 
 /*
@@ -164,51 +168,47 @@ static int set_registers(rtl8150_t * dev, u16 indx, u16 size, void *data)
                               indx, 0, data, size, 500);
 }
 
-static void ctrl_callback(struct urb *urb)
+static void async_set_reg_cb(struct urb *urb)
 {
-       rtl8150_t *dev;
+       struct async_req *req = (struct async_req *)urb->context;
        int status = urb->status;
 
-       switch (status) {
-       case 0:
-               break;
-       case -EINPROGRESS:
-               break;
-       case -ENOENT:
-               break;
-       default:
-               if (printk_ratelimit())
-                       dev_warn(&urb->dev->dev, "ctrl urb status %d\n", status);
-       }
-       dev = urb->context;
-       clear_bit(RX_REG_SET, &dev->flags);
+       if (status < 0)
+               dev_dbg(&urb->dev->dev, "%s failed with %d", __func__, status);
+       kfree(req);
+       usb_free_urb(urb);
 }
 
-static int async_set_registers(rtl8150_t * dev, u16 indx, u16 size)
+static int async_set_registers(rtl8150_t *dev, u16 indx, u16 size, u16 reg)
 {
-       int ret;
-
-       if (test_bit(RX_REG_SET, &dev->flags))
-               return -EAGAIN;
+       int res = -ENOMEM;
+       struct urb *async_urb;
+       struct async_req *req;
 
-       dev->dr.bRequestType = RTL8150_REQT_WRITE;
-       dev->dr.bRequest = RTL8150_REQ_SET_REGS;
-       dev->dr.wValue = cpu_to_le16(indx);
-       dev->dr.wIndex = 0;
-       dev->dr.wLength = cpu_to_le16(size);
-       dev->ctrl_urb->transfer_buffer_length = size;
-       usb_fill_control_urb(dev->ctrl_urb, dev->udev,
-                        usb_sndctrlpipe(dev->udev, 0), (char *) &dev->dr,
-                        &dev->rx_creg, size, ctrl_callback, dev);
-       if ((ret = usb_submit_urb(dev->ctrl_urb, GFP_ATOMIC))) {
-               if (ret == -ENODEV)
+       req = kmalloc(sizeof(struct async_req), GFP_ATOMIC);
+       if (req == NULL)
+               return res;
+       async_urb = usb_alloc_urb(0, GFP_ATOMIC);
+       if (async_urb == NULL) {
+               kfree(req);
+               return res;
+       }
+       req->rx_creg = cpu_to_le16(reg);
+       req->dr.bRequestType = RTL8150_REQT_WRITE;
+       req->dr.bRequest = RTL8150_REQ_SET_REGS;
+       req->dr.wIndex = 0;
+       req->dr.wValue = cpu_to_le16(indx);
+       req->dr.wLength = cpu_to_le16(size);
+       usb_fill_control_urb(async_urb, dev->udev,
+                            usb_sndctrlpipe(dev->udev, 0), (void *)&req->dr,
+                            &req->rx_creg, size, async_set_reg_cb, req);
+       res = usb_submit_urb(async_urb, GFP_ATOMIC);
+       if (res) {
+               if (res == -ENODEV)
                        netif_device_detach(dev->netdev);
-               dev_err(&dev->udev->dev,
-                       "control request submission failed: %d\n", ret);
-       } else
-               set_bit(RX_REG_SET, &dev->flags);
-
-       return ret;
+               dev_err(&dev->udev->dev, "%s failed with %d\n", __func__, res);
+       }
+       return res;
 }
 
 static int read_mii_word(rtl8150_t * dev, u8 phy, __u8 indx, u16 * reg)
@@ -330,13 +330,6 @@ static int alloc_all_urbs(rtl8150_t * dev)
                usb_free_urb(dev->tx_urb);
                return 0;
        }
-       dev->ctrl_urb = usb_alloc_urb(0, GFP_KERNEL);
-       if (!dev->ctrl_urb) {
-               usb_free_urb(dev->rx_urb);
-               usb_free_urb(dev->tx_urb);
-               usb_free_urb(dev->intr_urb);
-               return 0;
-       }
 
        return 1;
 }
@@ -346,7 +339,6 @@ static void free_all_urbs(rtl8150_t * dev)
        usb_free_urb(dev->rx_urb);
        usb_free_urb(dev->tx_urb);
        usb_free_urb(dev->intr_urb);
-       usb_free_urb(dev->ctrl_urb);
 }
 
 static void unlink_all_urbs(rtl8150_t * dev)
@@ -354,7 +346,6 @@ static void unlink_all_urbs(rtl8150_t * dev)
        usb_kill_urb(dev->rx_urb);
        usb_kill_urb(dev->tx_urb);
        usb_kill_urb(dev->intr_urb);
-       usb_kill_urb(dev->ctrl_urb);
 }
 
 static inline struct sk_buff *pull_skb(rtl8150_t *dev)
@@ -629,7 +620,6 @@ static int enable_net_traffic(rtl8150_t * dev)
        }
        /* RCR bit7=1 attach Rx info at the end;  =0 HW CRC (which is broken) */
        rcr = 0x9e;
-       dev->rx_creg = cpu_to_le16(rcr);
        tcr = 0xd8;
        cr = 0x0c;
        if (!(rcr & 0x80))
@@ -662,20 +652,22 @@ static void rtl8150_tx_timeout(struct net_device *netdev)
 static void rtl8150_set_multicast(struct net_device *netdev)
 {
        rtl8150_t *dev = netdev_priv(netdev);
+       u16 rx_creg = 0x9e;
+
        netif_stop_queue(netdev);
        if (netdev->flags & IFF_PROMISC) {
-               dev->rx_creg |= cpu_to_le16(0x0001);
+               rx_creg |= 0x0001;
                dev_info(&netdev->dev, "%s: promiscuous mode\n", netdev->name);
        } else if (!netdev_mc_empty(netdev) ||
                   (netdev->flags & IFF_ALLMULTI)) {
-               dev->rx_creg &= cpu_to_le16(0xfffe);
-               dev->rx_creg |= cpu_to_le16(0x0002);
+               rx_creg &= 0xfffe;
+               rx_creg |= 0x0002;
                dev_info(&netdev->dev, "%s: allmulti set\n", netdev->name);
        } else {
                /* ~RX_MULTICAST, ~RX_PROMISCUOUS */
-               dev->rx_creg &= cpu_to_le16(0x00fc);
+               rx_creg &= 0x00fc;
        }
-       async_set_registers(dev, RCR, 2);
+       async_set_registers(dev, RCR, sizeof(rx_creg), rx_creg);
        netif_wake_queue(netdev);
 }
 
index f95cb03..06ee82f 100644 (file)
@@ -1477,7 +1477,7 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
 
        /* usbnet already took usb runtime pm, so have to enable the feature
         * for usb interface, otherwise usb_autopm_get_interface may return
-        * failure if USB_SUSPEND(RUNTIME_PM) is enabled.
+        * failure if RUNTIME_PM is enabled.
         */
        if (!driver->supports_autosuspend) {
                driver->supports_autosuspend = 1;
index 3c23fdc..c9e0038 100644 (file)
@@ -28,7 +28,7 @@
 #include <linux/slab.h>
 #include <linux/cpu.h>
 
-static int napi_weight = 128;
+static int napi_weight = NAPI_POLL_WEIGHT;
 module_param(napi_weight, int, 0444);
 
 static bool csum = true, gso = true;
@@ -636,10 +636,11 @@ static int virtnet_open(struct net_device *dev)
        struct virtnet_info *vi = netdev_priv(dev);
        int i;
 
-       for (i = 0; i < vi->curr_queue_pairs; i++) {
-               /* Make sure we have some buffers: if oom use wq. */
-               if (!try_fill_recv(&vi->rq[i], GFP_KERNEL))
-                       schedule_delayed_work(&vi->refill, 0);
+       for (i = 0; i < vi->max_queue_pairs; i++) {
+               if (i < vi->curr_queue_pairs)
+                       /* Make sure we have some buffers: if oom use wq. */
+                       if (!try_fill_recv(&vi->rq[i], GFP_KERNEL))
+                               schedule_delayed_work(&vi->refill, 0);
                virtnet_napi_enable(&vi->rq[i]);
        }
 
index ba81f3c..3b1d2ee 100644 (file)
@@ -301,7 +301,7 @@ static inline struct hlist_head *vxlan_fdb_head(struct vxlan_dev *vxlan,
 }
 
 /* Look up Ethernet address in forwarding table */
-static struct vxlan_fdb *vxlan_find_mac(struct vxlan_dev *vxlan,
+static struct vxlan_fdb *__vxlan_find_mac(struct vxlan_dev *vxlan,
                                        const u8 *mac)
 
 {
@@ -316,6 +316,18 @@ static struct vxlan_fdb *vxlan_find_mac(struct vxlan_dev *vxlan,
        return NULL;
 }
 
+static struct vxlan_fdb *vxlan_find_mac(struct vxlan_dev *vxlan,
+                                       const u8 *mac)
+{
+       struct vxlan_fdb *f;
+
+       f = __vxlan_find_mac(vxlan, mac);
+       if (f)
+               f->used = jiffies;
+
+       return f;
+}
+
 /* Add/update destinations for multicast */
 static int vxlan_fdb_append(struct vxlan_fdb *f,
                            __be32 ip, __be16 port, __u32 vni, __u32 ifindex)
@@ -353,7 +365,7 @@ static int vxlan_fdb_create(struct vxlan_dev *vxlan,
        struct vxlan_fdb *f;
        int notify = 0;
 
-       f = vxlan_find_mac(vxlan, mac);
+       f = __vxlan_find_mac(vxlan, mac);
        if (f) {
                if (flags & NLM_F_EXCL) {
                        netdev_dbg(vxlan->dev,
@@ -563,7 +575,6 @@ static void vxlan_snoop(struct net_device *dev,
 
        f = vxlan_find_mac(vxlan, src_mac);
        if (likely(f)) {
-               f->used = jiffies;
                if (likely(f->remote.remote_ip == src_ip))
                        return;
 
index 9b20d9e..7f702fe 100644 (file)
@@ -2369,6 +2369,9 @@ ath5k_tx_complete_poll_work(struct work_struct *work)
        int i;
        bool needreset = false;
 
+       if (!test_bit(ATH_STAT_STARTED, ah->status))
+               return;
+
        mutex_lock(&ah->lock);
 
        for (i = 0; i < ARRAY_SIZE(ah->txqs); i++) {
@@ -2676,6 +2679,7 @@ done:
        mmiowb();
        mutex_unlock(&ah->lock);
 
+       set_bit(ATH_STAT_STARTED, ah->status);
        ieee80211_queue_delayed_work(ah->hw, &ah->tx_complete_work,
                        msecs_to_jiffies(ATH5K_TX_COMPLETE_POLL_INT));
 
@@ -2737,6 +2741,7 @@ void ath5k_stop(struct ieee80211_hw *hw)
 
        ath5k_stop_tasklets(ah);
 
+       clear_bit(ATH_STAT_STARTED, ah->status);
        cancel_delayed_work_sync(&ah->tx_complete_work);
 
        if (!ath5k_modparam_no_hw_rfkill_switch)
index 17507dc..3c2cbc9 100644 (file)
@@ -17,7 +17,7 @@ config ATH9K_BTCOEX_SUPPORT
 
 config ATH9K
        tristate "Atheros 802.11n wireless cards support"
-       depends on MAC80211
+       depends on MAC80211 && HAS_DMA
        select ATH9K_HW
        select MAC80211_LEDS
        select LEDS_CLASS
@@ -92,13 +92,17 @@ config ATH9K_MAC_DEBUG
          This option enables collection of statistics for Rx/Tx status
          data and some other MAC related statistics
 
-config ATH9K_RATE_CONTROL
+config ATH9K_LEGACY_RATE_CONTROL
        bool "Atheros ath9k rate control"
        depends on ATH9K
-       default y
+       default n
        ---help---
          Say Y, if you want to use the ath9k specific rate control
-         module instead of minstrel_ht.
+         module instead of minstrel_ht. Be warned that there are various
+         issues with the ath9k RC and minstrel is a more robust algorithm.
+         Note that even if this option is selected, "ath9k_rate_control"
+         has to be passed to mac80211 using the module parameter,
+         ieee80211_default_rc_algo.
 
 config ATH9K_HTC
        tristate "Atheros HTC based wireless cards support"
index 2ad8f94..75ee9e7 100644 (file)
@@ -8,7 +8,7 @@ ath9k-y +=      beacon.o \
                antenna.o
 
 ath9k-$(CONFIG_ATH9K_BTCOEX_SUPPORT) += mci.o
-ath9k-$(CONFIG_ATH9K_RATE_CONTROL) += rc.o
+ath9k-$(CONFIG_ATH9K_LEGACY_RATE_CONTROL) += rc.o
 ath9k-$(CONFIG_ATH9K_PCI) += pci.o
 ath9k-$(CONFIG_ATH9K_AHB) += ahb.o
 ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o
index db5ffad..7546b9a 100644 (file)
@@ -958,11 +958,11 @@ static const u32 ar9300Common_rx_gain_table_2p2[][2] = {
        {0x0000a074, 0x00000000},
        {0x0000a078, 0x00000000},
        {0x0000a07c, 0x00000000},
-       {0x0000a080, 0x1a1a1a1a},
-       {0x0000a084, 0x1a1a1a1a},
-       {0x0000a088, 0x1a1a1a1a},
-       {0x0000a08c, 0x1a1a1a1a},
-       {0x0000a090, 0x171a1a1a},
+       {0x0000a080, 0x22222229},
+       {0x0000a084, 0x1d1d1d1d},
+       {0x0000a088, 0x1d1d1d1d},
+       {0x0000a08c, 0x1d1d1d1d},
+       {0x0000a090, 0x171d1d1d},
        {0x0000a094, 0x11111717},
        {0x0000a098, 0x00030311},
        {0x0000a09c, 0x00000000},
index 639ba7d..6988e1d 100644 (file)
@@ -965,7 +965,7 @@ static void ar9003_hw_do_manual_peak_cal(struct ath_hw *ah,
 {
        int i;
 
-       if (!AR_SREV_9462(ah) && !AR_SREV_9565(ah))
+       if (!AR_SREV_9462(ah) && !AR_SREV_9565(ah) && !AR_SREV_9485(ah))
                return;
 
        for (i = 0; i < AR9300_MAX_CHAINS; i++) {
index 54ba42f..874f657 100644 (file)
 #define AR9300_BASE_ADDR 0x3ff
 #define AR9300_BASE_ADDR_512 0x1ff
 
-#define AR9300_OTP_BASE                        (AR_SREV_9340(ah) ? 0x30000 : 0x14000)
-#define AR9300_OTP_STATUS              (AR_SREV_9340(ah) ? 0x30018 : 0x15f18)
+#define AR9300_OTP_BASE \
+               ((AR_SREV_9340(ah) || AR_SREV_9550(ah)) ? 0x30000 : 0x14000)
+#define AR9300_OTP_STATUS \
+               ((AR_SREV_9340(ah) || AR_SREV_9550(ah)) ? 0x30018 : 0x15f18)
 #define AR9300_OTP_STATUS_TYPE         0x7
 #define AR9300_OTP_STATUS_VALID                0x4
 #define AR9300_OTP_STATUS_ACCESS_BUSY  0x2
 #define AR9300_OTP_STATUS_SM_BUSY      0x1
-#define AR9300_OTP_READ_DATA           (AR_SREV_9340(ah) ? 0x3001c : 0x15f1c)
+#define AR9300_OTP_READ_DATA \
+               ((AR_SREV_9340(ah) || AR_SREV_9550(ah)) ? 0x3001c : 0x15f1c)
 
 enum targetPowerHTRates {
        HT_TARGET_RATE_0_8_16,
index 2bf6548..e1714d7 100644 (file)
@@ -334,7 +334,8 @@ static void ar9003_hw_spur_ofdm(struct ath_hw *ah,
        REG_RMW_FIELD(ah, AR_PHY_SPUR_REG,
                      AR_PHY_SPUR_REG_EN_VIT_SPUR_RSSI, 1);
 
-       if (REG_READ_FIELD(ah, AR_PHY_MODE,
+       if (!AR_SREV_9340(ah) &&
+           REG_READ_FIELD(ah, AR_PHY_MODE,
                           AR_PHY_MODE_DYNAMIC) == 0x1)
                REG_RMW_FIELD(ah, AR_PHY_SPUR_REG,
                              AR_PHY_SPUR_REG_ENABLE_NF_RSSI_SPUR_MIT, 1);
index 712f415..88ff1d7 100644 (file)
@@ -1020,7 +1020,7 @@ static const u32 ar9485_1_1_baseband_postamble[][5] = {
        {0x0000a284, 0x00000000, 0x00000000, 0x000002a0, 0x000002a0},
        {0x0000a288, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
        {0x0000a28c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
+       {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00058d18, 0x00058d18},
        {0x0000a2d0, 0x00071981, 0x00071981, 0x00071982, 0x00071982},
        {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a},
        {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
index 0c2ac0c..e85a8b0 100644 (file)
@@ -233,9 +233,9 @@ static const u32 ar9565_1p0_baseband_core[][2] = {
        {0x00009d10, 0x01834061},
        {0x00009d14, 0x00c00400},
        {0x00009d18, 0x00000000},
-       {0x00009e08, 0x0078230c},
-       {0x00009e24, 0x990bb515},
-       {0x00009e28, 0x126f0000},
+       {0x00009e08, 0x0038230c},
+       {0x00009e24, 0x9907b515},
+       {0x00009e28, 0x126f0600},
        {0x00009e30, 0x06336f77},
        {0x00009e34, 0x6af6532f},
        {0x00009e38, 0x0cc80c00},
@@ -337,7 +337,7 @@ static const u32 ar9565_1p0_baseband_core[][2] = {
 
 static const u32 ar9565_1p0_baseband_postamble[][5] = {
        /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
-       {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a800d},
+       {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a8009},
        {0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a01ae},
        {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x63c640da},
        {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x09143c81},
@@ -345,9 +345,9 @@ static const u32 ar9565_1p0_baseband_postamble[][5] = {
        {0x00009830, 0x0000059c, 0x0000059c, 0x0000059c, 0x0000059c},
        {0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4},
        {0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a0},
-       {0x00009e04, 0x00802020, 0x00802020, 0x00802020, 0x00802020},
-       {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000d8},
-       {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec86d2e},
+       {0x00009e04, 0x00802020, 0x00802020, 0x00142020, 0x00142020},
+       {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
+       {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e},
        {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3379605e, 0x33795d5e},
        {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
        {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
@@ -450,6 +450,8 @@ static const u32 ar9565_1p0_soc_postamble[][5] = {
 
 static const u32 ar9565_1p0_Common_rx_gain_table[][2] = {
        /* Addr      allmodes  */
+       {0x00004050, 0x00300300},
+       {0x0000406c, 0x00100000},
        {0x0000a000, 0x00010000},
        {0x0000a004, 0x00030002},
        {0x0000a008, 0x00050004},
@@ -498,27 +500,27 @@ static const u32 ar9565_1p0_Common_rx_gain_table[][2] = {
        {0x0000a0b4, 0x00000000},
        {0x0000a0b8, 0x00000000},
        {0x0000a0bc, 0x00000000},
-       {0x0000a0c0, 0x001f0000},
-       {0x0000a0c4, 0x01000101},
-       {0x0000a0c8, 0x011e011f},
-       {0x0000a0cc, 0x011c011d},
-       {0x0000a0d0, 0x02030204},
-       {0x0000a0d4, 0x02010202},
-       {0x0000a0d8, 0x021f0200},
-       {0x0000a0dc, 0x0302021e},
-       {0x0000a0e0, 0x03000301},
-       {0x0000a0e4, 0x031e031f},
-       {0x0000a0e8, 0x0402031d},
-       {0x0000a0ec, 0x04000401},
-       {0x0000a0f0, 0x041e041f},
-       {0x0000a0f4, 0x0502041d},
-       {0x0000a0f8, 0x05000501},
-       {0x0000a0fc, 0x051e051f},
-       {0x0000a100, 0x06010602},
-       {0x0000a104, 0x061f0600},
-       {0x0000a108, 0x061d061e},
-       {0x0000a10c, 0x07020703},
-       {0x0000a110, 0x07000701},
+       {0x0000a0c0, 0x00bf00a0},
+       {0x0000a0c4, 0x11a011a1},
+       {0x0000a0c8, 0x11be11bf},
+       {0x0000a0cc, 0x11bc11bd},
+       {0x0000a0d0, 0x22632264},
+       {0x0000a0d4, 0x22612262},
+       {0x0000a0d8, 0x227f2260},
+       {0x0000a0dc, 0x4322227e},
+       {0x0000a0e0, 0x43204321},
+       {0x0000a0e4, 0x433e433f},
+       {0x0000a0e8, 0x4462433d},
+       {0x0000a0ec, 0x44604461},
+       {0x0000a0f0, 0x447e447f},
+       {0x0000a0f4, 0x5582447d},
+       {0x0000a0f8, 0x55805581},
+       {0x0000a0fc, 0x559e559f},
+       {0x0000a100, 0x66816682},
+       {0x0000a104, 0x669f6680},
+       {0x0000a108, 0x669d669e},
+       {0x0000a10c, 0x77627763},
+       {0x0000a110, 0x77607761},
        {0x0000a114, 0x00000000},
        {0x0000a118, 0x00000000},
        {0x0000a11c, 0x00000000},
@@ -530,27 +532,27 @@ static const u32 ar9565_1p0_Common_rx_gain_table[][2] = {
        {0x0000a134, 0x00000000},
        {0x0000a138, 0x00000000},
        {0x0000a13c, 0x00000000},
-       {0x0000a140, 0x001f0000},
-       {0x0000a144, 0x01000101},
-       {0x0000a148, 0x011e011f},
-       {0x0000a14c, 0x011c011d},
-       {0x0000a150, 0x02030204},
-       {0x0000a154, 0x02010202},
-       {0x0000a158, 0x021f0200},
-       {0x0000a15c, 0x0302021e},
-       {0x0000a160, 0x03000301},
-       {0x0000a164, 0x031e031f},
-       {0x0000a168, 0x0402031d},
-       {0x0000a16c, 0x04000401},
-       {0x0000a170, 0x041e041f},
-       {0x0000a174, 0x0502041d},
-       {0x0000a178, 0x05000501},
-       {0x0000a17c, 0x051e051f},
-       {0x0000a180, 0x06010602},
-       {0x0000a184, 0x061f0600},
-       {0x0000a188, 0x061d061e},
-       {0x0000a18c, 0x07020703},
-       {0x0000a190, 0x07000701},
+       {0x0000a140, 0x00bf00a0},
+       {0x0000a144, 0x11a011a1},
+       {0x0000a148, 0x11be11bf},
+       {0x0000a14c, 0x11bc11bd},
+       {0x0000a150, 0x22632264},
+       {0x0000a154, 0x22612262},
+       {0x0000a158, 0x227f2260},
+       {0x0000a15c, 0x4322227e},
+       {0x0000a160, 0x43204321},
+       {0x0000a164, 0x433e433f},
+       {0x0000a168, 0x4462433d},
+       {0x0000a16c, 0x44604461},
+       {0x0000a170, 0x447e447f},
+       {0x0000a174, 0x5582447d},
+       {0x0000a178, 0x55805581},
+       {0x0000a17c, 0x559e559f},
+       {0x0000a180, 0x66816682},
+       {0x0000a184, 0x669f6680},
+       {0x0000a188, 0x669d669e},
+       {0x0000a18c, 0x77e677e7},
+       {0x0000a190, 0x77e477e5},
        {0x0000a194, 0x00000000},
        {0x0000a198, 0x00000000},
        {0x0000a19c, 0x00000000},
@@ -770,7 +772,7 @@ static const u32 ar9565_1p0_Modes_lowest_ob_db_tx_gain_table[][5] = {
 
 static const u32 ar9565_1p0_pciephy_clkreq_disable_L1[][2] = {
        /* Addr      allmodes  */
-       {0x00018c00, 0x18213ede},
+       {0x00018c00, 0x18212ede},
        {0x00018c04, 0x000801d8},
        {0x00018c08, 0x0003780c},
 };
@@ -889,8 +891,8 @@ static const u32 ar9565_1p0_common_wo_xlna_rx_gain_table[][2] = {
        {0x0000a180, 0x66816682},
        {0x0000a184, 0x669f6680},
        {0x0000a188, 0x669d669e},
-       {0x0000a18c, 0x77627763},
-       {0x0000a190, 0x77607761},
+       {0x0000a18c, 0x77e677e7},
+       {0x0000a190, 0x77e477e5},
        {0x0000a194, 0x00000000},
        {0x0000a198, 0x00000000},
        {0x0000a19c, 0x00000000},
@@ -1114,7 +1116,7 @@ static const u32 ar9565_1p0_modes_high_ob_db_tx_gain_table[][5] = {
        {0x0000a2e0, 0xffecec00, 0xffecec00, 0xfd339c84, 0xfd339c84},
        {0x0000a2e4, 0xfc0f0000, 0xfc0f0000, 0xfec3e000, 0xfec3e000},
        {0x0000a2e8, 0xfc100000, 0xfc100000, 0xfffc0000, 0xfffc0000},
-       {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
+       {0x0000a410, 0x000050d9, 0x000050d9, 0x000050df, 0x000050df},
        {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
        {0x0000a504, 0x06002223, 0x06002223, 0x04000002, 0x04000002},
        {0x0000a508, 0x0b022220, 0x0b022220, 0x08000004, 0x08000004},
@@ -1140,13 +1142,13 @@ static const u32 ar9565_1p0_modes_high_ob_db_tx_gain_table[][5] = {
        {0x0000a558, 0x69027f56, 0x69027f56, 0x53001ce5, 0x53001ce5},
        {0x0000a55c, 0x6d029f56, 0x6d029f56, 0x57001ce9, 0x57001ce9},
        {0x0000a560, 0x73049f56, 0x73049f56, 0x5b001ceb, 0x5b001ceb},
-       {0x0000a564, 0x7804ff56, 0x7804ff56, 0x5d001eec, 0x5d001eec},
-       {0x0000a568, 0x7804ff56, 0x7804ff56, 0x5d001eec, 0x5d001eec},
-       {0x0000a56c, 0x7804ff56, 0x7804ff56, 0x5d001eec, 0x5d001eec},
-       {0x0000a570, 0x7804ff56, 0x7804ff56, 0x5d001eec, 0x5d001eec},
-       {0x0000a574, 0x7804ff56, 0x7804ff56, 0x5d001eec, 0x5d001eec},
-       {0x0000a578, 0x7804ff56, 0x7804ff56, 0x5d001eec, 0x5d001eec},
-       {0x0000a57c, 0x7804ff56, 0x7804ff56, 0x5d001eec, 0x5d001eec},
+       {0x0000a564, 0x7804ff56, 0x7804ff56, 0x60001cf0, 0x60001cf0},
+       {0x0000a568, 0x7804ff56, 0x7804ff56, 0x61001cf1, 0x61001cf1},
+       {0x0000a56c, 0x7804ff56, 0x7804ff56, 0x62001cf2, 0x62001cf2},
+       {0x0000a570, 0x7804ff56, 0x7804ff56, 0x63001cf3, 0x63001cf3},
+       {0x0000a574, 0x7804ff56, 0x7804ff56, 0x64001cf4, 0x64001cf4},
+       {0x0000a578, 0x7804ff56, 0x7804ff56, 0x66001ff6, 0x66001ff6},
+       {0x0000a57c, 0x7804ff56, 0x7804ff56, 0x66001ff6, 0x66001ff6},
        {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
        {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
        {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
@@ -1174,7 +1176,7 @@ static const u32 ar9565_1p0_modes_high_power_tx_gain_table[][5] = {
        {0x0000a2e0, 0xffecec00, 0xffecec00, 0xfd339c84, 0xfd339c84},
        {0x0000a2e4, 0xfc0f0000, 0xfc0f0000, 0xfec3e000, 0xfec3e000},
        {0x0000a2e8, 0xfc100000, 0xfc100000, 0xfffc0000, 0xfffc0000},
-       {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
+       {0x0000a410, 0x000050d9, 0x000050d9, 0x000050df, 0x000050df},
        {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
        {0x0000a504, 0x06002223, 0x06002223, 0x04000002, 0x04000002},
        {0x0000a508, 0x0a022220, 0x0a022220, 0x08000004, 0x08000004},
@@ -1200,13 +1202,13 @@ static const u32 ar9565_1p0_modes_high_power_tx_gain_table[][5] = {
        {0x0000a558, 0x66027f56, 0x66027f56, 0x4c001ce5, 0x4c001ce5},
        {0x0000a55c, 0x6a029f56, 0x6a029f56, 0x50001ce9, 0x50001ce9},
        {0x0000a560, 0x70049f56, 0x70049f56, 0x54001ceb, 0x54001ceb},
-       {0x0000a564, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
-       {0x0000a568, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
-       {0x0000a56c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
-       {0x0000a570, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
-       {0x0000a574, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
-       {0x0000a578, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
-       {0x0000a57c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+       {0x0000a564, 0x7504ff56, 0x7504ff56, 0x59001cf0, 0x59001cf0},
+       {0x0000a568, 0x7504ff56, 0x7504ff56, 0x5a001cf1, 0x5a001cf1},
+       {0x0000a56c, 0x7504ff56, 0x7504ff56, 0x5b001cf2, 0x5b001cf2},
+       {0x0000a570, 0x7504ff56, 0x7504ff56, 0x5c001cf3, 0x5c001cf3},
+       {0x0000a574, 0x7504ff56, 0x7504ff56, 0x5d001cf4, 0x5d001cf4},
+       {0x0000a578, 0x7504ff56, 0x7504ff56, 0x5f001ff6, 0x5f001ff6},
+       {0x0000a57c, 0x7504ff56, 0x7504ff56, 0x5f001ff6, 0x5f001ff6},
        {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
        {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
        {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
index 8a1888d..42b03dc 100644 (file)
@@ -251,9 +251,9 @@ struct ath_atx_tid {
        int tidno;
        int baw_head;   /* first un-acked tx buffer */
        int baw_tail;   /* next unused tx buffer slot */
-       int sched;
-       int paused;
-       u8 state;
+       bool sched;
+       bool paused;
+       bool active;
 };
 
 struct ath_node {
@@ -274,10 +274,6 @@ struct ath_node {
 #endif
 };
 
-#define AGGR_CLEANUP         BIT(1)
-#define AGGR_ADDBA_COMPLETE  BIT(2)
-#define AGGR_ADDBA_PROGRESS  BIT(3)
-
 struct ath_tx_control {
        struct ath_txq *txq;
        struct ath_node *an;
index e6307b8..b37eb8d 100644 (file)
@@ -2008,6 +2008,14 @@ void ath9k_get_et_stats(struct ieee80211_hw *hw,
        WARN_ON(i != ATH9K_SSTATS_LEN);
 }
 
+void ath9k_deinit_debug(struct ath_softc *sc)
+{
+       if (config_enabled(CONFIG_ATH9K_DEBUGFS) && sc->rfs_chan_spec_scan) {
+               relay_close(sc->rfs_chan_spec_scan);
+               sc->rfs_chan_spec_scan = NULL;
+       }
+}
+
 int ath9k_init_debug(struct ath_hw *ah)
 {
        struct ath_common *common = ath9k_hw_common(ah);
index 794a7ec..9d49aab 100644 (file)
@@ -304,6 +304,7 @@ struct ath9k_debug {
 };
 
 int ath9k_init_debug(struct ath_hw *ah);
+void ath9k_deinit_debug(struct ath_softc *sc);
 
 void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status);
 void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
@@ -339,6 +340,10 @@ static inline int ath9k_init_debug(struct ath_hw *ah)
        return 0;
 }
 
+static inline void ath9k_deinit_debug(struct ath_softc *sc)
+{
+}
+
 static inline void ath_debug_stat_interrupt(struct ath_softc *sc,
                                            enum ath9k_int status)
 {
index 7f25da8..15dfefc 100644 (file)
@@ -1172,6 +1172,7 @@ u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan)
 static inline void ath9k_hw_set_dma(struct ath_hw *ah)
 {
        struct ath_common *common = ath9k_hw_common(ah);
+       int txbuf_size;
 
        ENABLE_REGWRITE_BUFFER(ah);
 
@@ -1225,13 +1226,17 @@ static inline void ath9k_hw_set_dma(struct ath_hw *ah)
                 * So set the usable tx buf size also to half to
                 * avoid data/delimiter underruns
                 */
-               REG_WRITE(ah, AR_PCU_TXBUF_CTRL,
-                         AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE);
-       } else if (!AR_SREV_9271(ah)) {
-               REG_WRITE(ah, AR_PCU_TXBUF_CTRL,
-                         AR_PCU_TXBUF_CTRL_USABLE_SIZE);
+               txbuf_size = AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE;
+       } else if (AR_SREV_9340_13_OR_LATER(ah)) {
+               /* Uses fewer entries for AR934x v1.3+ to prevent rx overruns */
+               txbuf_size = AR_9340_PCU_TXBUF_CTRL_USABLE_SIZE;
+       } else {
+               txbuf_size = AR_PCU_TXBUF_CTRL_USABLE_SIZE;
        }
 
+       if (!AR_SREV_9271(ah))
+               REG_WRITE(ah, AR_PCU_TXBUF_CTRL, txbuf_size);
+
        REGWRITE_BUFFER_FLUSH(ah);
 
        if (AR_SREV_9300_20_OR_LATER(ah))
@@ -1306,9 +1311,13 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type)
                        AR_RTC_RC_COLD_RESET | AR_RTC_RC_WARM_RESET;
        } else {
                tmpReg = REG_READ(ah, AR_INTR_SYNC_CAUSE);
-               if (tmpReg &
-                   (AR_INTR_SYNC_LOCAL_TIMEOUT |
-                    AR_INTR_SYNC_RADM_CPL_TIMEOUT)) {
+               if (AR_SREV_9340(ah))
+                       tmpReg &= AR9340_INTR_SYNC_LOCAL_TIMEOUT;
+               else
+                       tmpReg &= AR_INTR_SYNC_LOCAL_TIMEOUT |
+                                 AR_INTR_SYNC_RADM_CPL_TIMEOUT;
+
+               if (tmpReg) {
                        u32 val;
                        REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0);
 
index 0237b28..2ba4945 100644 (file)
@@ -787,8 +787,7 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
        hw->wiphy->iface_combinations = if_comb;
        hw->wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);
 
-       if (AR_SREV_5416(sc->sc_ah))
-               hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
+       hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
 
        hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
        hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS;
@@ -830,10 +829,6 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
        sc->ant_rx = hw->wiphy->available_antennas_rx;
        sc->ant_tx = hw->wiphy->available_antennas_tx;
 
-#ifdef CONFIG_ATH9K_RATE_CONTROL
-       hw->rate_control_algorithm = "ath9k_rate_control";
-#endif
-
        if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
                hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
                        &sc->sbands[IEEE80211_BAND_2GHZ];
@@ -906,7 +901,7 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc,
        if (!ath_is_world_regd(reg)) {
                error = regulatory_hint(hw->wiphy, reg->alpha2);
                if (error)
-                       goto unregister;
+                       goto debug_cleanup;
        }
 
        ath_init_leds(sc);
@@ -914,6 +909,8 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc,
 
        return 0;
 
+debug_cleanup:
+       ath9k_deinit_debug(sc);
 unregister:
        ieee80211_unregister_hw(hw);
 rx_cleanup:
@@ -942,11 +939,6 @@ static void ath9k_deinit_softc(struct ath_softc *sc)
                sc->dfs_detector->exit(sc->dfs_detector);
 
        ath9k_eeprom_release(sc);
-
-       if (config_enabled(CONFIG_ATH9K_DEBUGFS) && sc->rfs_chan_spec_scan) {
-               relay_close(sc->rfs_chan_spec_scan);
-               sc->rfs_chan_spec_scan = NULL;
-       }
 }
 
 void ath9k_deinit_device(struct ath_softc *sc)
@@ -960,6 +952,7 @@ void ath9k_deinit_device(struct ath_softc *sc)
 
        ath9k_ps_restore(sc);
 
+       ath9k_deinit_debug(sc);
        ieee80211_unregister_hw(hw);
        ath_rx_cleanup(sc);
        ath9k_deinit_softc(sc);
index 498fee0..566109a 100644 (file)
@@ -410,7 +410,7 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
 
        REG_WRITE(ah, AR_QMISC(q), AR_Q_MISC_DCU_EARLY_TERM_REQ);
 
-       if (AR_SREV_9340(ah))
+       if (AR_SREV_9340(ah) && !AR_SREV_9340_13_OR_LATER(ah))
                REG_WRITE(ah, AR_DMISC(q),
                          AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x1);
        else
index 6963862..5092eca 100644 (file)
@@ -227,13 +227,13 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start)
                if (!test_bit(SC_OP_BEACONS, &sc->sc_flags))
                        goto work;
 
-               ath9k_set_beacon(sc);
-
                if (ah->opmode == NL80211_IFTYPE_STATION &&
                    test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) {
                        spin_lock_irqsave(&sc->sc_pm_lock, flags);
                        sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON;
                        spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
+               } else {
+                       ath9k_set_beacon(sc);
                }
        work:
                ath_restart_work(sc);
@@ -1332,6 +1332,7 @@ static int ath9k_sta_add(struct ieee80211_hw *hw,
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
        struct ath_node *an = (struct ath_node *) sta->drv_priv;
        struct ieee80211_key_conf ps_key = { };
+       int key;
 
        ath_node_attach(sc, sta, vif);
 
@@ -1339,7 +1340,9 @@ static int ath9k_sta_add(struct ieee80211_hw *hw,
            vif->type != NL80211_IFTYPE_AP_VLAN)
                return 0;
 
-       an->ps_key = ath_key_config(common, vif, sta, &ps_key);
+       key = ath_key_config(common, vif, sta, &ps_key);
+       if (key > 0)
+               an->ps_key = key;
 
        return 0;
 }
@@ -1356,6 +1359,7 @@ static void ath9k_del_ps_key(struct ath_softc *sc,
            return;
 
        ath_key_delete(common, &ps_key);
+       an->ps_key = 0;
 }
 
 static int ath9k_sta_remove(struct ieee80211_hw *hw,
@@ -1683,6 +1687,7 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw,
                              u16 tid, u16 *ssn, u8 buf_size)
 {
        struct ath_softc *sc = hw->priv;
+       bool flush = false;
        int ret = 0;
 
        local_bh_disable();
@@ -1699,12 +1704,14 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw,
                        ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
                ath9k_ps_restore(sc);
                break;
-       case IEEE80211_AMPDU_TX_STOP_CONT:
        case IEEE80211_AMPDU_TX_STOP_FLUSH:
        case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
+               flush = true;
+       case IEEE80211_AMPDU_TX_STOP_CONT:
                ath9k_ps_wakeup(sc);
                ath_tx_aggr_stop(sc, sta, tid);
-               ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+               if (!flush)
+                       ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
                ath9k_ps_restore(sc);
                break;
        case IEEE80211_AMPDU_TX_OPERATIONAL:
index aa4d368..7eb1f4b 100644 (file)
@@ -1227,10 +1227,7 @@ static bool ath_tx_aggr_check(struct ath_softc *sc, struct ieee80211_sta *sta,
                return false;
 
        txtid = ATH_AN_2_TID(an, tidno);
-
-       if (!(txtid->state & (AGGR_ADDBA_COMPLETE | AGGR_ADDBA_PROGRESS)))
-                       return true;
-       return false;
+       return !txtid->active;
 }
 
 
index 267dbfc..b9a8738 100644 (file)
@@ -231,7 +231,7 @@ static inline void ath_debug_stat_retries(struct ath_rate_priv *rc, int rix,
 }
 #endif
 
-#ifdef CONFIG_ATH9K_RATE_CONTROL
+#ifdef CONFIG_ATH9K_LEGACY_RATE_CONTROL
 int ath_rate_control_register(void);
 void ath_rate_control_unregister(void);
 #else
index 5c4ab50..f7c90cc 100644 (file)
 #define AR_SREV_REVISION_9485_10       0
 #define AR_SREV_REVISION_9485_11        1
 #define AR_SREV_VERSION_9340           0x300
+#define AR_SREV_REVISION_9340_10       0
+#define AR_SREV_REVISION_9340_11       1
+#define AR_SREV_REVISION_9340_12       2
+#define AR_SREV_REVISION_9340_13       3
 #define AR_SREV_VERSION_9580           0x1C0
 #define AR_SREV_REVISION_9580_10       4 /* AR9580 1.0 */
 #define AR_SREV_VERSION_9462           0x280
 #define AR_SREV_9340(_ah) \
        (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9340))
 
+#define AR_SREV_9340_13_OR_LATER(_ah) \
+       (AR_SREV_9340((_ah)) && \
+        ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9340_13))
+
 #define AR_SREV_9285E_20(_ah) \
     (AR_SREV_9285_12_OR_LATER(_ah) && \
      ((REG_READ(_ah, AR_AN_SYNTH9) & 0x7) == 0x1))
@@ -1007,6 +1015,8 @@ enum {
                                AR_INTR_SYNC_LOCAL_TIMEOUT |
                                AR_INTR_SYNC_MAC_SLEEP_ACCESS),
 
+       AR9340_INTR_SYNC_LOCAL_TIMEOUT = 0x00000010,
+
        AR_INTR_SYNC_SPURIOUS = 0xFFFFFFFF,
 
 };
@@ -1881,6 +1891,7 @@ enum {
 #define AR_PCU_TXBUF_CTRL_SIZE_MASK     0x7FF
 #define AR_PCU_TXBUF_CTRL_USABLE_SIZE   0x700
 #define AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE   0x380
+#define AR_9340_PCU_TXBUF_CTRL_USABLE_SIZE   0x500
 
 #define AR_PCU_MISC_MODE2               0x8344
 #define AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE           0x00000002
index eab0fcb..1c9b1ba 100644 (file)
@@ -125,24 +125,6 @@ static void ath_tx_queue_tid(struct ath_txq *txq, struct ath_atx_tid *tid)
        list_add_tail(&ac->list, &txq->axq_acq);
 }
 
-static void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
-{
-       struct ath_txq *txq = tid->ac->txq;
-
-       WARN_ON(!tid->paused);
-
-       ath_txq_lock(sc, txq);
-       tid->paused = false;
-
-       if (skb_queue_empty(&tid->buf_q))
-               goto unlock;
-
-       ath_tx_queue_tid(txq, tid);
-       ath_txq_schedule(sc, txq);
-unlock:
-       ath_txq_unlock_complete(sc, txq);
-}
-
 static struct ath_frame_info *get_frame_info(struct sk_buff *skb)
 {
        struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
@@ -201,11 +183,6 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
                }
        }
 
-       if (tid->baw_head == tid->baw_tail) {
-               tid->state &= ~AGGR_ADDBA_COMPLETE;
-               tid->state &= ~AGGR_CLEANUP;
-       }
-
        if (sendbar) {
                ath_txq_unlock(sc, txq);
                ath_send_bar(tid, tid->seq_start);
@@ -277,9 +254,7 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq,
 
                list_add_tail(&bf->list, &bf_head);
 
-               if (fi->retries)
-                       ath_tx_update_baw(sc, tid, bf->bf_state.seqno);
-
+               ath_tx_update_baw(sc, tid, bf->bf_state.seqno);
                ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0);
        }
 
@@ -491,19 +466,19 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
                tx_info = IEEE80211_SKB_CB(skb);
                fi = get_frame_info(skb);
 
-               if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, seqno))) {
+               if (!BAW_WITHIN(tid->seq_start, tid->baw_size, seqno)) {
+                       /*
+                        * Outside of the current BlockAck window,
+                        * maybe part of a previous session
+                        */
+                       txfail = 1;
+               } else if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, seqno))) {
                        /* transmit completion, subframe is
                         * acked by block ack */
                        acked_cnt++;
                } else if (!isaggr && txok) {
                        /* transmit completion */
                        acked_cnt++;
-               } else if (tid->state & AGGR_CLEANUP) {
-                       /*
-                        * cleanup in progress, just fail
-                        * the un-acked sub-frames
-                        */
-                       txfail = 1;
                } else if (flush) {
                        txpending = 1;
                } else if (fi->retries < ATH_MAX_SW_RETRIES) {
@@ -527,7 +502,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
                if (bf_next != NULL || !bf_last->bf_stale)
                        list_move_tail(&bf->list, &bf_head);
 
-               if (!txpending || (tid->state & AGGR_CLEANUP)) {
+               if (!txpending) {
                        /*
                         * complete the acked-ones/xretried ones; update
                         * block-ack window
@@ -601,9 +576,6 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
                ath_txq_lock(sc, txq);
        }
 
-       if (tid->state & AGGR_CLEANUP)
-               ath_tx_flush_tid(sc, tid);
-
        rcu_read_unlock();
 
        if (needreset)
@@ -620,6 +592,7 @@ static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq,
                                  struct ath_tx_status *ts, struct ath_buf *bf,
                                  struct list_head *bf_head)
 {
+       struct ieee80211_tx_info *info;
        bool txok, flush;
 
        txok = !(ts->ts_status & ATH9K_TXERR_MASK);
@@ -631,8 +604,12 @@ static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq,
                txq->axq_ampdu_depth--;
 
        if (!bf_isampdu(bf)) {
-               if (!flush)
+               if (!flush) {
+                       info = IEEE80211_SKB_CB(bf->bf_mpdu);
+                       memcpy(info->control.rates, bf->rates,
+                              sizeof(info->control.rates));
                        ath_tx_rc_status(sc, bf, ts, 1, txok ? 0 : 1, txok);
+               }
                ath_tx_complete_buf(sc, bf, txq, bf_head, ts, txok);
        } else
                ath_tx_complete_aggr(sc, txq, bf, bf_head, ts, txok);
@@ -676,7 +653,7 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
 
        skb = bf->bf_mpdu;
        tx_info = IEEE80211_SKB_CB(skb);
-       rates = tx_info->control.rates;
+       rates = bf->rates;
 
        /*
         * Find the lowest frame length among the rate series that will have a
@@ -1231,9 +1208,6 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
        an = (struct ath_node *)sta->drv_priv;
        txtid = ATH_AN_2_TID(an, tid);
 
-       if (txtid->state & (AGGR_CLEANUP | AGGR_ADDBA_COMPLETE))
-               return -EAGAIN;
-
        /* update ampdu factor/density, they may have changed. This may happen
         * in HT IBSS when a beacon with HT-info is received after the station
         * has already been added.
@@ -1245,7 +1219,7 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
                an->mpdudensity = density;
        }
 
-       txtid->state |= AGGR_ADDBA_PROGRESS;
+       txtid->active = true;
        txtid->paused = true;
        *ssn = txtid->seq_start = txtid->seq_next;
        txtid->bar_index = -1;
@@ -1262,28 +1236,9 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
        struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid);
        struct ath_txq *txq = txtid->ac->txq;
 
-       if (txtid->state & AGGR_CLEANUP)
-               return;
-
-       if (!(txtid->state & AGGR_ADDBA_COMPLETE)) {
-               txtid->state &= ~AGGR_ADDBA_PROGRESS;
-               return;
-       }
-
        ath_txq_lock(sc, txq);
+       txtid->active = false;
        txtid->paused = true;
-
-       /*
-        * If frames are still being transmitted for this TID, they will be
-        * cleaned up during tx completion. To prevent race conditions, this
-        * TID can only be reused after all in-progress subframes have been
-        * completed.
-        */
-       if (txtid->baw_head != txtid->baw_tail)
-               txtid->state |= AGGR_CLEANUP;
-       else
-               txtid->state &= ~AGGR_ADDBA_COMPLETE;
-
        ath_tx_flush_tid(sc, txtid);
        ath_txq_unlock_complete(sc, txq);
 }
@@ -1349,18 +1304,28 @@ void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an)
        }
 }
 
-void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
+void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta,
+                       u16 tidno)
 {
-       struct ath_atx_tid *txtid;
+       struct ath_atx_tid *tid;
        struct ath_node *an;
+       struct ath_txq *txq;
 
        an = (struct ath_node *)sta->drv_priv;
+       tid = ATH_AN_2_TID(an, tidno);
+       txq = tid->ac->txq;
 
-       txtid = ATH_AN_2_TID(an, tid);
-       txtid->baw_size = IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor;
-       txtid->state |= AGGR_ADDBA_COMPLETE;
-       txtid->state &= ~AGGR_ADDBA_PROGRESS;
-       ath_tx_resume_tid(sc, txtid);
+       ath_txq_lock(sc, txq);
+
+       tid->baw_size = IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor;
+       tid->paused = false;
+
+       if (!skb_queue_empty(&tid->buf_q)) {
+               ath_tx_queue_tid(txq, tid);
+               ath_txq_schedule(sc, txq);
+       }
+
+       ath_txq_unlock_complete(sc, txq);
 }
 
 /********************/
@@ -2409,12 +2374,10 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
                tid->baw_head  = tid->baw_tail = 0;
                tid->sched     = false;
                tid->paused    = false;
-               tid->state &= ~AGGR_CLEANUP;
+               tid->active        = false;
                __skb_queue_head_init(&tid->buf_q);
                acno = TID_TO_WME_AC(tidno);
                tid->ac = &an->ac[acno];
-               tid->state &= ~AGGR_ADDBA_COMPLETE;
-               tid->state &= ~AGGR_ADDBA_PROGRESS;
        }
 
        for (acno = 0, ac = &an->ac[acno];
@@ -2451,8 +2414,7 @@ void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an)
                }
 
                ath_tid_drain(sc, txq, tid);
-               tid->state &= ~AGGR_ADDBA_COMPLETE;
-               tid->state &= ~AGGR_CLEANUP;
+               tid->active = false;
 
                ath_txq_unlock(sc, txq);
        }
index 830bb1d..b827d51 100644 (file)
@@ -1624,7 +1624,7 @@ struct net_device *init_atmel_card(unsigned short irq, unsigned long port,
 
        netif_carrier_off(dev);
 
-       if (!proc_create_data("driver/atmel", 0, NULL, &atmel_proc_fops, priv));
+       if (!proc_create_data("driver/atmel", 0, NULL, &atmel_proc_fops, priv))
                printk(KERN_WARNING "atmel: unable to create /proc entry.\n");
 
        printk(KERN_INFO "%s: Atmel at76c50x. Version %d.%d. MAC %pM\n",
index 523355b..f7c70b3 100644 (file)
@@ -1728,6 +1728,25 @@ drop_recycle_buffer:
        sync_descbuffer_for_device(ring, dmaaddr, ring->rx_buffersize);
 }
 
+void b43_dma_handle_rx_overflow(struct b43_dmaring *ring)
+{
+       int current_slot, previous_slot;
+
+       B43_WARN_ON(ring->tx);
+
+       /* Device has filled all buffers, drop all packets and let TCP
+        * decrease speed.
+        * Decrement RX index by one will let the device to see all slots
+        * as free again
+        */
+       /*
+       *TODO: How to increase rx_drop in mac80211?
+       */
+       current_slot = ring->ops->get_current_rxslot(ring);
+       previous_slot = prev_slot(ring, current_slot);
+       ring->ops->set_current_rxslot(ring, previous_slot);
+}
+
 void b43_dma_rx(struct b43_dmaring *ring)
 {
        const struct b43_dma_ops *ops = ring->ops;
index 9fdd198..df8c8cd 100644 (file)
@@ -9,7 +9,7 @@
 /* DMA-Interrupt reasons. */
 #define B43_DMAIRQ_FATALMASK   ((1 << 10) | (1 << 11) | (1 << 12) \
                                         | (1 << 14) | (1 << 15))
-#define B43_DMAIRQ_NONFATALMASK        (1 << 13)
+#define B43_DMAIRQ_RDESC_UFLOW         (1 << 13)
 #define B43_DMAIRQ_RX_DONE             (1 << 16)
 
 /*** 32-bit DMA Engine. ***/
@@ -295,6 +295,8 @@ int b43_dma_tx(struct b43_wldev *dev,
 void b43_dma_handle_txstatus(struct b43_wldev *dev,
                             const struct b43_txstatus *status);
 
+void b43_dma_handle_rx_overflow(struct b43_dmaring *ring);
+
 void b43_dma_rx(struct b43_dmaring *ring);
 
 void b43_dma_direct_fifo_rx(struct b43_wldev *dev,
index d377f77..a95b77a 100644 (file)
@@ -1902,30 +1902,18 @@ static void b43_do_interrupt_thread(struct b43_wldev *dev)
                }
        }
 
-       if (unlikely(merged_dma_reason & (B43_DMAIRQ_FATALMASK |
-                                         B43_DMAIRQ_NONFATALMASK))) {
-               if (merged_dma_reason & B43_DMAIRQ_FATALMASK) {
-                       b43err(dev->wl, "Fatal DMA error: "
-                              "0x%08X, 0x%08X, 0x%08X, "
-                              "0x%08X, 0x%08X, 0x%08X\n",
-                              dma_reason[0], dma_reason[1],
-                              dma_reason[2], dma_reason[3],
-                              dma_reason[4], dma_reason[5]);
-                       b43err(dev->wl, "This device does not support DMA "
+       if (unlikely(merged_dma_reason & (B43_DMAIRQ_FATALMASK))) {
+               b43err(dev->wl,
+                       "Fatal DMA error: 0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X\n",
+                       dma_reason[0], dma_reason[1],
+                       dma_reason[2], dma_reason[3],
+                       dma_reason[4], dma_reason[5]);
+               b43err(dev->wl, "This device does not support DMA "
                               "on your system. It will now be switched to PIO.\n");
-                       /* Fall back to PIO transfers if we get fatal DMA errors! */
-                       dev->use_pio = true;
-                       b43_controller_restart(dev, "DMA error");
-                       return;
-               }
-               if (merged_dma_reason & B43_DMAIRQ_NONFATALMASK) {
-                       b43err(dev->wl, "DMA error: "
-                              "0x%08X, 0x%08X, 0x%08X, "
-                              "0x%08X, 0x%08X, 0x%08X\n",
-                              dma_reason[0], dma_reason[1],
-                              dma_reason[2], dma_reason[3],
-                              dma_reason[4], dma_reason[5]);
-               }
+               /* Fall back to PIO transfers if we get fatal DMA errors! */
+               dev->use_pio = true;
+               b43_controller_restart(dev, "DMA error");
+               return;
        }
 
        if (unlikely(reason & B43_IRQ_UCODE_DEBUG))
@@ -1944,6 +1932,11 @@ static void b43_do_interrupt_thread(struct b43_wldev *dev)
                handle_irq_noise(dev);
 
        /* Check the DMA reason registers for received data. */
+       if (dma_reason[0] & B43_DMAIRQ_RDESC_UFLOW) {
+               if (B43_DEBUG)
+                       b43warn(dev->wl, "RX descriptor underrun\n");
+               b43_dma_handle_rx_overflow(dev->dma.rx_ring);
+       }
        if (dma_reason[0] & B43_DMAIRQ_RX_DONE) {
                if (b43_using_pio_transfers(dev))
                        b43_pio_rx(dev->pio.rx_queue);
@@ -2001,7 +1994,7 @@ static irqreturn_t b43_do_interrupt(struct b43_wldev *dev)
                return IRQ_NONE;
 
        dev->dma_reason[0] = b43_read32(dev, B43_MMIO_DMA0_REASON)
-           & 0x0001DC00;
+           & 0x0001FC00;
        dev->dma_reason[1] = b43_read32(dev, B43_MMIO_DMA1_REASON)
            & 0x0000DC00;
        dev->dma_reason[2] = b43_read32(dev, B43_MMIO_DMA2_REASON)
@@ -2465,7 +2458,7 @@ static void b43_request_firmware(struct work_struct *work)
        for (i = 0; i < B43_NR_FWTYPES; i++) {
                errmsg = ctx->errors[i];
                if (strlen(errmsg))
-                       b43err(dev->wl, errmsg);
+                       b43err(dev->wl, "%s", errmsg);
        }
        b43_print_fw_helptext(dev->wl, 1);
        goto out;
@@ -3130,7 +3123,7 @@ static int b43_chip_init(struct b43_wldev *dev)
                b43_write32(dev, 0x018C, 0x02000000);
        }
        b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, 0x00004000);
-       b43_write32(dev, B43_MMIO_DMA0_IRQ_MASK, 0x0001DC00);
+       b43_write32(dev, B43_MMIO_DMA0_IRQ_MASK, 0x0001FC00);
        b43_write32(dev, B43_MMIO_DMA1_IRQ_MASK, 0x0000DC00);
        b43_write32(dev, B43_MMIO_DMA2_IRQ_MASK, 0x0000DC00);
        b43_write32(dev, B43_MMIO_DMA3_IRQ_MASK, 0x0001DC00);
index be0787c..9431af2 100644 (file)
@@ -27,7 +27,6 @@
 #include "tracepoint.h"
 
 #define PKTFILTER_BUF_SIZE             128
-#define BRCMF_ARPOL_MODE               0xb     /* agent|snoop|peer_autoreply */
 #define BRCMF_DEFAULT_BCN_TIMEOUT      3
 #define BRCMF_DEFAULT_SCAN_CHANNEL_TIME        40
 #define BRCMF_DEFAULT_SCAN_UNASSOC_TIME        40
@@ -338,23 +337,6 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
                goto done;
        }
 
-       /* Try to set and enable ARP offload feature, this may fail */
-       err = brcmf_fil_iovar_int_set(ifp, "arp_ol", BRCMF_ARPOL_MODE);
-       if (err) {
-               brcmf_dbg(TRACE, "failed to set ARP offload mode to 0x%x, err = %d\n",
-                         BRCMF_ARPOL_MODE, err);
-               err = 0;
-       } else {
-               err = brcmf_fil_iovar_int_set(ifp, "arpoe", 1);
-               if (err) {
-                       brcmf_dbg(TRACE, "failed to enable ARP offload err = %d\n",
-                                 err);
-                       err = 0;
-               } else
-                       brcmf_dbg(TRACE, "successfully enabled ARP offload to 0x%x\n",
-                                 BRCMF_ARPOL_MODE);
-       }
-
        /* Setup packet filter */
        brcmf_c_pktfilter_offload_set(ifp, BRCMF_DEFAULT_PACKET_FILTER);
        brcmf_c_pktfilter_offload_enable(ifp, BRCMF_DEFAULT_PACKET_FILTER,
index 59c2546..b98f223 100644 (file)
@@ -653,10 +653,13 @@ int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked)
 
        brcmf_dbg(INFO, "%s: Broadcom Dongle Host Driver\n", ndev->name);
 
+       ndev->destructor = free_netdev;
        return 0;
 
 fail:
+       drvr->iflist[ifp->bssidx] = NULL;
        ndev->netdev_ops = NULL;
+       free_netdev(ndev);
        return -EBADE;
 }
 
@@ -720,6 +723,9 @@ static int brcmf_net_p2p_attach(struct brcmf_if *ifp)
        return 0;
 
 fail:
+       ifp->drvr->iflist[ifp->bssidx] = NULL;
+       ndev->netdev_ops = NULL;
+       free_netdev(ndev);
        return -EBADE;
 }
 
@@ -788,6 +794,7 @@ void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx)
        struct brcmf_if *ifp;
 
        ifp = drvr->iflist[bssidx];
+       drvr->iflist[bssidx] = NULL;
        if (!ifp) {
                brcmf_err("Null interface, idx=%d\n", bssidx);
                return;
@@ -808,15 +815,13 @@ void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx)
                        cancel_work_sync(&ifp->setmacaddr_work);
                        cancel_work_sync(&ifp->multicast_work);
                }
-
+               /* unregister will take care of freeing it */
                unregister_netdev(ifp->ndev);
                if (bssidx == 0)
                        brcmf_cfg80211_detach(drvr->config);
-               free_netdev(ifp->ndev);
        } else {
                kfree(ifp);
        }
-       drvr->iflist[bssidx] = NULL;
 }
 
 int brcmf_attach(uint bus_hdrlen, struct device *dev)
@@ -925,8 +930,6 @@ fail:
                        brcmf_fws_del_interface(ifp);
                        brcmf_fws_deinit(drvr);
                }
-               free_netdev(ifp->ndev);
-               drvr->iflist[0] = NULL;
                if (p2p_ifp) {
                        free_netdev(p2p_ifp->ndev);
                        drvr->iflist[1] = NULL;
@@ -934,7 +937,8 @@ fail:
                return ret;
        }
        if ((brcmf_p2p_enable) && (p2p_ifp))
-               brcmf_net_p2p_attach(p2p_ifp);
+               if (brcmf_net_p2p_attach(p2p_ifp) < 0)
+                       brcmf_p2p_enable = 0;
 
        return 0;
 }
index 5a64280..83ee53a 100644 (file)
@@ -202,7 +202,8 @@ static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr,
                        return;
                brcmf_fws_add_interface(ifp);
                if (!drvr->fweh.evt_handler[BRCMF_E_IF])
-                       err = brcmf_net_attach(ifp, false);
+                       if (brcmf_net_attach(ifp, false) < 0)
+                               return;
        }
 
        if (ifevent->action == BRCMF_E_IF_CHANGE)
index 0f2c83b..665ef69 100644 (file)
 
 #define BRCMF_FIL_ACTION_FRAME_SIZE    1800
 
+/* ARP Offload feature flags for arp_ol iovar */
+#define BRCMF_ARP_OL_AGENT             0x00000001
+#define BRCMF_ARP_OL_SNOOP             0x00000002
+#define BRCMF_ARP_OL_HOST_AUTO_REPLY   0x00000004
+#define BRCMF_ARP_OL_PEER_AUTO_REPLY   0x00000008
+
 
 enum brcmf_fil_p2p_if_types {
        BRCMF_FIL_P2P_IF_CLIENT,
index e7a1a47..79555f0 100644 (file)
@@ -47,6 +47,7 @@
 #define IS_P2P_SOCIAL_CHANNEL(channel) ((channel == SOCIAL_CHAN_1) || \
                                         (channel == SOCIAL_CHAN_2) || \
                                         (channel == SOCIAL_CHAN_3))
+#define BRCMF_P2P_TEMP_CHAN    SOCIAL_CHAN_3
 #define SOCIAL_CHAN_CNT                3
 #define AF_PEER_SEARCH_CNT     2
 
@@ -1954,21 +1955,21 @@ s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg)
                err = brcmf_fil_iovar_int_set(pri_ifp, "p2p_disc", 1);
                if (err < 0) {
                        brcmf_err("set p2p_disc error\n");
-                       brcmf_free_vif(p2p_vif);
+                       brcmf_free_vif(cfg, p2p_vif);
                        goto exit;
                }
                /* obtain bsscfg index for P2P discovery */
                err = brcmf_fil_iovar_int_get(pri_ifp, "p2p_dev", &bssidx);
                if (err < 0) {
                        brcmf_err("retrieving discover bsscfg index failed\n");
-                       brcmf_free_vif(p2p_vif);
+                       brcmf_free_vif(cfg, p2p_vif);
                        goto exit;
                }
                /* Verify that firmware uses same bssidx as driver !! */
                if (p2p_ifp->bssidx != bssidx) {
                        brcmf_err("Incorrect bssidx=%d, compared to p2p_ifp->bssidx=%d\n",
                                  bssidx, p2p_ifp->bssidx);
-                       brcmf_free_vif(p2p_vif);
+                       brcmf_free_vif(cfg, p2p_vif);
                        goto exit;
                }
 
@@ -1996,7 +1997,7 @@ void brcmf_p2p_detach(struct brcmf_p2p_info *p2p)
                brcmf_p2p_cancel_remain_on_channel(vif->ifp);
                brcmf_p2p_deinit_discovery(p2p);
                /* remove discovery interface */
-               brcmf_free_vif(vif);
+               brcmf_free_vif(p2p->cfg, vif);
                p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL;
        }
        /* just set it all to zero */
@@ -2013,17 +2014,30 @@ static void brcmf_p2p_get_current_chanspec(struct brcmf_p2p_info *p2p,
                                           u16 *chanspec)
 {
        struct brcmf_if *ifp;
-       struct brcmf_fil_chan_info_le ci;
+       u8 mac_addr[ETH_ALEN];
        struct brcmu_chan ch;
-       s32 err;
+       struct brcmf_bss_info_le *bi;
+       u8 *buf;
 
        ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp;
 
-       ch.chnum = 11;
-
-       err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_CHANNEL, &ci, sizeof(ci));
-       if (!err)
-               ch.chnum = le32_to_cpu(ci.hw_channel);
+       if (brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSSID, mac_addr,
+                                  ETH_ALEN) == 0) {
+               buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
+               if (buf != NULL) {
+                       *(__le32 *)buf = cpu_to_le32(WL_BSS_INFO_MAX);
+                       if (brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSS_INFO,
+                                                  buf, WL_BSS_INFO_MAX) == 0) {
+                               bi = (struct brcmf_bss_info_le *)(buf + 4);
+                               *chanspec = le16_to_cpu(bi->chanspec);
+                               kfree(buf);
+                               return;
+                       }
+                       kfree(buf);
+               }
+       }
+       /* Use default channel for P2P */
+       ch.chnum = BRCMF_P2P_TEMP_CHAN;
        ch.bw = BRCMU_CHAN_BW_20;
        p2p->cfg->d11inf.encchspec(&ch);
        *chanspec = ch.chspec;
@@ -2208,7 +2222,7 @@ static struct wireless_dev *brcmf_p2p_create_p2pdev(struct brcmf_p2p_info *p2p,
        return &p2p_vif->wdev;
 
 fail:
-       brcmf_free_vif(p2p_vif);
+       brcmf_free_vif(p2p->cfg, p2p_vif);
        return ERR_PTR(err);
 }
 
@@ -2217,13 +2231,31 @@ fail:
  *
  * @vif: virtual interface object to delete.
  */
-static void brcmf_p2p_delete_p2pdev(struct brcmf_cfg80211_vif *vif)
+static void brcmf_p2p_delete_p2pdev(struct brcmf_cfg80211_info *cfg,
+                                   struct brcmf_cfg80211_vif *vif)
 {
-       struct brcmf_p2p_info *p2p = &vif->ifp->drvr->config->p2p;
-
        cfg80211_unregister_wdev(&vif->wdev);
-       p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL;
-       brcmf_free_vif(vif);
+       cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL;
+       brcmf_free_vif(cfg, vif);
+}
+
+/**
+ * brcmf_p2p_free_p2p_if() - free up net device related data.
+ *
+ * @ndev: net device that needs to be freed.
+ */
+static void brcmf_p2p_free_p2p_if(struct net_device *ndev)
+{
+       struct brcmf_cfg80211_info *cfg;
+       struct brcmf_cfg80211_vif *vif;
+       struct brcmf_if *ifp;
+
+       ifp = netdev_priv(ndev);
+       cfg = ifp->drvr->config;
+       vif = ifp->vif;
+
+       brcmf_free_vif(cfg, vif);
+       free_netdev(ifp->ndev);
 }
 
 /**
@@ -2303,6 +2335,9 @@ struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name,
                brcmf_err("Registering netdevice failed\n");
                goto fail;
        }
+       /* override destructor */
+       ifp->ndev->destructor = brcmf_p2p_free_p2p_if;
+
        cfg->p2p.bss_idx[P2PAPI_BSSCFG_CONNECTION].vif = vif;
        /* Disable firmware roaming for P2P interface  */
        brcmf_fil_iovar_int_set(ifp, "roam_off", 1);
@@ -2314,7 +2349,7 @@ struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name,
        return &ifp->vif->wdev;
 
 fail:
-       brcmf_free_vif(vif);
+       brcmf_free_vif(cfg, vif);
        return ERR_PTR(err);
 }
 
@@ -2350,7 +2385,7 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev)
                break;
 
        case NL80211_IFTYPE_P2P_DEVICE:
-               brcmf_p2p_delete_p2pdev(vif);
+               brcmf_p2p_delete_p2pdev(cfg, vif);
                return 0;
        default:
                return -ENOTSUPP;
@@ -2378,7 +2413,6 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev)
                        err = 0;
        }
        brcmf_cfg80211_arm_vif_event(cfg, NULL);
-       brcmf_free_vif(vif);
        p2p->bss_idx[P2PAPI_BSSCFG_CONNECTION].vif = NULL;
 
        return err;
index 6d758f2..301e572 100644 (file)
@@ -459,6 +459,38 @@ send_key_to_dongle(struct net_device *ndev, struct brcmf_wsec_key *key)
        return err;
 }
 
+static s32
+brcmf_configure_arp_offload(struct brcmf_if *ifp, bool enable)
+{
+       s32 err;
+       u32 mode;
+
+       if (enable)
+               mode = BRCMF_ARP_OL_AGENT | BRCMF_ARP_OL_PEER_AUTO_REPLY;
+       else
+               mode = 0;
+
+       /* Try to set and enable ARP offload feature, this may fail, then it  */
+       /* is simply not supported and err 0 will be returned                 */
+       err = brcmf_fil_iovar_int_set(ifp, "arp_ol", mode);
+       if (err) {
+               brcmf_dbg(TRACE, "failed to set ARP offload mode to 0x%x, err = %d\n",
+                         mode, err);
+               err = 0;
+       } else {
+               err = brcmf_fil_iovar_int_set(ifp, "arpoe", enable);
+               if (err) {
+                       brcmf_dbg(TRACE, "failed to configure (%d) ARP offload err = %d\n",
+                                 enable, err);
+                       err = 0;
+               } else
+                       brcmf_dbg(TRACE, "successfully configured (%d) ARP offload to 0x%x\n",
+                                 enable, mode);
+       }
+
+       return err;
+}
+
 static struct wireless_dev *brcmf_cfg80211_add_iface(struct wiphy *wiphy,
                                                     const char *name,
                                                     enum nl80211_iftype type,
@@ -2216,6 +2248,11 @@ brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev,
        }
 
        pm = enabled ? PM_FAST : PM_OFF;
+       /* Do not enable the power save after assoc if it is a p2p interface */
+       if (ifp->vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT) {
+               brcmf_dbg(INFO, "Do not enable power save for P2P clients\n");
+               pm = PM_OFF;
+       }
        brcmf_dbg(INFO, "power save %s\n", (pm ? "enabled" : "disabled"));
 
        err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM, pm);
@@ -3639,11 +3676,29 @@ brcmf_config_ap_mgmt_ie(struct brcmf_cfg80211_vif *vif,
        return err;
 }
 
+static s32
+brcmf_cfg80211_set_channel(struct brcmf_cfg80211_info *cfg,
+                          struct brcmf_if *ifp,
+                          struct ieee80211_channel *channel)
+{
+       u16 chanspec;
+       s32 err;
+
+       brcmf_dbg(TRACE, "band=%d, center_freq=%d\n", channel->band,
+                 channel->center_freq);
+
+       chanspec = channel_to_chanspec(&cfg->d11inf, channel);
+       err = brcmf_fil_iovar_int_set(ifp, "chanspec", chanspec);
+
+       return err;
+}
+
 static s32
 brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
                        struct cfg80211_ap_settings *settings)
 {
        s32 ie_offset;
+       struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
        struct brcmf_if *ifp = netdev_priv(ndev);
        struct brcmf_tlv *ssid_ie;
        struct brcmf_ssid_le ssid_le;
@@ -3683,6 +3738,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
        }
 
        brcmf_set_mpc(ifp, 0);
+       brcmf_configure_arp_offload(ifp, false);
 
        /* find the RSN_IE */
        rsn_ie = brcmf_parse_tlvs((u8 *)settings->beacon.tail,
@@ -3713,6 +3769,12 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
 
        brcmf_config_ap_mgmt_ie(ifp->vif, &settings->beacon);
 
+       err = brcmf_cfg80211_set_channel(cfg, ifp, settings->chandef.chan);
+       if (err < 0) {
+               brcmf_err("Set Channel failed, %d\n", err);
+               goto exit;
+       }
+
        if (settings->beacon_interval) {
                err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_BCNPRD,
                                            settings->beacon_interval);
@@ -3789,8 +3851,10 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
        set_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state);
 
 exit:
-       if (err)
+       if (err) {
                brcmf_set_mpc(ifp, 1);
+               brcmf_configure_arp_offload(ifp, true);
+       }
        return err;
 }
 
@@ -3831,6 +3895,7 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev)
                        brcmf_err("bss_enable config failed %d\n", err);
        }
        brcmf_set_mpc(ifp, 1);
+       brcmf_configure_arp_offload(ifp, true);
        set_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state);
        clear_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state);
 
@@ -4140,11 +4205,15 @@ static const struct ieee80211_iface_limit brcmf_iface_limits[] = {
                .types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
                         BIT(NL80211_IFTYPE_P2P_GO)
        },
+       {
+               .max = 1,
+               .types = BIT(NL80211_IFTYPE_P2P_DEVICE)
+       }
 };
 static const struct ieee80211_iface_combination brcmf_iface_combos[] = {
        {
                 .max_interfaces = BRCMF_IFACE_MAX_CNT,
-                .num_different_channels = 1, /* no multi-channel for now */
+                .num_different_channels = 2,
                 .n_limits = ARRAY_SIZE(brcmf_iface_limits),
                 .limits = brcmf_iface_limits
        }
@@ -4197,7 +4266,8 @@ static struct wiphy *brcmf_setup_wiphy(struct device *phydev)
                                 BIT(NL80211_IFTYPE_ADHOC) |
                                 BIT(NL80211_IFTYPE_AP) |
                                 BIT(NL80211_IFTYPE_P2P_CLIENT) |
-                                BIT(NL80211_IFTYPE_P2P_GO);
+                                BIT(NL80211_IFTYPE_P2P_GO) |
+                                BIT(NL80211_IFTYPE_P2P_DEVICE);
        wiphy->iface_combinations = brcmf_iface_combos;
        wiphy->n_iface_combinations = ARRAY_SIZE(brcmf_iface_combos);
        wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
@@ -4251,20 +4321,16 @@ struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg,
        return vif;
 }
 
-void brcmf_free_vif(struct brcmf_cfg80211_vif *vif)
+void brcmf_free_vif(struct brcmf_cfg80211_info *cfg,
+                   struct brcmf_cfg80211_vif *vif)
 {
-       struct brcmf_cfg80211_info *cfg;
-       struct wiphy *wiphy;
-
-       wiphy = vif->wdev.wiphy;
-       cfg = wiphy_priv(wiphy);
        list_del(&vif->list);
        cfg->vif_cnt--;
 
        kfree(vif);
        if (!cfg->vif_cnt) {
-               wiphy_unregister(wiphy);
-               wiphy_free(wiphy);
+               wiphy_unregister(cfg->wiphy);
+               wiphy_free(cfg->wiphy);
        }
 }
 
@@ -4641,7 +4707,6 @@ static s32 brcmf_notify_vif_event(struct brcmf_if *ifp,
                return 0;
 
        case BRCMF_E_IF_DEL:
-               ifp->vif = NULL;
                mutex_unlock(&event->vif_event_lock);
                /* event may not be upon user request */
                if (brcmf_cfg80211_vif_event_armed(cfg))
@@ -4847,8 +4912,7 @@ cfg80211_p2p_attach_out:
        wl_deinit_priv(cfg);
 
 cfg80211_attach_out:
-       brcmf_free_vif(vif);
-       wiphy_free(wiphy);
+       brcmf_free_vif(cfg, vif);
        return NULL;
 }
 
@@ -4860,7 +4924,7 @@ void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg)
        wl_deinit_priv(cfg);
        brcmf_btcoex_detach(cfg);
        list_for_each_entry_safe(vif, tmp, &cfg->vif_list, list) {
-               brcmf_free_vif(vif);
+               brcmf_free_vif(cfg, vif);
        }
 }
 
@@ -5224,6 +5288,8 @@ static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg)
        if (err)
                goto default_conf_out;
 
+       brcmf_configure_arp_offload(ifp, true);
+
        cfg->dongle_up = true;
 default_conf_out:
 
index a71cff8..d9bdaf9 100644 (file)
@@ -487,7 +487,8 @@ enum nl80211_iftype brcmf_cfg80211_get_iftype(struct brcmf_if *ifp);
 struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg,
                                           enum nl80211_iftype type,
                                           bool pm_block);
-void brcmf_free_vif(struct brcmf_cfg80211_vif *vif);
+void brcmf_free_vif(struct brcmf_cfg80211_info *cfg,
+                   struct brcmf_cfg80211_vif *vif);
 
 s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag,
                          const u8 *vndr_ie_buf, u32 vndr_ie_len);
index b8f82e6..9a95045 100644 (file)
@@ -5741,8 +5741,7 @@ il4965_mac_setup_register(struct il_priv *il, u32 max_probe_length)
        hw->flags =
            IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_AMPDU_AGGREGATION |
            IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC | IEEE80211_HW_SPECTRUM_MGMT |
-           IEEE80211_HW_REPORTS_TX_ACK_STATUS | IEEE80211_HW_SUPPORTS_PS |
-           IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
+           IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
        if (il->cfg->sku & IL_SKU_N)
                hw->flags |=
                    IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS |
index 592d0aa..e9a3cbc 100644 (file)
@@ -1423,7 +1423,7 @@ il_setup_rx_scan_handlers(struct il_priv *il)
 }
 EXPORT_SYMBOL(il_setup_rx_scan_handlers);
 
-inline u16
+u16
 il_get_active_dwell_time(struct il_priv *il, enum ieee80211_band band,
                         u8 n_probes)
 {
index f8246f2..4caaf52 100644 (file)
@@ -1832,16 +1832,16 @@ u32 il_usecs_to_beacons(struct il_priv *il, u32 usec, u32 beacon_interval);
 __le32 il_add_beacon_time(struct il_priv *il, u32 base, u32 addon,
                          u32 beacon_interval);
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 extern const struct dev_pm_ops il_pm_ops;
 
 #define IL_LEGACY_PM_OPS       (&il_pm_ops)
 
-#else /* !CONFIG_PM */
+#else /* !CONFIG_PM_SLEEP */
 
 #define IL_LEGACY_PM_OPS       NULL
 
-#endif /* !CONFIG_PM */
+#endif /* !CONFIG_PM_SLEEP */
 
 /*****************************************************
 *  Error Handling Debugging
index db183b4..c3c13ce 100644 (file)
@@ -735,7 +735,7 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
                                        memcpy(&lq, priv->stations[i].lq,
                                               sizeof(struct iwl_link_quality_cmd));
 
-                               if (!memcmp(&lq, &zero_lq, sizeof(lq)))
+                               if (memcmp(&lq, &zero_lq, sizeof(lq)))
                                        send_lq = true;
                        }
                        spin_unlock_bh(&priv->sta_lock);
index 191dcae..c638455 100644 (file)
@@ -173,6 +173,8 @@ enum {
        REPLY_DEBUG_CMD = 0xf0,
        DEBUG_LOG_MSG = 0xf7,
 
+       MCAST_FILTER_CMD = 0xd0,
+
        /* D3 commands/notifications */
        D3_CONFIG_CMD = 0xd3,
        PROT_OFFLOAD_CONFIG_CMD = 0xd4,
@@ -948,4 +950,29 @@ struct iwl_set_calib_default_cmd {
        u8 data[0];
 } __packed; /* PHY_CALIB_OVERRIDE_VALUES_S */
 
+#define MAX_PORT_ID_NUM        2
+
+/**
+ * struct iwl_mcast_filter_cmd - configure multicast filter.
+ * @filter_own: Set 1 to filter out multicast packets sent by station itself
+ * @port_id:   Multicast MAC addresses array specifier. This is a strange way
+ *             to identify network interface adopted in host-device IF.
+ *             It is used by FW as index in array of addresses. This array has
+ *             MAX_PORT_ID_NUM members.
+ * @count:     Number of MAC addresses in the array
+ * @pass_all:  Set 1 to pass all multicast packets.
+ * @bssid:     current association BSSID.
+ * @addr_list: Place holder for array of MAC addresses.
+ *             IMPORTANT: add padding if necessary to ensure DWORD alignment.
+ */
+struct iwl_mcast_filter_cmd {
+       u8 filter_own;
+       u8 port_id;
+       u8 count;
+       u8 pass_all;
+       u8 bssid[6];
+       u8 reserved[2];
+       u8 addr_list[0];
+} __packed; /* MCAST_FILTERING_CMD_API_S_VER_1 */
+
 #endif /* __fw_api_h__ */
index e6eca4d..b2cc3d9 100644 (file)
@@ -586,10 +586,12 @@ static int iwl_mvm_mac_ctxt_send_cmd(struct iwl_mvm *mvm,
  */
 static void iwl_mvm_mac_ctxt_cmd_fill_sta(struct iwl_mvm *mvm,
                                          struct ieee80211_vif *vif,
-                                         struct iwl_mac_data_sta *ctxt_sta)
+                                         struct iwl_mac_data_sta *ctxt_sta,
+                                         bool force_assoc_off)
 {
        /* We need the dtim_period to set the MAC as associated */
-       if (vif->bss_conf.assoc && vif->bss_conf.dtim_period) {
+       if (vif->bss_conf.assoc && vif->bss_conf.dtim_period &&
+           !force_assoc_off) {
                u32 dtim_offs;
 
                /*
@@ -659,7 +661,8 @@ static int iwl_mvm_mac_ctxt_cmd_station(struct iwl_mvm *mvm,
                cmd.filter_flags &= ~cpu_to_le32(MAC_FILTER_IN_BEACON);
 
        /* Fill the data specific for station mode */
-       iwl_mvm_mac_ctxt_cmd_fill_sta(mvm, vif, &cmd.sta);
+       iwl_mvm_mac_ctxt_cmd_fill_sta(mvm, vif, &cmd.sta,
+                                     action == FW_CTXT_ACTION_ADD);
 
        return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
 }
@@ -677,7 +680,8 @@ static int iwl_mvm_mac_ctxt_cmd_p2p_client(struct iwl_mvm *mvm,
        iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
 
        /* Fill the data specific for station mode */
-       iwl_mvm_mac_ctxt_cmd_fill_sta(mvm, vif, &cmd.p2p_sta.sta);
+       iwl_mvm_mac_ctxt_cmd_fill_sta(mvm, vif, &cmd.p2p_sta.sta,
+                                     action == FW_CTXT_ACTION_ADD);
 
        cmd.p2p_sta.ctwin = cpu_to_le32(noa->oppps_ctwindow &
                                        IEEE80211_P2P_OPPPS_CTWINDOW_MASK);
index dd158ec..a5eb8c8 100644 (file)
@@ -701,6 +701,20 @@ static void iwl_mvm_configure_filter(struct ieee80211_hw *hw,
        *total_flags = 0;
 }
 
+static int iwl_mvm_configure_mcast_filter(struct iwl_mvm *mvm,
+                                         struct ieee80211_vif *vif)
+{
+       struct iwl_mcast_filter_cmd mcast_filter_cmd = {
+               .pass_all = 1,
+       };
+
+       memcpy(mcast_filter_cmd.bssid, vif->bss_conf.bssid, ETH_ALEN);
+
+       return iwl_mvm_send_cmd_pdu(mvm, MCAST_FILTER_CMD, CMD_SYNC,
+                                   sizeof(mcast_filter_cmd),
+                                   &mcast_filter_cmd);
+}
+
 static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
                                             struct ieee80211_vif *vif,
                                             struct ieee80211_bss_conf *bss_conf,
@@ -722,6 +736,7 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
                                return;
                        }
                        iwl_mvm_bt_coex_vif_assoc(mvm, vif);
+                       iwl_mvm_configure_mcast_filter(mvm, vif);
                } else if (mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT) {
                        /* remove AP station now that the MAC is unassoc */
                        ret = iwl_mvm_rm_sta_id(mvm, vif, mvmvif->ap_sta_id);
@@ -931,7 +946,7 @@ static void iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw,
 
        switch (cmd) {
        case STA_NOTIFY_SLEEP:
-               if (atomic_read(&mvmsta->pending_frames) > 0)
+               if (atomic_read(&mvm->pending_frames[mvmsta->sta_id]) > 0)
                        ieee80211_sta_block_awake(hw, sta, true);
                /*
                 * The fw updates the STA to be asleep. Tx packets on the Tx
index 8269bc5..9f46b23 100644 (file)
@@ -292,6 +292,7 @@ struct iwl_mvm {
        struct ieee80211_sta __rcu *fw_id_to_mac_id[IWL_MVM_STATION_COUNT];
        struct work_struct sta_drained_wk;
        unsigned long sta_drained[BITS_TO_LONGS(IWL_MVM_STATION_COUNT)];
+       atomic_t pending_frames[IWL_MVM_STATION_COUNT];
 
        /* configured by mac80211 */
        u32 rts_threshold;
index fe031d3..b29c31a 100644 (file)
@@ -292,6 +292,7 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = {
        CMD(BT_COEX_PROT_ENV),
        CMD(BT_PROFILE_NOTIFICATION),
        CMD(BT_CONFIG),
+       CMD(MCAST_FILTER_CMD),
 };
 #undef CMD
 
index 2157b0f..2476e43 100644 (file)
@@ -298,6 +298,12 @@ int iwl_mvm_scan_request(struct iwl_mvm *mvm,
        else
                cmd->type = cpu_to_le32(SCAN_TYPE_FORCED);
 
+       /*
+        * TODO: This is a WA due to a bug in the FW AUX framework that does not
+        * properly handle time events that fail to be scheduled
+        */
+       cmd->type = cpu_to_le32(SCAN_TYPE_FORCED);
+
        cmd->repeats = cpu_to_le32(1);
 
        /*
index 0fd96e4..5c664ed 100644 (file)
@@ -219,7 +219,7 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm,
        mvm_sta->max_agg_bufsize = LINK_QUAL_AGG_FRAME_LIMIT_DEF;
 
        /* HW restart, don't assume the memory has been zeroed */
-       atomic_set(&mvm_sta->pending_frames, 0);
+       atomic_set(&mvm->pending_frames[sta_id], 0);
        mvm_sta->tid_disable_agg = 0;
        mvm_sta->tfd_queue_msk = 0;
        for (i = 0; i < IEEE80211_NUM_ACS; i++)
@@ -406,15 +406,22 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
                mvmvif->ap_sta_id = IWL_MVM_STATION_COUNT;
        }
 
+       /*
+        * Make sure that the tx response code sees the station as -EBUSY and
+        * calls the drain worker.
+        */
+       spin_lock_bh(&mvm_sta->lock);
        /*
         * There are frames pending on the AC queues for this station.
         * We need to wait until all the frames are drained...
         */
-       if (atomic_read(&mvm_sta->pending_frames)) {
-               ret = iwl_mvm_drain_sta(mvm, mvm_sta, true);
+       if (atomic_read(&mvm->pending_frames[mvm_sta->sta_id])) {
                rcu_assign_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id],
                                   ERR_PTR(-EBUSY));
+               spin_unlock_bh(&mvm_sta->lock);
+               ret = iwl_mvm_drain_sta(mvm, mvm_sta, true);
        } else {
+               spin_unlock_bh(&mvm_sta->lock);
                ret = iwl_mvm_rm_sta_common(mvm, mvm_sta->sta_id);
                rcu_assign_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id], NULL);
        }
index 12abd2d..a4ddce7 100644 (file)
@@ -274,7 +274,6 @@ struct iwl_mvm_tid_data {
  * @bt_reduced_txpower: is reduced tx power enabled for this station
  * @lock: lock to protect the whole struct. Since %tid_data is access from Tx
  * and from Tx response flow, it needs a spinlock.
- * @pending_frames: number of frames for this STA on the shared Tx queues.
  * @tid_data: per tid data. Look at %iwl_mvm_tid_data.
  *
  * When mac80211 creates a station it reserves some space (hw->sta_data_size)
@@ -290,7 +289,6 @@ struct iwl_mvm_sta {
        u8 max_agg_bufsize;
        bool bt_reduced_txpower;
        spinlock_t lock;
-       atomic_t pending_frames;
        struct iwl_mvm_tid_data tid_data[IWL_MAX_TID_COUNT];
        struct iwl_lq_sta lq_sta;
        struct ieee80211_vif *vif;
index 4790743..f212f16 100644 (file)
@@ -416,9 +416,8 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb,
 
        spin_unlock(&mvmsta->lock);
 
-       if (mvmsta->vif->type == NL80211_IFTYPE_AP &&
-           txq_id < IWL_MVM_FIRST_AGG_QUEUE)
-               atomic_inc(&mvmsta->pending_frames);
+       if (txq_id < IWL_MVM_FIRST_AGG_QUEUE)
+               atomic_inc(&mvm->pending_frames[mvmsta->sta_id]);
 
        return 0;
 
@@ -680,16 +679,41 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
        /*
         * If the txq is not an AMPDU queue, there is no chance we freed
         * several skbs. Check that out...
-        * If there are no pending frames for this STA, notify mac80211 that
-        * this station can go to sleep in its STA table.
         */
-       if (txq_id < IWL_MVM_FIRST_AGG_QUEUE && mvmsta &&
-           !WARN_ON(skb_freed > 1) &&
-           mvmsta->vif->type == NL80211_IFTYPE_AP &&
-           atomic_sub_and_test(skb_freed, &mvmsta->pending_frames)) {
-               ieee80211_sta_block_awake(mvm->hw, sta, false);
-               set_bit(sta_id, mvm->sta_drained);
-               schedule_work(&mvm->sta_drained_wk);
+       if (txq_id < IWL_MVM_FIRST_AGG_QUEUE && !WARN_ON(skb_freed > 1) &&
+           atomic_sub_and_test(skb_freed, &mvm->pending_frames[sta_id])) {
+               if (mvmsta) {
+                       /*
+                        * If there are no pending frames for this STA, notify
+                        * mac80211 that this station can go to sleep in its
+                        * STA table.
+                        */
+                       if (mvmsta->vif->type == NL80211_IFTYPE_AP)
+                               ieee80211_sta_block_awake(mvm->hw, sta, false);
+                       /*
+                        * We might very well have taken mvmsta pointer while
+                        * the station was being removed. The remove flow might
+                        * have seen a pending_frame (because we didn't take
+                        * the lock) even if now the queues are drained. So make
+                        * really sure now that this the station is not being
+                        * removed. If it is, run the drain worker to remove it.
+                        */
+                       spin_lock_bh(&mvmsta->lock);
+                       sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]);
+                       if (IS_ERR_OR_NULL(sta)) {
+                               /*
+                                * Station disappeared in the meantime:
+                                * so we are draining.
+                                */
+                               set_bit(sta_id, mvm->sta_drained);
+                               schedule_work(&mvm->sta_drained_wk);
+                       }
+                       spin_unlock_bh(&mvmsta->lock);
+               } else if (!mvmsta) {
+                       /* Tx response without STA, so we are draining */
+                       set_bit(sta_id, mvm->sta_drained);
+                       schedule_work(&mvm->sta_drained_wk);
+               }
        }
 
        rcu_read_unlock();
index b878a32..cb34c78 100644 (file)
@@ -1723,11 +1723,11 @@ static void mac80211_hwsim_free(void)
        class_destroy(hwsim_class);
 }
 
-
-static struct device_driver mac80211_hwsim_driver = {
-       .name = "mac80211_hwsim",
-       .bus = &platform_bus_type,
-       .owner = THIS_MODULE,
+static struct platform_driver mac80211_hwsim_driver = {
+       .driver = {
+               .name = "mac80211_hwsim",
+               .owner = THIS_MODULE,
+       },
 };
 
 static const struct net_device_ops hwsim_netdev_ops = {
@@ -2219,7 +2219,7 @@ static int __init init_mac80211_hwsim(void)
        spin_lock_init(&hwsim_radio_lock);
        INIT_LIST_HEAD(&hwsim_radios);
 
-       err = driver_register(&mac80211_hwsim_driver);
+       err = platform_driver_register(&mac80211_hwsim_driver);
        if (err)
                return err;
 
@@ -2254,7 +2254,7 @@ static int __init init_mac80211_hwsim(void)
                        err = -ENOMEM;
                        goto failed_drvdata;
                }
-               data->dev->driver = &mac80211_hwsim_driver;
+               data->dev->driver = &mac80211_hwsim_driver.driver;
                err = device_bind_driver(data->dev);
                if (err != 0) {
                        printk(KERN_DEBUG
@@ -2564,7 +2564,7 @@ failed_drvdata:
 failed:
        mac80211_hwsim_free();
 failed_unregister_driver:
-       driver_unregister(&mac80211_hwsim_driver);
+       platform_driver_unregister(&mac80211_hwsim_driver);
        return err;
 }
 module_init(init_mac80211_hwsim);
@@ -2577,6 +2577,6 @@ static void __exit exit_mac80211_hwsim(void)
 
        mac80211_hwsim_free();
        unregister_netdev(hwsim_mon);
-       driver_unregister(&mac80211_hwsim_driver);
+       platform_driver_unregister(&mac80211_hwsim_driver);
 }
 module_exit(exit_mac80211_hwsim);
index d3c8ece..e42b266 100644 (file)
@@ -2234,9 +2234,6 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
        if (wdev->netdev->reg_state == NETREG_REGISTERED)
                unregister_netdevice(wdev->netdev);
 
-       if (wdev->netdev->reg_state == NETREG_UNREGISTERED)
-               free_netdev(wdev->netdev);
-
        /* Clear the priv in adapter */
        priv->netdev = NULL;
 
index 74db0d2..26755d9 100644 (file)
@@ -1191,6 +1191,7 @@ mwifiex_process_hs_config(struct mwifiex_adapter *adapter)
        adapter->if_ops.wakeup(adapter);
        adapter->hs_activated = false;
        adapter->is_hs_configured = false;
+       adapter->is_suspended = false;
        mwifiex_hs_activated_event(mwifiex_get_priv(adapter,
                                                    MWIFIEX_BSS_ROLE_ANY),
                                   false);
index 753b568..a5f9875 100644 (file)
 static struct dentry *mwifiex_dfs_dir;
 
 static char *bss_modes[] = {
-       "Unknown",
-       "Ad-hoc",
-       "Managed",
-       "Auto"
+       "UNSPECIFIED",
+       "ADHOC",
+       "STATION",
+       "AP",
+       "AP_VLAN",
+       "WDS",
+       "MONITOR",
+       "MESH_POINT",
+       "P2P_CLIENT",
+       "P2P_GO",
+       "P2P_DEVICE",
 };
 
 /* size/addr for mwifiex_debug_info */
@@ -200,7 +207,12 @@ mwifiex_info_read(struct file *file, char __user *ubuf,
        p += sprintf(p, "driver_version = %s", fmt);
        p += sprintf(p, "\nverext = %s", priv->version_str);
        p += sprintf(p, "\ninterface_name=\"%s\"\n", netdev->name);
-       p += sprintf(p, "bss_mode=\"%s\"\n", bss_modes[info.bss_mode]);
+
+       if (info.bss_mode >= ARRAY_SIZE(bss_modes))
+               p += sprintf(p, "bss_mode=\"%d\"\n", info.bss_mode);
+       else
+               p += sprintf(p, "bss_mode=\"%s\"\n", bss_modes[info.bss_mode]);
+
        p += sprintf(p, "media_state=\"%s\"\n",
                     (!priv->media_connected ? "Disconnected" : "Connected"));
        p += sprintf(p, "mac_address=\"%pM\"\n", netdev->dev_addr);
index 121443a..2eb88ea 100644 (file)
@@ -655,6 +655,7 @@ void mwifiex_init_priv_params(struct mwifiex_private *priv,
                                                struct net_device *dev)
 {
        dev->netdev_ops = &mwifiex_netdev_ops;
+       dev->destructor = free_netdev;
        /* Initialize private structure */
        priv->current_key_index = 0;
        priv->media_connected = false;
index 311d0b2..1a8a19d 100644 (file)
@@ -96,7 +96,7 @@ int mwifiex_request_set_multicast_list(struct mwifiex_private *priv,
        } else {
                /* Multicast */
                priv->curr_pkt_filter &= ~HostCmd_ACT_MAC_PROMISCUOUS_ENABLE;
-               if (mcast_list->mode == MWIFIEX_MULTICAST_MODE) {
+               if (mcast_list->mode == MWIFIEX_ALL_MULTI_MODE) {
                        dev_dbg(priv->adapter->dev,
                                "info: Enabling All Multicast!\n");
                        priv->curr_pkt_filter |=
@@ -108,20 +108,11 @@ int mwifiex_request_set_multicast_list(struct mwifiex_private *priv,
                                dev_dbg(priv->adapter->dev,
                                        "info: Set multicast list=%d\n",
                                       mcast_list->num_multicast_addr);
-                               /* Set multicast addresses to firmware */
-                               if (old_pkt_filter == priv->curr_pkt_filter) {
-                                       /* Send request to firmware */
-                                       ret = mwifiex_send_cmd_async(priv,
-                                               HostCmd_CMD_MAC_MULTICAST_ADR,
-                                               HostCmd_ACT_GEN_SET, 0,
-                                               mcast_list);
-                               } else {
-                                       /* Send request to firmware */
-                                       ret = mwifiex_send_cmd_async(priv,
-                                               HostCmd_CMD_MAC_MULTICAST_ADR,
-                                               HostCmd_ACT_GEN_SET, 0,
-                                               mcast_list);
-                               }
+                               /* Send multicast addresses to firmware */
+                               ret = mwifiex_send_cmd_async(priv,
+                                       HostCmd_CMD_MAC_MULTICAST_ADR,
+                                       HostCmd_ACT_GEN_SET, 0,
+                                       mcast_list);
                        }
                }
        }
index 999ffc1..c97e9d3 100644 (file)
@@ -764,6 +764,7 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
                                 "can't alloc skb for rx\n");
                        goto done;
                }
+               kmemleak_not_leak(new_skb);
 
                pci_unmap_single(rtlpci->pdev,
                                 *((dma_addr_t *) skb->cb),
index d3a02e7..21ca33a 100644 (file)
@@ -550,7 +550,7 @@ do {                                                                \
         rxmcs == DESC92C_RATE11M)
 
 struct phy_rx_agc_info_t {
-       #if __LITTLE_ENDIAN
+       #ifdef __LITTLE_ENDIAN
                u8      gain:7, trsw:1;
        #else
                u8      trsw:1, gain:7;
@@ -574,7 +574,7 @@ struct phy_status_rpt {
        u8      stream_target_csi[2];
        u8      sig_evm;
        u8      rsvd_3;
-#if __LITTLE_ENDIAN
+#ifdef __LITTLE_ENDIAN
        u8      antsel_rx_keep_2:1;     /*ex_intf_flg:1;*/
        u8      sgi_en:1;
        u8      rxsc:2;
index 3d0498e..189ba12 100644 (file)
@@ -1973,26 +1973,35 @@ void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
        }
 }
 
-void rtl92cu_update_hal_rate_table(struct ieee80211_hw *hw,
-                                  struct ieee80211_sta *sta,
-                                  u8 rssi_level)
+static void rtl92cu_update_hal_rate_table(struct ieee80211_hw *hw,
+                                         struct ieee80211_sta *sta)
 {
        struct rtl_priv *rtlpriv = rtl_priv(hw);
        struct rtl_phy *rtlphy = &(rtlpriv->phy);
        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
-       u32 ratr_value = (u32) mac->basic_rates;
-       u8 *mcsrate = mac->mcs;
+       struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+       u32 ratr_value;
        u8 ratr_index = 0;
        u8 nmode = mac->ht_enable;
-       u8 mimo_ps = 1;
-       u16 shortgi_rate = 0;
-       u32 tmp_ratr_value = 0;
+       u8 mimo_ps = IEEE80211_SMPS_OFF;
+       u16 shortgi_rate;
+       u32 tmp_ratr_value;
        u8 curtxbw_40mhz = mac->bw_40;
-       u8 curshortgi_40mhz = mac->sgi_40;
-       u8 curshortgi_20mhz = mac->sgi_20;
+       u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ?
+                              1 : 0;
+       u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ?
+                              1 : 0;
        enum wireless_mode wirelessmode = mac->mode;
 
-       ratr_value |= ((*(u16 *) (mcsrate))) << 12;
+       if (rtlhal->current_bandtype == BAND_ON_5G)
+               ratr_value = sta->supp_rates[1] << 4;
+       else
+               ratr_value = sta->supp_rates[0];
+       if (mac->opmode == NL80211_IFTYPE_ADHOC)
+               ratr_value = 0xfff;
+
+       ratr_value |= (sta->ht_cap.mcs.rx_mask[1] << 20 |
+                       sta->ht_cap.mcs.rx_mask[0] << 12);
        switch (wirelessmode) {
        case WIRELESS_MODE_B:
                if (ratr_value & 0x0000000c)
@@ -2006,7 +2015,7 @@ void rtl92cu_update_hal_rate_table(struct ieee80211_hw *hw,
        case WIRELESS_MODE_N_24G:
        case WIRELESS_MODE_N_5G:
                nmode = 1;
-               if (mimo_ps == 0) {
+               if (mimo_ps == IEEE80211_SMPS_STATIC) {
                        ratr_value &= 0x0007F005;
                } else {
                        u32 ratr_mask;
@@ -2016,8 +2025,7 @@ void rtl92cu_update_hal_rate_table(struct ieee80211_hw *hw,
                                ratr_mask = 0x000ff005;
                        else
                                ratr_mask = 0x0f0ff005;
-                       if (curtxbw_40mhz)
-                               ratr_mask |= 0x00000010;
+
                        ratr_value &= ratr_mask;
                }
                break;
@@ -2026,41 +2034,74 @@ void rtl92cu_update_hal_rate_table(struct ieee80211_hw *hw,
                        ratr_value &= 0x000ff0ff;
                else
                        ratr_value &= 0x0f0ff0ff;
+
                break;
        }
+
        ratr_value &= 0x0FFFFFFF;
-       if (nmode && ((curtxbw_40mhz && curshortgi_40mhz) ||
-           (!curtxbw_40mhz && curshortgi_20mhz))) {
+
+       if (nmode && ((curtxbw_40mhz &&
+                        curshortgi_40mhz) || (!curtxbw_40mhz &&
+                                              curshortgi_20mhz))) {
+
                ratr_value |= 0x10000000;
                tmp_ratr_value = (ratr_value >> 12);
+
                for (shortgi_rate = 15; shortgi_rate > 0; shortgi_rate--) {
                        if ((1 << shortgi_rate) & tmp_ratr_value)
                                break;
                }
+
                shortgi_rate = (shortgi_rate << 12) | (shortgi_rate << 8) |
-                              (shortgi_rate << 4) | (shortgi_rate);
+                   (shortgi_rate << 4) | (shortgi_rate);
        }
+
        rtl_write_dword(rtlpriv, REG_ARFR0 + ratr_index * 4, ratr_value);
+
+       RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, "%x\n",
+                rtl_read_dword(rtlpriv, REG_ARFR0));
 }
 
-void rtl92cu_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level)
+static void rtl92cu_update_hal_rate_mask(struct ieee80211_hw *hw,
+                                        struct ieee80211_sta *sta,
+                                        u8 rssi_level)
 {
        struct rtl_priv *rtlpriv = rtl_priv(hw);
        struct rtl_phy *rtlphy = &(rtlpriv->phy);
        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
-       u32 ratr_bitmap = (u32) mac->basic_rates;
-       u8 *p_mcsrate = mac->mcs;
-       u8 ratr_index = 0;
-       u8 curtxbw_40mhz = mac->bw_40;
-       u8 curshortgi_40mhz = mac->sgi_40;
-       u8 curshortgi_20mhz = mac->sgi_20;
-       enum wireless_mode wirelessmode = mac->mode;
+       struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+       struct rtl_sta_info *sta_entry = NULL;
+       u32 ratr_bitmap;
+       u8 ratr_index;
+       u8 curtxbw_40mhz = (sta->bandwidth >= IEEE80211_STA_RX_BW_40) ? 1 : 0;
+       u8 curshortgi_40mhz = curtxbw_40mhz &&
+                             (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ?
+                               1 : 0;
+       u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ?
+                               1 : 0;
+       enum wireless_mode wirelessmode = 0;
        bool shortgi = false;
        u8 rate_mask[5];
        u8 macid = 0;
-       u8 mimops = 1;
-
-       ratr_bitmap |= (p_mcsrate[1] << 20) | (p_mcsrate[0] << 12);
+       u8 mimo_ps = IEEE80211_SMPS_OFF;
+
+       sta_entry = (struct rtl_sta_info *) sta->drv_priv;
+       wirelessmode = sta_entry->wireless_mode;
+       if (mac->opmode == NL80211_IFTYPE_STATION ||
+           mac->opmode == NL80211_IFTYPE_MESH_POINT)
+               curtxbw_40mhz = mac->bw_40;
+       else if (mac->opmode == NL80211_IFTYPE_AP ||
+               mac->opmode == NL80211_IFTYPE_ADHOC)
+               macid = sta->aid + 1;
+
+       if (rtlhal->current_bandtype == BAND_ON_5G)
+               ratr_bitmap = sta->supp_rates[1] << 4;
+       else
+               ratr_bitmap = sta->supp_rates[0];
+       if (mac->opmode == NL80211_IFTYPE_ADHOC)
+               ratr_bitmap = 0xfff;
+       ratr_bitmap |= (sta->ht_cap.mcs.rx_mask[1] << 20 |
+                       sta->ht_cap.mcs.rx_mask[0] << 12);
        switch (wirelessmode) {
        case WIRELESS_MODE_B:
                ratr_index = RATR_INX_WIRELESS_B;
@@ -2071,6 +2112,7 @@ void rtl92cu_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level)
                break;
        case WIRELESS_MODE_G:
                ratr_index = RATR_INX_WIRELESS_GB;
+
                if (rssi_level == 1)
                        ratr_bitmap &= 0x00000f00;
                else if (rssi_level == 2)
@@ -2085,7 +2127,8 @@ void rtl92cu_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level)
        case WIRELESS_MODE_N_24G:
        case WIRELESS_MODE_N_5G:
                ratr_index = RATR_INX_WIRELESS_NGB;
-               if (mimops == 0) {
+
+               if (mimo_ps == IEEE80211_SMPS_STATIC) {
                        if (rssi_level == 1)
                                ratr_bitmap &= 0x00070000;
                        else if (rssi_level == 2)
@@ -2128,8 +2171,10 @@ void rtl92cu_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level)
                                }
                        }
                }
+
                if ((curtxbw_40mhz && curshortgi_40mhz) ||
                    (!curtxbw_40mhz && curshortgi_20mhz)) {
+
                        if (macid == 0)
                                shortgi = true;
                        else if (macid == 1)
@@ -2138,21 +2183,42 @@ void rtl92cu_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level)
                break;
        default:
                ratr_index = RATR_INX_WIRELESS_NGB;
+
                if (rtlphy->rf_type == RF_1T2R)
                        ratr_bitmap &= 0x000ff0ff;
                else
                        ratr_bitmap &= 0x0f0ff0ff;
                break;
        }
-       RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, "ratr_bitmap :%x\n",
-                ratr_bitmap);
-       *(u32 *)&rate_mask = ((ratr_bitmap & 0x0fffffff) |
-                                     ratr_index << 28);
+       sta_entry->ratr_index = ratr_index;
+
+       RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG,
+                "ratr_bitmap :%x\n", ratr_bitmap);
+       *(u32 *)&rate_mask = (ratr_bitmap & 0x0fffffff) |
+                                    (ratr_index << 28);
        rate_mask[4] = macid | (shortgi ? 0x20 : 0x00) | 0x80;
        RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG,
                 "Rate_index:%x, ratr_val:%x, %5phC\n",
                 ratr_index, ratr_bitmap, rate_mask);
-       rtl92c_fill_h2c_cmd(hw, H2C_RA_MASK, 5, rate_mask);
+       memcpy(rtlpriv->rate_mask, rate_mask, 5);
+       /* rtl92c_fill_h2c_cmd() does USB I/O and will result in a
+        * "scheduled while atomic" if called directly */
+       schedule_work(&rtlpriv->works.fill_h2c_cmd);
+
+       if (macid != 0)
+               sta_entry->ratr_index = ratr_index;
+}
+
+void rtl92cu_update_hal_rate_tbl(struct ieee80211_hw *hw,
+                                struct ieee80211_sta *sta,
+                                u8 rssi_level)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+       if (rtlpriv->dm.useramask)
+               rtl92cu_update_hal_rate_mask(hw, sta, rssi_level);
+       else
+               rtl92cu_update_hal_rate_table(hw, sta);
 }
 
 void rtl92cu_update_channel_access_setting(struct ieee80211_hw *hw)
index f41a3aa..8e3ec1e 100644 (file)
@@ -98,10 +98,6 @@ void rtl92cu_update_interrupt_mask(struct ieee80211_hw *hw,
                                   u32 add_msr, u32 rm_msr);
 void rtl92cu_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val);
 void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val);
-void rtl92cu_update_hal_rate_table(struct ieee80211_hw *hw,
-                                  struct ieee80211_sta *sta,
-                                  u8 rssi_level);
-void rtl92cu_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level);
 
 void rtl92cu_update_channel_access_setting(struct ieee80211_hw *hw);
 bool rtl92cu_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 * valid);
index 85b6bdb..da4f587 100644 (file)
@@ -289,14 +289,30 @@ void rtl92c_set_key(struct ieee80211_hw *hw, u32 key_index,
                                macaddr = cam_const_broad;
                                entry_id = key_index;
                        } else {
+                               if (mac->opmode == NL80211_IFTYPE_AP ||
+                                   mac->opmode == NL80211_IFTYPE_MESH_POINT) {
+                                       entry_id = rtl_cam_get_free_entry(hw,
+                                                                p_macaddr);
+                                       if (entry_id >=  TOTAL_CAM_ENTRY) {
+                                               RT_TRACE(rtlpriv, COMP_SEC,
+                                                        DBG_EMERG,
+                                                        "Can not find free hw security cam entry\n");
+                                               return;
+                                       }
+                               } else {
+                                       entry_id = CAM_PAIRWISE_KEY_POSITION;
+                               }
+
                                key_index = PAIRWISE_KEYIDX;
-                               entry_id = CAM_PAIRWISE_KEY_POSITION;
                                is_pairwise = true;
                        }
                }
                if (rtlpriv->sec.key_len[key_index] == 0) {
                        RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
                                 "delete one entry\n");
+                       if (mac->opmode == NL80211_IFTYPE_AP ||
+                           mac->opmode == NL80211_IFTYPE_MESH_POINT)
+                               rtl_cam_del_entry(hw, p_macaddr);
                        rtl_cam_delete_one_entry(hw, p_macaddr, entry_id);
                } else {
                        RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
index 23d640a..826f085 100644 (file)
@@ -106,8 +106,7 @@ static struct rtl_hal_ops rtl8192cu_hal_ops = {
        .update_interrupt_mask = rtl92cu_update_interrupt_mask,
        .get_hw_reg = rtl92cu_get_hw_reg,
        .set_hw_reg = rtl92cu_set_hw_reg,
-       .update_rate_tbl = rtl92cu_update_hal_rate_table,
-       .update_rate_mask = rtl92cu_update_hal_rate_mask,
+       .update_rate_tbl = rtl92cu_update_hal_rate_tbl,
        .fill_tx_desc = rtl92cu_tx_fill_desc,
        .fill_fake_txdesc = rtl92cu_fill_fake_txdesc,
        .fill_tx_cmddesc = rtl92cu_tx_fill_cmddesc,
@@ -137,6 +136,7 @@ static struct rtl_hal_ops rtl8192cu_hal_ops = {
        .phy_lc_calibrate = _rtl92cu_phy_lc_calibrate,
        .phy_set_bw_mode_callback = rtl92cu_phy_set_bw_mode_callback,
        .dm_dynamic_txpower = rtl92cu_dm_dynamic_txpower,
+       .fill_h2c_cmd = rtl92c_fill_h2c_cmd,
 };
 
 static struct rtl_mod_params rtl92cu_mod_params = {
@@ -349,6 +349,7 @@ static struct usb_device_id rtl8192c_usb_ids[] = {
        {RTL_USB_DEVICE(0x07aa, 0x0056, rtl92cu_hal_cfg)}, /*ATKK-Gemtek*/
        {RTL_USB_DEVICE(0x07b8, 0x8178, rtl92cu_hal_cfg)}, /*Funai -Abocom*/
        {RTL_USB_DEVICE(0x0846, 0x9021, rtl92cu_hal_cfg)}, /*Netgear-Sercomm*/
+       {RTL_USB_DEVICE(0x0846, 0xf001, rtl92cu_hal_cfg)}, /*On Netwrks N300MA*/
        {RTL_USB_DEVICE(0x0b05, 0x17ab, rtl92cu_hal_cfg)}, /*ASUS-Edimax*/
        {RTL_USB_DEVICE(0x0bda, 0x8186, rtl92cu_hal_cfg)}, /*Realtek 92CE-VAU*/
        {RTL_USB_DEVICE(0x0df6, 0x0061, rtl92cu_hal_cfg)}, /*Sitecom-Edimax*/
index a1310ab..262e1e4 100644 (file)
@@ -49,5 +49,8 @@ bool rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw,
 u32 rtl92cu_phy_query_rf_reg(struct ieee80211_hw *hw,
                            enum radio_path rfpath, u32 regaddr, u32 bitmask);
 void rtl92cu_phy_set_bw_mode_callback(struct ieee80211_hw *hw);
+void rtl92cu_update_hal_rate_tbl(struct ieee80211_hw *hw,
+                                struct ieee80211_sta *sta,
+                                u8 rssi_level);
 
 #endif
index 76732b0..a3532e0 100644 (file)
@@ -824,6 +824,7 @@ static void rtl_usb_stop(struct ieee80211_hw *hw)
 
        /* should after adapter start and interrupt enable. */
        set_hal_stop(rtlhal);
+       cancel_work_sync(&rtlpriv->works.fill_h2c_cmd);
        /* Enable software */
        SET_USB_STOP(rtlusb);
        rtl_usb_deinit(hw);
@@ -1026,6 +1027,16 @@ static bool rtl_usb_tx_chk_waitq_insert(struct ieee80211_hw *hw,
        return false;
 }
 
+static void rtl_fill_h2c_cmd_work_callback(struct work_struct *work)
+{
+       struct rtl_works *rtlworks =
+           container_of(work, struct rtl_works, fill_h2c_cmd);
+       struct ieee80211_hw *hw = rtlworks->hw;
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+       rtlpriv->cfg->ops->fill_h2c_cmd(hw, H2C_RA_MASK, 5, rtlpriv->rate_mask);
+}
+
 static struct rtl_intf_ops rtl_usb_ops = {
        .adapter_start = rtl_usb_start,
        .adapter_stop = rtl_usb_stop,
@@ -1057,6 +1068,8 @@ int rtl_usb_probe(struct usb_interface *intf,
 
        /* this spin lock must be initialized early */
        spin_lock_init(&rtlpriv->locks.usb_lock);
+       INIT_WORK(&rtlpriv->works.fill_h2c_cmd,
+                 rtl_fill_h2c_cmd_work_callback);
 
        rtlpriv->usb_data_index = 0;
        init_completion(&rtlpriv->firmware_loading_complete);
index 44328ba..cc03e7c 100644 (file)
@@ -1736,6 +1736,8 @@ struct rtl_hal_ops {
        void (*bt_wifi_media_status_notify) (struct ieee80211_hw *hw,
                                             bool mstate);
        void (*bt_coex_off_before_lps) (struct ieee80211_hw *hw);
+       void (*fill_h2c_cmd) (struct ieee80211_hw *hw, u8 element_id,
+                             u32 cmd_len, u8 *p_cmdbuffer);
 };
 
 struct rtl_intf_ops {
@@ -1869,6 +1871,7 @@ struct rtl_works {
        struct delayed_work fwevt_wq;
 
        struct work_struct lps_change_work;
+       struct work_struct fill_h2c_cmd;
 };
 
 struct rtl_debug {
@@ -2048,6 +2051,7 @@ struct rtl_priv {
                };
        };
        bool enter_ps;  /* true when entering PS */
+       u8 rate_mask[5];
 
        /*This must be the last item so
           that it points to the data allocated
index affdb3e..4a0bbb1 100644 (file)
@@ -310,7 +310,7 @@ static void wl12xx_adjust_channels(struct wl1271_cmd_sched_scan_config *cmd,
        memcpy(cmd->channels_2, cmd_channels->channels_2,
               sizeof(cmd->channels_2));
        memcpy(cmd->channels_5, cmd_channels->channels_5,
-              sizeof(cmd->channels_2));
+              sizeof(cmd->channels_5));
        /* channels_4 are not supported, so no need to copy them */
 }
 
index 222d035..9e5484a 100644 (file)
 #define WL127X_IFTYPE_SR_VER   3
 #define WL127X_MAJOR_SR_VER    10
 #define WL127X_SUBTYPE_SR_VER  WLCORE_FW_VER_IGNORE
-#define WL127X_MINOR_SR_VER    115
+#define WL127X_MINOR_SR_VER    133
 /* minimum multi-role FW version for wl127x */
 #define WL127X_IFTYPE_MR_VER   5
 #define WL127X_MAJOR_MR_VER    7
 #define WL127X_SUBTYPE_MR_VER  WLCORE_FW_VER_IGNORE
-#define WL127X_MINOR_MR_VER    115
+#define WL127X_MINOR_MR_VER    42
 
 /* FW chip version for wl128x */
 #define WL128X_CHIP_VER                7
@@ -49,7 +49,7 @@
 #define WL128X_IFTYPE_SR_VER   3
 #define WL128X_MAJOR_SR_VER    10
 #define WL128X_SUBTYPE_SR_VER  WLCORE_FW_VER_IGNORE
-#define WL128X_MINOR_SR_VER    115
+#define WL128X_MINOR_SR_VER    133
 /* minimum multi-role FW version for wl128x */
 #define WL128X_IFTYPE_MR_VER   5
 #define WL128X_MAJOR_MR_VER    7
index 09d9445..2b642f8 100644 (file)
@@ -34,7 +34,7 @@ static void wl18xx_adjust_channels(struct wl18xx_cmd_scan_params *cmd,
        memcpy(cmd->channels_2, cmd_channels->channels_2,
               sizeof(cmd->channels_2));
        memcpy(cmd->channels_5, cmd_channels->channels_5,
-              sizeof(cmd->channels_2));
+              sizeof(cmd->channels_5));
        /* channels_4 are not supported, so no need to copy them */
 }
 
index 4775d4e..74a852e 100644 (file)
@@ -28,7 +28,7 @@ config NFC_WILINK
 
 config NFC_MEI_PHY
        tristate "MEI bus NFC device support"
-       depends on INTEL_MEI_BUS_NFC && NFC_HCI
+       depends on INTEL_MEI && NFC_HCI
        help
          This adds support to use an mei bus nfc device. Select this if you
          will use an HCI NFC driver for an NFC chip connected behind an
index b8f8abc..1201bdb 100644 (file)
@@ -64,6 +64,15 @@ int nfc_mei_phy_enable(void *phy_id)
                 return r;
        }
 
+       r = mei_cl_register_event_cb(phy->device, nfc_mei_event_cb, phy);
+       if (r) {
+               pr_err("MEY_PHY: Event cb registration failed\n");
+               mei_cl_disable_device(phy->device);
+               phy->powered = 0;
+
+               return r;
+       }
+
        phy->powered = 1;
 
        return 0;
index 1ad044d..cdf1bc5 100644 (file)
@@ -43,24 +43,16 @@ static int microread_mei_probe(struct mei_cl_device *device,
                return -ENOMEM;
        }
 
-       r = mei_cl_register_event_cb(device, nfc_mei_event_cb, phy);
-       if (r) {
-               pr_err(MICROREAD_DRIVER_NAME ": event cb registration failed\n");
-               goto err_out;
-       }
-
        r = microread_probe(phy, &mei_phy_ops, LLC_NOP_NAME,
                            MEI_NFC_HEADER_SIZE, 0, MEI_NFC_MAX_HCI_PAYLOAD,
                            &phy->hdev);
-       if (r < 0)
-               goto err_out;
-
-       return 0;
+       if (r < 0) {
+               nfc_mei_phy_free(phy);
 
-err_out:
-       nfc_mei_phy_free(phy);
+               return r;
+       }
 
-       return r;
+       return 0;
 }
 
 static int microread_mei_remove(struct mei_cl_device *device)
@@ -71,8 +63,6 @@ static int microread_mei_remove(struct mei_cl_device *device)
 
        microread_remove(phy->hdev);
 
-       nfc_mei_phy_disable(phy);
-
        nfc_mei_phy_free(phy);
 
        return 0;
index 1eb4884..b5d3d18 100644 (file)
@@ -43,24 +43,16 @@ static int pn544_mei_probe(struct mei_cl_device *device,
                return -ENOMEM;
        }
 
-       r = mei_cl_register_event_cb(device, nfc_mei_event_cb, phy);
-       if (r) {
-               pr_err(PN544_DRIVER_NAME ": event cb registration failed\n");
-               goto err_out;
-       }
-
        r = pn544_hci_probe(phy, &mei_phy_ops, LLC_NOP_NAME,
                            MEI_NFC_HEADER_SIZE, 0, MEI_NFC_MAX_HCI_PAYLOAD,
                            &phy->hdev);
-       if (r < 0)
-               goto err_out;
-
-       return 0;
+       if (r < 0) {
+               nfc_mei_phy_free(phy);
 
-err_out:
-       nfc_mei_phy_free(phy);
+               return r;
+       }
 
-       return r;
+       return 0;
 }
 
 static int pn544_mei_remove(struct mei_cl_device *device)
@@ -71,8 +63,6 @@ static int pn544_mei_remove(struct mei_cl_device *device)
 
        pn544_hci_remove(phy->hdev);
 
-       nfc_mei_phy_disable(phy);
-
        nfc_mei_phy_free(phy);
 
        return 0;
index f802e7c..2dacd19 100644 (file)
@@ -345,7 +345,7 @@ int ntb_read_remote_spad(struct ntb_device *ndev, unsigned int idx, u32 *val)
  */
 void __iomem *ntb_get_mw_vbase(struct ntb_device *ndev, unsigned int mw)
 {
-       if (mw > NTB_NUM_MW)
+       if (mw >= NTB_NUM_MW)
                return NULL;
 
        return ndev->mw[mw].vbase;
@@ -362,7 +362,7 @@ void __iomem *ntb_get_mw_vbase(struct ntb_device *ndev, unsigned int mw)
  */
 resource_size_t ntb_get_mw_size(struct ntb_device *ndev, unsigned int mw)
 {
-       if (mw > NTB_NUM_MW)
+       if (mw >= NTB_NUM_MW)
                return 0;
 
        return ndev->mw[mw].bar_sz;
@@ -380,7 +380,7 @@ resource_size_t ntb_get_mw_size(struct ntb_device *ndev, unsigned int mw)
  */
 void ntb_set_mw_addr(struct ntb_device *ndev, unsigned int mw, u64 addr)
 {
-       if (mw > NTB_NUM_MW)
+       if (mw >= NTB_NUM_MW)
                return;
 
        dev_dbg(&ndev->pdev->dev, "Writing addr %Lx to BAR %d\n", addr,
@@ -1027,8 +1027,8 @@ static int ntb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                ndev->mw[i].vbase =
                    ioremap_wc(pci_resource_start(pdev, MW_TO_BAR(i)),
                               ndev->mw[i].bar_sz);
-               dev_info(&pdev->dev, "MW %d size %d\n", i,
-                        (u32) pci_resource_len(pdev, MW_TO_BAR(i)));
+               dev_info(&pdev->dev, "MW %d size %llu\n", i,
+                        pci_resource_len(pdev, MW_TO_BAR(i)));
                if (!ndev->mw[i].vbase) {
                        dev_warn(&pdev->dev, "Cannot remap BAR %d\n",
                                 MW_TO_BAR(i));
index e0bdfd7..f8d7081 100644 (file)
@@ -58,7 +58,7 @@
 #include <linux/ntb.h>
 #include "ntb_hw.h"
 
-#define NTB_TRANSPORT_VERSION  2
+#define NTB_TRANSPORT_VERSION  3
 
 static unsigned int transport_mtu = 0x401E;
 module_param(transport_mtu, uint, 0644);
@@ -173,10 +173,13 @@ struct ntb_payload_header {
 
 enum {
        VERSION = 0,
-       MW0_SZ,
-       MW1_SZ,
-       NUM_QPS,
        QP_LINKS,
+       NUM_QPS,
+       NUM_MWS,
+       MW0_SZ_HIGH,
+       MW0_SZ_LOW,
+       MW1_SZ_HIGH,
+       MW1_SZ_LOW,
        MAX_SPAD,
 };
 
@@ -297,7 +300,7 @@ int ntb_register_client_dev(char *device_name)
 {
        struct ntb_transport_client_dev *client_dev;
        struct ntb_transport *nt;
-       int rc;
+       int rc, i = 0;
 
        if (list_empty(&ntb_transport_list))
                return -ENODEV;
@@ -315,7 +318,7 @@ int ntb_register_client_dev(char *device_name)
                dev = &client_dev->dev;
 
                /* setup and register client devices */
-               dev_set_name(dev, "%s", device_name);
+               dev_set_name(dev, "%s%d", device_name, i);
                dev->bus = &ntb_bus_type;
                dev->release = ntb_client_release;
                dev->parent = &ntb_query_pdev(nt->ndev)->dev;
@@ -327,6 +330,7 @@ int ntb_register_client_dev(char *device_name)
                }
 
                list_add_tail(&client_dev->entry, &nt->client_devs);
+               i++;
        }
 
        return 0;
@@ -486,12 +490,13 @@ static void ntb_transport_setup_qp_mw(struct ntb_transport *nt,
                             (qp_num / NTB_NUM_MW * rx_size);
        rx_size -= sizeof(struct ntb_rx_info);
 
-       qp->rx_buff = qp->remote_rx_info + sizeof(struct ntb_rx_info);
-       qp->rx_max_frame = min(transport_mtu, rx_size);
+       qp->rx_buff = qp->remote_rx_info + 1;
+       /* Due to housekeeping, there must be atleast 2 buffs */
+       qp->rx_max_frame = min(transport_mtu, rx_size / 2);
        qp->rx_max_entry = rx_size / qp->rx_max_frame;
        qp->rx_index = 0;
 
-       qp->remote_rx_info->entry = qp->rx_max_entry;
+       qp->remote_rx_info->entry = qp->rx_max_entry - 1;
 
        /* setup the hdr offsets with 0's */
        for (i = 0; i < qp->rx_max_entry; i++) {
@@ -502,6 +507,19 @@ static void ntb_transport_setup_qp_mw(struct ntb_transport *nt,
 
        qp->rx_pkts = 0;
        qp->tx_pkts = 0;
+       qp->tx_index = 0;
+}
+
+static void ntb_free_mw(struct ntb_transport *nt, int num_mw)
+{
+       struct ntb_transport_mw *mw = &nt->mw[num_mw];
+       struct pci_dev *pdev = ntb_query_pdev(nt->ndev);
+
+       if (!mw->virt_addr)
+               return;
+
+       dma_free_coherent(&pdev->dev, mw->size, mw->virt_addr, mw->dma_addr);
+       mw->virt_addr = NULL;
 }
 
 static int ntb_set_mw(struct ntb_transport *nt, int num_mw, unsigned int size)
@@ -509,12 +527,20 @@ static int ntb_set_mw(struct ntb_transport *nt, int num_mw, unsigned int size)
        struct ntb_transport_mw *mw = &nt->mw[num_mw];
        struct pci_dev *pdev = ntb_query_pdev(nt->ndev);
 
+       /* No need to re-setup */
+       if (mw->size == ALIGN(size, 4096))
+               return 0;
+
+       if (mw->size != 0)
+               ntb_free_mw(nt, num_mw);
+
        /* Alloc memory for receiving data.  Must be 4k aligned */
        mw->size = ALIGN(size, 4096);
 
        mw->virt_addr = dma_alloc_coherent(&pdev->dev, mw->size, &mw->dma_addr,
                                           GFP_KERNEL);
        if (!mw->virt_addr) {
+               mw->size = 0;
                dev_err(&pdev->dev, "Unable to allocate MW buffer of size %d\n",
                       (int) mw->size);
                return -ENOMEM;
@@ -604,25 +630,31 @@ static void ntb_transport_link_work(struct work_struct *work)
        u32 val;
        int rc, i;
 
-       /* send the local info */
-       rc = ntb_write_remote_spad(ndev, VERSION, NTB_TRANSPORT_VERSION);
-       if (rc) {
-               dev_err(&pdev->dev, "Error writing %x to remote spad %d\n",
-                       0, VERSION);
-               goto out;
-       }
+       /* send the local info, in the opposite order of the way we read it */
+       for (i = 0; i < NTB_NUM_MW; i++) {
+               rc = ntb_write_remote_spad(ndev, MW0_SZ_HIGH + (i * 2),
+                                          ntb_get_mw_size(ndev, i) >> 32);
+               if (rc) {
+                       dev_err(&pdev->dev, "Error writing %u to remote spad %d\n",
+                               (u32)(ntb_get_mw_size(ndev, i) >> 32),
+                               MW0_SZ_HIGH + (i * 2));
+                       goto out;
+               }
 
-       rc = ntb_write_remote_spad(ndev, MW0_SZ, ntb_get_mw_size(ndev, 0));
-       if (rc) {
-               dev_err(&pdev->dev, "Error writing %x to remote spad %d\n",
-                       (u32) ntb_get_mw_size(ndev, 0), MW0_SZ);
-               goto out;
+               rc = ntb_write_remote_spad(ndev, MW0_SZ_LOW + (i * 2),
+                                          (u32) ntb_get_mw_size(ndev, i));
+               if (rc) {
+                       dev_err(&pdev->dev, "Error writing %u to remote spad %d\n",
+                               (u32) ntb_get_mw_size(ndev, i),
+                               MW0_SZ_LOW + (i * 2));
+                       goto out;
+               }
        }
 
-       rc = ntb_write_remote_spad(ndev, MW1_SZ, ntb_get_mw_size(ndev, 1));
+       rc = ntb_write_remote_spad(ndev, NUM_MWS, NTB_NUM_MW);
        if (rc) {
                dev_err(&pdev->dev, "Error writing %x to remote spad %d\n",
-                       (u32) ntb_get_mw_size(ndev, 1), MW1_SZ);
+                       NTB_NUM_MW, NUM_MWS);
                goto out;
        }
 
@@ -633,16 +665,10 @@ static void ntb_transport_link_work(struct work_struct *work)
                goto out;
        }
 
-       rc = ntb_read_local_spad(nt->ndev, QP_LINKS, &val);
-       if (rc) {
-               dev_err(&pdev->dev, "Error reading spad %d\n", QP_LINKS);
-               goto out;
-       }
-
-       rc = ntb_write_remote_spad(ndev, QP_LINKS, val);
+       rc = ntb_write_remote_spad(ndev, VERSION, NTB_TRANSPORT_VERSION);
        if (rc) {
                dev_err(&pdev->dev, "Error writing %x to remote spad %d\n",
-                       val, QP_LINKS);
+                       NTB_TRANSPORT_VERSION, VERSION);
                goto out;
        }
 
@@ -667,33 +693,43 @@ static void ntb_transport_link_work(struct work_struct *work)
                goto out;
        dev_dbg(&pdev->dev, "Remote max number of qps = %d\n", val);
 
-       rc = ntb_read_remote_spad(ndev, MW0_SZ, &val);
+       rc = ntb_read_remote_spad(ndev, NUM_MWS, &val);
        if (rc) {
-               dev_err(&pdev->dev, "Error reading remote spad %d\n", MW0_SZ);
+               dev_err(&pdev->dev, "Error reading remote spad %d\n", NUM_MWS);
                goto out;
        }
 
-       if (!val)
+       if (val != NTB_NUM_MW)
                goto out;
-       dev_dbg(&pdev->dev, "Remote MW0 size = %d\n", val);
+       dev_dbg(&pdev->dev, "Remote number of mws = %d\n", val);
 
-       rc = ntb_set_mw(nt, 0, val);
-       if (rc)
-               goto out;
+       for (i = 0; i < NTB_NUM_MW; i++) {
+               u64 val64;
 
-       rc = ntb_read_remote_spad(ndev, MW1_SZ, &val);
-       if (rc) {
-               dev_err(&pdev->dev, "Error reading remote spad %d\n", MW1_SZ);
-               goto out;
-       }
+               rc = ntb_read_remote_spad(ndev, MW0_SZ_HIGH + (i * 2), &val);
+               if (rc) {
+                       dev_err(&pdev->dev, "Error reading remote spad %d\n",
+                               MW0_SZ_HIGH + (i * 2));
+                       goto out1;
+               }
 
-       if (!val)
-               goto out;
-       dev_dbg(&pdev->dev, "Remote MW1 size = %d\n", val);
+               val64 = (u64) val << 32;
 
-       rc = ntb_set_mw(nt, 1, val);
-       if (rc)
-               goto out;
+               rc = ntb_read_remote_spad(ndev, MW0_SZ_LOW + (i * 2), &val);
+               if (rc) {
+                       dev_err(&pdev->dev, "Error reading remote spad %d\n",
+                               MW0_SZ_LOW + (i * 2));
+                       goto out1;
+               }
+
+               val64 |= val;
+
+               dev_dbg(&pdev->dev, "Remote MW%d size = %llu\n", i, val64);
+
+               rc = ntb_set_mw(nt, i, val64);
+               if (rc)
+                       goto out1;
+       }
 
        nt->transport_link = NTB_LINK_UP;
 
@@ -708,6 +744,9 @@ static void ntb_transport_link_work(struct work_struct *work)
 
        return;
 
+out1:
+       for (i = 0; i < NTB_NUM_MW; i++)
+               ntb_free_mw(nt, i);
 out:
        if (ntb_hw_link_status(ndev))
                schedule_delayed_work(&nt->link_work,
@@ -780,10 +819,10 @@ static void ntb_transport_init_queue(struct ntb_transport *nt,
                      (qp_num / NTB_NUM_MW * tx_size);
        tx_size -= sizeof(struct ntb_rx_info);
 
-       qp->tx_mw = qp->rx_info + sizeof(struct ntb_rx_info);
-       qp->tx_max_frame = min(transport_mtu, tx_size);
+       qp->tx_mw = qp->rx_info + 1;
+       /* Due to housekeeping, there must be atleast 2 buffs */
+       qp->tx_max_frame = min(transport_mtu, tx_size / 2);
        qp->tx_max_entry = tx_size / qp->tx_max_frame;
-       qp->tx_index = 0;
 
        if (nt->debugfs_dir) {
                char debugfs_name[4];
@@ -897,10 +936,7 @@ void ntb_transport_free(void *transport)
        pdev = ntb_query_pdev(nt->ndev);
 
        for (i = 0; i < NTB_NUM_MW; i++)
-               if (nt->mw[i].virt_addr)
-                       dma_free_coherent(&pdev->dev, nt->mw[i].size,
-                                         nt->mw[i].virt_addr,
-                                         nt->mw[i].dma_addr);
+               ntb_free_mw(nt, i);
 
        kfree(nt->qps);
        ntb_unregister_transport(nt->ndev);
@@ -999,11 +1035,16 @@ out:
 static void ntb_transport_rx(unsigned long data)
 {
        struct ntb_transport_qp *qp = (struct ntb_transport_qp *)data;
-       int rc;
+       int rc, i;
 
-       do {
+       /* Limit the number of packets processed in a single interrupt to
+        * provide fairness to others
+        */
+       for (i = 0; i < qp->rx_max_entry; i++) {
                rc = ntb_process_rxc(qp);
-       } while (!rc);
+               if (rc)
+                       break;
+       }
 }
 
 static void ntb_transport_rxc_db(void *data, int db_num)
@@ -1210,12 +1251,14 @@ EXPORT_SYMBOL_GPL(ntb_transport_create_queue);
  */
 void ntb_transport_free_queue(struct ntb_transport_qp *qp)
 {
-       struct pci_dev *pdev = ntb_query_pdev(qp->ndev);
+       struct pci_dev *pdev;
        struct ntb_queue_entry *entry;
 
        if (!qp)
                return;
 
+       pdev = ntb_query_pdev(qp->ndev);
+
        cancel_delayed_work_sync(&qp->link_work);
 
        ntb_unregister_db_callback(qp->ndev, qp->qp_num);
@@ -1371,12 +1414,13 @@ EXPORT_SYMBOL_GPL(ntb_transport_link_up);
  */
 void ntb_transport_link_down(struct ntb_transport_qp *qp)
 {
-       struct pci_dev *pdev = ntb_query_pdev(qp->ndev);
+       struct pci_dev *pdev;
        int rc, val;
 
        if (!qp)
                return;
 
+       pdev = ntb_query_pdev(qp->ndev);
        qp->client_ready = NTB_LINK_DOWN;
 
        rc = ntb_read_local_spad(qp->ndev, QP_LINKS, &val);
@@ -1408,6 +1452,9 @@ EXPORT_SYMBOL_GPL(ntb_transport_link_down);
  */
 bool ntb_transport_link_query(struct ntb_transport_qp *qp)
 {
+       if (!qp)
+               return false;
+
        return qp->qp_link == NTB_LINK_UP;
 }
 EXPORT_SYMBOL_GPL(ntb_transport_link_query);
@@ -1422,6 +1469,9 @@ EXPORT_SYMBOL_GPL(ntb_transport_link_query);
  */
 unsigned char ntb_transport_qp_num(struct ntb_transport_qp *qp)
 {
+       if (!qp)
+               return 0;
+
        return qp->qp_num;
 }
 EXPORT_SYMBOL_GPL(ntb_transport_qp_num);
@@ -1436,6 +1486,9 @@ EXPORT_SYMBOL_GPL(ntb_transport_qp_num);
  */
 unsigned int ntb_transport_max_size(struct ntb_transport_qp *qp)
 {
+       if (!qp)
+               return 0;
+
        return qp->tx_max_frame - sizeof(struct ntb_payload_header);
 }
 EXPORT_SYMBOL_GPL(ntb_transport_max_size);
index c76d16c..f53b992 100644 (file)
@@ -1208,11 +1208,11 @@ static int __of_parse_phandle_with_args(const struct device_node *np,
                                out_args->args_count = count;
                                for (i = 0; i < count; i++)
                                        out_args->args[i] = be32_to_cpup(list++);
+                       } else {
+                               of_node_put(node);
                        }
 
                        /* Found it! return success */
-                       if (node)
-                               of_node_put(node);
                        return 0;
                }
 
index 2ef7103..1f05913 100644 (file)
@@ -668,7 +668,7 @@ lba_fixup_bus(struct pci_bus *bus)
                        BUG();
                }
 
-               if (ldev->hba.elmmio_space.start) {
+               if (ldev->hba.elmmio_space.flags) {
                        err = request_resource(&iomem_resource,
                                        &(ldev->hba.elmmio_space));
                        if (err < 0) {
@@ -993,7 +993,7 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev)
 
                case PAT_LMMIO:
                        /* used to fix up pre-initialized MEM BARs */
-                       if (!lba_dev->hba.lmmio_space.start) {
+                       if (!lba_dev->hba.lmmio_space.flags) {
                                sprintf(lba_dev->hba.lmmio_name,
                                                "PCI%02x LMMIO",
                                                (int)lba_dev->hba.bus_num.start);
@@ -1001,7 +1001,7 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev)
                                        io->start;
                                r = &lba_dev->hba.lmmio_space;
                                r->name = lba_dev->hba.lmmio_name;
-                       } else if (!lba_dev->hba.elmmio_space.start) {
+                       } else if (!lba_dev->hba.elmmio_space.flags) {
                                sprintf(lba_dev->hba.elmmio_name,
                                                "PCI%02x ELMMIO",
                                                (int)lba_dev->hba.bus_num.start);
@@ -1096,6 +1096,7 @@ lba_legacy_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev)
        r->name = "LBA PCI Busses";
        r->start = lba_num & 0xff;
        r->end = (lba_num>>8) & 0xff;
+       r->flags = IORESOURCE_BUS;
 
        /* Set up local PCI Bus resources - we don't need them for
        ** Legacy boxes but it's nice to see in /proc/iomem.
@@ -1494,7 +1495,7 @@ lba_driver_probe(struct parisc_device *dev)
 
        pci_add_resource_offset(&resources, &lba_dev->hba.io_space,
                                HBA_PORT_BASE(lba_dev->hba.hba_num));
-       if (lba_dev->hba.elmmio_space.start)
+       if (lba_dev->hba.elmmio_space.flags)
                pci_add_resource_offset(&resources, &lba_dev->hba.elmmio_space,
                                        lba_dev->hba.lmmio_space_offset);
        if (lba_dev->hba.lmmio_space.flags)
index ac6e8e7..a042d06 100644 (file)
@@ -494,15 +494,4 @@ static struct pci_driver superio_driver = {
        .probe =        superio_probe,
 };
 
-static int __init superio_modinit(void)
-{
-       return pci_register_driver(&superio_driver);
-}
-
-static void __exit superio_exit(void)
-{
-       pci_unregister_driver(&superio_driver);
-}
-
-module_init(superio_modinit);
-module_exit(superio_exit);
+module_pci_driver(superio_driver);
index 24e12d4..a505760 100644 (file)
@@ -71,7 +71,7 @@ config PARPORT_PC_FIFO
 
 config PARPORT_PC_SUPERIO
        bool "SuperIO chipset support"
-       depends on PARPORT_PC
+       depends on PARPORT_PC && !PARISC
        help
          Saying Y here enables some probes for Super-IO chipsets in order to
          find out things like base addresses, IRQ lines and DMA channels.  It
index a5251cb..6e3a60c 100644 (file)
@@ -234,7 +234,7 @@ static int parport_PS2_supported(struct parport *pb)
 
 struct parport *parport_gsc_probe_port(unsigned long base,
                                       unsigned long base_hi, int irq,
-                                      int dma, struct pci_dev *dev)
+                                      int dma, struct parisc_device *padev)
 {
        struct parport_gsc_private *priv;
        struct parport_operations *ops;
@@ -258,7 +258,6 @@ struct parport *parport_gsc_probe_port(unsigned long base,
        priv->ctr_writable = 0xff;
        priv->dma_buf = 0;
        priv->dma_handle = 0;
-       priv->dev = dev;
        p->base = base;
        p->base_hi = base_hi;
        p->irq = irq;
@@ -282,6 +281,7 @@ struct parport *parport_gsc_probe_port(unsigned long base,
                return NULL;
        }
 
+       p->dev = &padev->dev;
        p->base_hi = base_hi;
        p->modes = tmp.modes;
        p->size = (p->modes & PARPORT_MODE_EPP)?8:3;
@@ -373,7 +373,7 @@ static int parport_init_chip(struct parisc_device *dev)
        }
        
        p = parport_gsc_probe_port(port, 0, dev->irq,
-                       /* PARPORT_IRQ_NONE */ PARPORT_DMA_NONE, NULL);
+                       /* PARPORT_IRQ_NONE */ PARPORT_DMA_NONE, dev);
        if (p)
                parport_count++;
        dev_set_drvdata(&dev->dev, p);
index fc9c37c..8122147 100644 (file)
@@ -217,6 +217,6 @@ extern void parport_gsc_dec_use_count(void);
 extern struct parport *parport_gsc_probe_port(unsigned long base,
                                                unsigned long base_hi,
                                                int irq, int dma,
-                                               struct pci_dev *dev);
+                                               struct parisc_device *padev);
 
 #endif /* __DRIVERS_PARPORT_PARPORT_GSC_H */
index 96fed19..716aa93 100644 (file)
@@ -950,6 +950,20 @@ check_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
        return AE_OK ;
 }
 
+void acpiphp_check_host_bridge(acpi_handle handle)
+{
+       struct acpiphp_bridge *bridge;
+
+       bridge = acpiphp_handle_to_bridge(handle);
+       if (bridge) {
+               acpiphp_check_bridge(bridge);
+               put_bridge(bridge);
+       }
+
+       acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
+               ACPI_UINT32_MAX, check_sub_bridges, NULL, NULL, NULL);
+}
+
 static void _handle_hotplug_event_bridge(struct work_struct *work)
 {
        struct acpiphp_bridge *bridge;
index 8ec8b4f..0f4554e 100644 (file)
@@ -580,6 +580,7 @@ struct aer_recover_entry
        u8      devfn;
        u16     domain;
        int     severity;
+       struct aer_capability_regs *regs;
 };
 
 static DEFINE_KFIFO(aer_recover_ring, struct aer_recover_entry,
@@ -593,7 +594,7 @@ static DEFINE_SPINLOCK(aer_recover_ring_lock);
 static DECLARE_WORK(aer_recover_work, aer_recover_work_func);
 
 void aer_recover_queue(int domain, unsigned int bus, unsigned int devfn,
-                      int severity)
+                      int severity, struct aer_capability_regs *aer_regs)
 {
        unsigned long flags;
        struct aer_recover_entry entry = {
@@ -601,6 +602,7 @@ void aer_recover_queue(int domain, unsigned int bus, unsigned int devfn,
                .devfn          = devfn,
                .domain         = domain,
                .severity       = severity,
+               .regs           = aer_regs,
        };
 
        spin_lock_irqsave(&aer_recover_ring_lock, flags);
@@ -627,6 +629,7 @@ static void aer_recover_work_func(struct work_struct *work)
                               PCI_SLOT(entry.devfn), PCI_FUNC(entry.devfn));
                        continue;
                }
+               cper_print_aer(pdev, entry.severity, entry.regs);
                do_recovery(pdev, entry.severity);
                pci_dev_put(pdev);
        }
index 5ab1425..2c7c9f5 100644 (file)
@@ -220,7 +220,7 @@ int cper_severity_to_aer(int cper_severity)
 }
 EXPORT_SYMBOL_GPL(cper_severity_to_aer);
 
-void cper_print_aer(const char *prefix, struct pci_dev *dev, int cper_severity,
+void cper_print_aer(struct pci_dev *dev, int cper_severity,
                    struct aer_capability_regs *aer)
 {
        int aer_severity, layer, agent, status_strs_size, tlp_header_valid = 0;
@@ -244,7 +244,7 @@ void cper_print_aer(const char *prefix, struct pci_dev *dev, int cper_severity,
        agent = AER_GET_AGENT(aer_severity, status);
        dev_err(&dev->dev, "aer_status: 0x%08x, aer_mask: 0x%08x\n",
               status, mask);
-       cper_print_bits(prefix, status, status_strs, status_strs_size);
+       cper_print_bits("", status, status_strs, status_strs_size);
        dev_err(&dev->dev, "aer_layer=%s, aer_agent=%s\n",
               aer_error_layer[layer], aer_agent_string[agent]);
        if (aer_severity != AER_CORRECTABLE)
index a3a851e..18c0d8d 100644 (file)
@@ -68,12 +68,6 @@ MODULE_LICENSE("Dual MPL/GPL");
 
 #if !defined(CONFIG_PCMCIA_SLOT_A) && !defined(CONFIG_PCMCIA_SLOT_B)
 
-/* The RPX series use SLOT_B */
-#if defined(CONFIG_RPXCLASSIC) || defined(CONFIG_RPXLITE)
-#define CONFIG_PCMCIA_SLOT_B
-#define CONFIG_BD_IS_MHZ
-#endif
-
 /* The ADS board use SLOT_A */
 #ifdef CONFIG_ADS
 #define CONFIG_PCMCIA_SLOT_A
@@ -253,81 +247,6 @@ static irqreturn_t m8xx_interrupt(int irq, void *dev);
 
 #define PCMCIA_BMT_LIMIT (15*4)        /* Bus Monitor Timeout value */
 
-/* ------------------------------------------------------------------------- */
-/* board specific stuff:                                                     */
-/* voltage_set(), hardware_enable() and hardware_disable()                   */
-/* ------------------------------------------------------------------------- */
-/* RPX Boards from Embedded Planet                                           */
-
-#if defined(CONFIG_RPXCLASSIC) || defined(CONFIG_RPXLITE)
-
-/* The RPX boards seems to have it's bus monitor timeout set to 6*8 clocks.
- * SYPCR is write once only, therefore must the slowest memory be faster
- * than the bus monitor or we will get a machine check due to the bus timeout.
- */
-
-#define PCMCIA_BOARD_MSG "RPX CLASSIC or RPX LITE"
-
-#undef PCMCIA_BMT_LIMIT
-#define PCMCIA_BMT_LIMIT (6*8)
-
-static int voltage_set(int slot, int vcc, int vpp)
-{
-       u32 reg = 0;
-
-       switch (vcc) {
-       case 0:
-               break;
-       case 33:
-               reg |= BCSR1_PCVCTL4;
-               break;
-       case 50:
-               reg |= BCSR1_PCVCTL5;
-               break;
-       default:
-               return 1;
-       }
-
-       switch (vpp) {
-       case 0:
-               break;
-       case 33:
-       case 50:
-               if (vcc == vpp)
-                       reg |= BCSR1_PCVCTL6;
-               else
-                       return 1;
-               break;
-       case 120:
-               reg |= BCSR1_PCVCTL7;
-       default:
-               return 1;
-       }
-
-       if (!((vcc == 50) || (vcc == 0)))
-               return 1;
-
-       /* first, turn off all power */
-
-       out_be32(((u32 *) RPX_CSR_ADDR),
-                in_be32(((u32 *) RPX_CSR_ADDR)) & ~(BCSR1_PCVCTL4 |
-                                                    BCSR1_PCVCTL5 |
-                                                    BCSR1_PCVCTL6 |
-                                                    BCSR1_PCVCTL7));
-
-       /* enable new powersettings */
-
-       out_be32(((u32 *) RPX_CSR_ADDR), in_be32(((u32 *) RPX_CSR_ADDR)) | reg);
-
-       return 0;
-}
-
-#define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V
-#define hardware_enable(_slot_)        /* No hardware to enable */
-#define hardware_disable(_slot_)       /* No hardware to disable */
-
-#endif                         /* CONFIG_RPXCLASSIC */
-
 /* FADS Boards from Motorola                                               */
 
 #if defined(CONFIG_FADS)
@@ -419,65 +338,6 @@ static inline int voltage_set(int slot, int vcc, int vpp)
 
 #endif
 
-/* ------------------------------------------------------------------------- */
-/* Motorola MBX860                                                           */
-
-#if defined(CONFIG_MBX)
-
-#define PCMCIA_BOARD_MSG "MBX"
-
-static int voltage_set(int slot, int vcc, int vpp)
-{
-       u8 reg = 0;
-
-       switch (vcc) {
-       case 0:
-               break;
-       case 33:
-               reg |= CSR2_VCC_33;
-               break;
-       case 50:
-               reg |= CSR2_VCC_50;
-               break;
-       default:
-               return 1;
-       }
-
-       switch (vpp) {
-       case 0:
-               break;
-       case 33:
-       case 50:
-               if (vcc == vpp)
-                       reg |= CSR2_VPP_VCC;
-               else
-                       return 1;
-               break;
-       case 120:
-               if ((vcc == 33) || (vcc == 50))
-                       reg |= CSR2_VPP_12;
-               else
-                       return 1;
-       default:
-               return 1;
-       }
-
-       /* first, turn off all power */
-       out_8((u8 *) MBX_CSR2_ADDR,
-             in_8((u8 *) MBX_CSR2_ADDR) & ~(CSR2_VCC_MASK | CSR2_VPP_MASK));
-
-       /* enable new powersettings */
-       out_8((u8 *) MBX_CSR2_ADDR, in_8((u8 *) MBX_CSR2_ADDR) | reg);
-
-       return 0;
-}
-
-#define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V
-#define hardware_enable(_slot_)        /* No hardware to enable */
-#define hardware_disable(_slot_)       /* No hardware to disable */
-
-#endif                         /* CONFIG_MBX */
-
 #if defined(CONFIG_PRxK)
 #include <asm/cpld.h>
 extern volatile fpga_pc_regs *fpga_pc;
index c67c37e..694c3ac 100644 (file)
@@ -610,7 +610,7 @@ static int pinconf_dbg_config_print(struct seq_file *s, void *d)
        bool found = false;
        unsigned long config;
 
-       mutex_lock(&pctldev->mutex);
+       mutex_lock(&pinctrl_maps_mutex);
 
        /* Parse the pinctrl map and look for the elected pin/state */
        for_each_maps(maps_node, i, map) {
@@ -659,7 +659,7 @@ static int pinconf_dbg_config_print(struct seq_file *s, void *d)
                confops->pin_config_config_dbg_show(pctldev, s, config);
 
 exit:
-       mutex_unlock(&pctldev->mutex);
+       mutex_unlock(&pinctrl_maps_mutex);
 
        return 0;
 }
index aa17f75..6d45327 100644 (file)
@@ -851,23 +851,12 @@ static int abx500_gpio_probe(struct platform_device *pdev)
 
        if (abx500_pdata)
                pdata = abx500_pdata->gpio;
-       if (!pdata) {
-               if (np) {
-                       const struct of_device_id *match;
 
-                       match = of_match_device(abx500_gpio_match, &pdev->dev);
-                       if (!match)
-                               return -ENODEV;
-                       id = (unsigned long)match->data;
-               } else {
-                       dev_err(&pdev->dev, "gpio dt and platform data missing\n");
-                       return -ENODEV;
-               }
+       if (!(pdata || np)) {
+               dev_err(&pdev->dev, "gpio dt and platform data missing\n");
+               return -ENODEV;
        }
 
-       if (platid)
-               id = platid->driver_data;
-
        pct = devm_kzalloc(&pdev->dev, sizeof(struct abx500_pinctrl),
                                   GFP_KERNEL);
        if (pct == NULL) {
@@ -882,6 +871,16 @@ static int abx500_gpio_probe(struct platform_device *pdev)
        pct->chip.dev = &pdev->dev;
        pct->chip.base = (np) ? -1 : pdata->gpio_base;
 
+       if (platid)
+               id = platid->driver_data;
+       else if (np) {
+               const struct of_device_id *match;
+
+               match = of_match_device(abx500_gpio_match, &pdev->dev);
+               if (match)
+                       id = (unsigned long)match->data;
+       }
+
        /* initialize the lock */
        mutex_init(&pct->lock);
 
@@ -900,8 +899,7 @@ static int abx500_gpio_probe(struct platform_device *pdev)
                abx500_pinctrl_ab8505_init(&pct->soc);
                break;
        default:
-               dev_err(&pdev->dev, "Unsupported pinctrl sub driver (%d)\n",
-                               (int) platid->driver_data);
+               dev_err(&pdev->dev, "Unsupported pinctrl sub driver (%d)\n", id);
                mutex_destroy(&pct->lock);
                return -EINVAL;
        }
index edde3ac..d6b4174 100644 (file)
@@ -713,11 +713,6 @@ static int __init u300_gpio_probe(struct platform_device *pdev)
        gpio->dev = &pdev->dev;
 
        memres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!memres) {
-               dev_err(gpio->dev, "could not get GPIO memory resource\n");
-               return -ENODEV;
-       }
-
        gpio->base = devm_ioremap_resource(&pdev->dev, memres);
        if (IS_ERR(gpio->base))
                return PTR_ERR(gpio->base);
@@ -835,7 +830,8 @@ static int __init u300_gpio_probe(struct platform_device *pdev)
        return 0;
 
 err_no_range:
-       err = gpiochip_remove(&gpio->chip);
+       if (gpiochip_remove(&gpio->chip))
+               dev_err(&pdev->dev, "failed to remove gpio chip\n");
 err_no_chip:
 err_no_domain:
 err_no_port:
index ac74281..2d76f66 100644 (file)
@@ -196,6 +196,12 @@ static irqreturn_t exynos_eint_gpio_irq(int irq, void *data)
        return IRQ_HANDLED;
 }
 
+struct exynos_eint_gpio_save {
+       u32 eint_con;
+       u32 eint_fltcon0;
+       u32 eint_fltcon1;
+};
+
 /*
  * exynos_eint_gpio_init() - setup handling of external gpio interrupts.
  * @d: driver data of samsung pinctrl driver.
@@ -204,8 +210,8 @@ static int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d)
 {
        struct samsung_pin_bank *bank;
        struct device *dev = d->dev;
-       unsigned int ret;
-       unsigned int i;
+       int ret;
+       int i;
 
        if (!d->irq) {
                dev_err(dev, "irq number not available\n");
@@ -227,11 +233,29 @@ static int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d)
                                bank->nr_pins, &exynos_gpio_irqd_ops, bank);
                if (!bank->irq_domain) {
                        dev_err(dev, "gpio irq domain add failed\n");
-                       return -ENXIO;
+                       ret = -ENXIO;
+                       goto err_domains;
+               }
+
+               bank->soc_priv = devm_kzalloc(d->dev,
+                       sizeof(struct exynos_eint_gpio_save), GFP_KERNEL);
+               if (!bank->soc_priv) {
+                       irq_domain_remove(bank->irq_domain);
+                       ret = -ENOMEM;
+                       goto err_domains;
                }
        }
 
        return 0;
+
+err_domains:
+       for (--i, --bank; i >= 0; --i, --bank) {
+               if (bank->eint_type != EINT_TYPE_GPIO)
+                       continue;
+               irq_domain_remove(bank->irq_domain);
+       }
+
+       return ret;
 }
 
 static void exynos_wkup_irq_unmask(struct irq_data *irqd)
@@ -326,6 +350,28 @@ static int exynos_wkup_irq_set_type(struct irq_data *irqd, unsigned int type)
        return 0;
 }
 
+static u32 exynos_eint_wake_mask = 0xffffffff;
+
+u32 exynos_get_eint_wake_mask(void)
+{
+       return exynos_eint_wake_mask;
+}
+
+static int exynos_wkup_irq_set_wake(struct irq_data *irqd, unsigned int on)
+{
+       struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
+       unsigned long bit = 1UL << (2 * bank->eint_offset + irqd->hwirq);
+
+       pr_info("wake %s for irq %d\n", on ? "enabled" : "disabled", irqd->irq);
+
+       if (!on)
+               exynos_eint_wake_mask |= bit;
+       else
+               exynos_eint_wake_mask &= ~bit;
+
+       return 0;
+}
+
 /*
  * irq_chip for wakeup interrupts
  */
@@ -335,6 +381,7 @@ static struct irq_chip exynos_wkup_irq_chip = {
        .irq_mask       = exynos_wkup_irq_mask,
        .irq_ack        = exynos_wkup_irq_ack,
        .irq_set_type   = exynos_wkup_irq_set_type,
+       .irq_set_wake   = exynos_wkup_irq_set_wake,
 };
 
 /* interrupt handler for wakeup interrupts 0..15 */
@@ -505,6 +552,72 @@ static int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)
        return 0;
 }
 
+static void exynos_pinctrl_suspend_bank(
+                               struct samsung_pinctrl_drv_data *drvdata,
+                               struct samsung_pin_bank *bank)
+{
+       struct exynos_eint_gpio_save *save = bank->soc_priv;
+       void __iomem *regs = drvdata->virt_base;
+
+       save->eint_con = readl(regs + EXYNOS_GPIO_ECON_OFFSET
+                                               + bank->eint_offset);
+       save->eint_fltcon0 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
+                                               + 2 * bank->eint_offset);
+       save->eint_fltcon1 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
+                                               + 2 * bank->eint_offset + 4);
+
+       pr_debug("%s: save     con %#010x\n", bank->name, save->eint_con);
+       pr_debug("%s: save fltcon0 %#010x\n", bank->name, save->eint_fltcon0);
+       pr_debug("%s: save fltcon1 %#010x\n", bank->name, save->eint_fltcon1);
+}
+
+static void exynos_pinctrl_suspend(struct samsung_pinctrl_drv_data *drvdata)
+{
+       struct samsung_pin_ctrl *ctrl = drvdata->ctrl;
+       struct samsung_pin_bank *bank = ctrl->pin_banks;
+       int i;
+
+       for (i = 0; i < ctrl->nr_banks; ++i, ++bank)
+               if (bank->eint_type == EINT_TYPE_GPIO)
+                       exynos_pinctrl_suspend_bank(drvdata, bank);
+}
+
+static void exynos_pinctrl_resume_bank(
+                               struct samsung_pinctrl_drv_data *drvdata,
+                               struct samsung_pin_bank *bank)
+{
+       struct exynos_eint_gpio_save *save = bank->soc_priv;
+       void __iomem *regs = drvdata->virt_base;
+
+       pr_debug("%s:     con %#010x => %#010x\n", bank->name,
+                       readl(regs + EXYNOS_GPIO_ECON_OFFSET
+                       + bank->eint_offset), save->eint_con);
+       pr_debug("%s: fltcon0 %#010x => %#010x\n", bank->name,
+                       readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
+                       + 2 * bank->eint_offset), save->eint_fltcon0);
+       pr_debug("%s: fltcon1 %#010x => %#010x\n", bank->name,
+                       readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
+                       + 2 * bank->eint_offset + 4), save->eint_fltcon1);
+
+       writel(save->eint_con, regs + EXYNOS_GPIO_ECON_OFFSET
+                                               + bank->eint_offset);
+       writel(save->eint_fltcon0, regs + EXYNOS_GPIO_EFLTCON_OFFSET
+                                               + 2 * bank->eint_offset);
+       writel(save->eint_fltcon1, regs + EXYNOS_GPIO_EFLTCON_OFFSET
+                                               + 2 * bank->eint_offset + 4);
+}
+
+static void exynos_pinctrl_resume(struct samsung_pinctrl_drv_data *drvdata)
+{
+       struct samsung_pin_ctrl *ctrl = drvdata->ctrl;
+       struct samsung_pin_bank *bank = ctrl->pin_banks;
+       int i;
+
+       for (i = 0; i < ctrl->nr_banks; ++i, ++bank)
+               if (bank->eint_type == EINT_TYPE_GPIO)
+                       exynos_pinctrl_resume_bank(drvdata, bank);
+}
+
 /* pin banks of exynos4210 pin-controller 0 */
 static struct samsung_pin_bank exynos4210_pin_banks0[] = {
        EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0", 0x00),
@@ -568,6 +681,8 @@ struct samsung_pin_ctrl exynos4210_pin_ctrl[] = {
                .geint_pend     = EXYNOS_GPIO_EPEND_OFFSET,
                .svc            = EXYNOS_SVC_OFFSET,
                .eint_gpio_init = exynos_eint_gpio_init,
+               .suspend        = exynos_pinctrl_suspend,
+               .resume         = exynos_pinctrl_resume,
                .label          = "exynos4210-gpio-ctrl0",
        }, {
                /* pin-controller instance 1 data */
@@ -582,6 +697,8 @@ struct samsung_pin_ctrl exynos4210_pin_ctrl[] = {
                .svc            = EXYNOS_SVC_OFFSET,
                .eint_gpio_init = exynos_eint_gpio_init,
                .eint_wkup_init = exynos_eint_wkup_init,
+               .suspend        = exynos_pinctrl_suspend,
+               .resume         = exynos_pinctrl_resume,
                .label          = "exynos4210-gpio-ctrl1",
        }, {
                /* pin-controller instance 2 data */
@@ -663,6 +780,8 @@ struct samsung_pin_ctrl exynos4x12_pin_ctrl[] = {
                .geint_pend     = EXYNOS_GPIO_EPEND_OFFSET,
                .svc            = EXYNOS_SVC_OFFSET,
                .eint_gpio_init = exynos_eint_gpio_init,
+               .suspend        = exynos_pinctrl_suspend,
+               .resume         = exynos_pinctrl_resume,
                .label          = "exynos4x12-gpio-ctrl0",
        }, {
                /* pin-controller instance 1 data */
@@ -677,6 +796,8 @@ struct samsung_pin_ctrl exynos4x12_pin_ctrl[] = {
                .svc            = EXYNOS_SVC_OFFSET,
                .eint_gpio_init = exynos_eint_gpio_init,
                .eint_wkup_init = exynos_eint_wkup_init,
+               .suspend        = exynos_pinctrl_suspend,
+               .resume         = exynos_pinctrl_resume,
                .label          = "exynos4x12-gpio-ctrl1",
        }, {
                /* pin-controller instance 2 data */
@@ -687,6 +808,8 @@ struct samsung_pin_ctrl exynos4x12_pin_ctrl[] = {
                .geint_pend     = EXYNOS_GPIO_EPEND_OFFSET,
                .svc            = EXYNOS_SVC_OFFSET,
                .eint_gpio_init = exynos_eint_gpio_init,
+               .suspend        = exynos_pinctrl_suspend,
+               .resume         = exynos_pinctrl_resume,
                .label          = "exynos4x12-gpio-ctrl2",
        }, {
                /* pin-controller instance 3 data */
@@ -697,6 +820,8 @@ struct samsung_pin_ctrl exynos4x12_pin_ctrl[] = {
                .geint_pend     = EXYNOS_GPIO_EPEND_OFFSET,
                .svc            = EXYNOS_SVC_OFFSET,
                .eint_gpio_init = exynos_eint_gpio_init,
+               .suspend        = exynos_pinctrl_suspend,
+               .resume         = exynos_pinctrl_resume,
                .label          = "exynos4x12-gpio-ctrl3",
        },
 };
@@ -775,6 +900,8 @@ struct samsung_pin_ctrl exynos5250_pin_ctrl[] = {
                .svc            = EXYNOS_SVC_OFFSET,
                .eint_gpio_init = exynos_eint_gpio_init,
                .eint_wkup_init = exynos_eint_wkup_init,
+               .suspend        = exynos_pinctrl_suspend,
+               .resume         = exynos_pinctrl_resume,
                .label          = "exynos5250-gpio-ctrl0",
        }, {
                /* pin-controller instance 1 data */
@@ -785,6 +912,8 @@ struct samsung_pin_ctrl exynos5250_pin_ctrl[] = {
                .geint_pend     = EXYNOS_GPIO_EPEND_OFFSET,
                .svc            = EXYNOS_SVC_OFFSET,
                .eint_gpio_init = exynos_eint_gpio_init,
+               .suspend        = exynos_pinctrl_suspend,
+               .resume         = exynos_pinctrl_resume,
                .label          = "exynos5250-gpio-ctrl1",
        }, {
                /* pin-controller instance 2 data */
@@ -795,6 +924,8 @@ struct samsung_pin_ctrl exynos5250_pin_ctrl[] = {
                .geint_pend     = EXYNOS_GPIO_EPEND_OFFSET,
                .svc            = EXYNOS_SVC_OFFSET,
                .eint_gpio_init = exynos_eint_gpio_init,
+               .suspend        = exynos_pinctrl_suspend,
+               .resume         = exynos_pinctrl_resume,
                .label          = "exynos5250-gpio-ctrl2",
        }, {
                /* pin-controller instance 3 data */
@@ -805,6 +936,8 @@ struct samsung_pin_ctrl exynos5250_pin_ctrl[] = {
                .geint_pend     = EXYNOS_GPIO_EPEND_OFFSET,
                .svc            = EXYNOS_SVC_OFFSET,
                .eint_gpio_init = exynos_eint_gpio_init,
+               .suspend        = exynos_pinctrl_suspend,
+               .resume         = exynos_pinctrl_resume,
                .label          = "exynos5250-gpio-ctrl3",
        },
 };
index 9b1f77a..3c91c35 100644 (file)
@@ -19,6 +19,7 @@
 
 /* External GPIO and wakeup interrupt related definitions */
 #define EXYNOS_GPIO_ECON_OFFSET                0x700
+#define EXYNOS_GPIO_EFLTCON_OFFSET     0x800
 #define EXYNOS_GPIO_EMASK_OFFSET       0x900
 #define EXYNOS_GPIO_EPEND_OFFSET       0xA00
 #define EXYNOS_WKUP_ECON_OFFSET                0xE00
index 6038503..32a48f4 100644 (file)
@@ -1000,11 +1000,6 @@ static int exynos5440_pinctrl_probe(struct platform_device *pdev)
        }
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(dev, "cannot find IO resource\n");
-               return -ENOENT;
-       }
-
        priv->reg_base = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(priv->reg_base))
                return PTR_ERR(priv->reg_base);
index 615c500..d22ca25 100644 (file)
@@ -52,7 +52,8 @@ static void ltq_pinctrl_dt_free_map(struct pinctrl_dev *pctldev,
        int i;
 
        for (i = 0; i < num_maps; i++)
-               if (map[i].type == PIN_MAP_TYPE_CONFIGS_PIN)
+               if (map[i].type == PIN_MAP_TYPE_CONFIGS_PIN ||
+                   map[i].type == PIN_MAP_TYPE_CONFIGS_GROUP)
                        kfree(map[i].data.configs.configs);
        kfree(map);
 }
index 9763668..63ac22e 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/gpio.h>
 #include <linux/irqdomain.h>
 #include <linux/spinlock.h>
+#include <linux/syscore_ops.h>
 
 #include "core.h"
 #include "pinctrl-samsung.h"
@@ -48,6 +49,9 @@ static struct pin_config {
        { "samsung,pin-pud-pdn", PINCFG_TYPE_PUD_PDN },
 };
 
+/* Global list of devices (struct samsung_pinctrl_drv_data) */
+LIST_HEAD(drvdata_list);
+
 static unsigned int pin_base;
 
 static inline struct samsung_pin_bank *gc_to_pin_bank(struct gpio_chip *gc)
@@ -932,11 +936,6 @@ static int samsung_pinctrl_probe(struct platform_device *pdev)
        drvdata->dev = dev;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(dev, "cannot find IO resource\n");
-               return -ENOENT;
-       }
-
        drvdata->virt_base = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(drvdata->virt_base))
                return PTR_ERR(drvdata->virt_base);
@@ -961,9 +960,151 @@ static int samsung_pinctrl_probe(struct platform_device *pdev)
                ctrl->eint_wkup_init(drvdata);
 
        platform_set_drvdata(pdev, drvdata);
+
+       /* Add to the global list */
+       list_add_tail(&drvdata->node, &drvdata_list);
+
        return 0;
 }
 
+#ifdef CONFIG_PM
+
+/**
+ * samsung_pinctrl_suspend_dev - save pinctrl state for suspend for a device
+ *
+ * Save data for all banks handled by this device.
+ */
+static void samsung_pinctrl_suspend_dev(
+       struct samsung_pinctrl_drv_data *drvdata)
+{
+       struct samsung_pin_ctrl *ctrl = drvdata->ctrl;
+       void __iomem *virt_base = drvdata->virt_base;
+       int i;
+
+       for (i = 0; i < ctrl->nr_banks; i++) {
+               struct samsung_pin_bank *bank = &ctrl->pin_banks[i];
+               void __iomem *reg = virt_base + bank->pctl_offset;
+
+               u8 *offs = bank->type->reg_offset;
+               u8 *widths = bank->type->fld_width;
+               enum pincfg_type type;
+
+               /* Registers without a powerdown config aren't lost */
+               if (!widths[PINCFG_TYPE_CON_PDN])
+                       continue;
+
+               for (type = 0; type < PINCFG_TYPE_NUM; type++)
+                       if (widths[type])
+                               bank->pm_save[type] = readl(reg + offs[type]);
+
+               if (widths[PINCFG_TYPE_FUNC] * bank->nr_pins > 32) {
+                       /* Some banks have two config registers */
+                       bank->pm_save[PINCFG_TYPE_NUM] =
+                               readl(reg + offs[PINCFG_TYPE_FUNC] + 4);
+                       pr_debug("Save %s @ %p (con %#010x %08x)\n",
+                                bank->name, reg,
+                                bank->pm_save[PINCFG_TYPE_FUNC],
+                                bank->pm_save[PINCFG_TYPE_NUM]);
+               } else {
+                       pr_debug("Save %s @ %p (con %#010x)\n", bank->name,
+                                reg, bank->pm_save[PINCFG_TYPE_FUNC]);
+               }
+       }
+
+       if (ctrl->suspend)
+               ctrl->suspend(drvdata);
+}
+
+/**
+ * samsung_pinctrl_resume_dev - restore pinctrl state from suspend for a device
+ *
+ * Restore one of the banks that was saved during suspend.
+ *
+ * We don't bother doing anything complicated to avoid glitching lines since
+ * we're called before pad retention is turned off.
+ */
+static void samsung_pinctrl_resume_dev(struct samsung_pinctrl_drv_data *drvdata)
+{
+       struct samsung_pin_ctrl *ctrl = drvdata->ctrl;
+       void __iomem *virt_base = drvdata->virt_base;
+       int i;
+
+       if (ctrl->resume)
+               ctrl->resume(drvdata);
+
+       for (i = 0; i < ctrl->nr_banks; i++) {
+               struct samsung_pin_bank *bank = &ctrl->pin_banks[i];
+               void __iomem *reg = virt_base + bank->pctl_offset;
+
+               u8 *offs = bank->type->reg_offset;
+               u8 *widths = bank->type->fld_width;
+               enum pincfg_type type;
+
+               /* Registers without a powerdown config aren't lost */
+               if (!widths[PINCFG_TYPE_CON_PDN])
+                       continue;
+
+               if (widths[PINCFG_TYPE_FUNC] * bank->nr_pins > 32) {
+                       /* Some banks have two config registers */
+                       pr_debug("%s @ %p (con %#010x %08x => %#010x %08x)\n",
+                                bank->name, reg,
+                                readl(reg + offs[PINCFG_TYPE_FUNC]),
+                                readl(reg + offs[PINCFG_TYPE_FUNC] + 4),
+                                bank->pm_save[PINCFG_TYPE_FUNC],
+                                bank->pm_save[PINCFG_TYPE_NUM]);
+                       writel(bank->pm_save[PINCFG_TYPE_NUM],
+                              reg + offs[PINCFG_TYPE_FUNC] + 4);
+               } else {
+                       pr_debug("%s @ %p (con %#010x => %#010x)\n", bank->name,
+                                reg, readl(reg + offs[PINCFG_TYPE_FUNC]),
+                                bank->pm_save[PINCFG_TYPE_FUNC]);
+               }
+               for (type = 0; type < PINCFG_TYPE_NUM; type++)
+                       if (widths[type])
+                               writel(bank->pm_save[type], reg + offs[type]);
+       }
+}
+
+/**
+ * samsung_pinctrl_suspend - save pinctrl state for suspend
+ *
+ * Save data for all banks across all devices.
+ */
+static int samsung_pinctrl_suspend(void)
+{
+       struct samsung_pinctrl_drv_data *drvdata;
+
+       list_for_each_entry(drvdata, &drvdata_list, node) {
+               samsung_pinctrl_suspend_dev(drvdata);
+       }
+
+       return 0;
+}
+
+/**
+ * samsung_pinctrl_resume - restore pinctrl state for suspend
+ *
+ * Restore data for all banks across all devices.
+ */
+static void samsung_pinctrl_resume(void)
+{
+       struct samsung_pinctrl_drv_data *drvdata;
+
+       list_for_each_entry_reverse(drvdata, &drvdata_list, node) {
+               samsung_pinctrl_resume_dev(drvdata);
+       }
+}
+
+#else
+#define samsung_pinctrl_suspend                NULL
+#define samsung_pinctrl_resume         NULL
+#endif
+
+static struct syscore_ops samsung_pinctrl_syscore_ops = {
+       .suspend        = samsung_pinctrl_suspend,
+       .resume         = samsung_pinctrl_resume,
+};
+
 static const struct of_device_id samsung_pinctrl_dt_match[] = {
 #ifdef CONFIG_PINCTRL_EXYNOS
        { .compatible = "samsung,exynos4210-pinctrl",
@@ -992,6 +1133,14 @@ static struct platform_driver samsung_pinctrl_driver = {
 
 static int __init samsung_pinctrl_drv_register(void)
 {
+       /*
+        * Register syscore ops for save/restore of registers across suspend.
+        * It's important to ensure that this driver is running at an earlier
+        * initcall level than any arch-specific init calls that install syscore
+        * ops that turn off pad retention (like exynos_pm_resume).
+        */
+       register_syscore_ops(&samsung_pinctrl_syscore_ops);
+
        return platform_driver_register(&samsung_pinctrl_driver);
 }
 postcore_initcall(samsung_pinctrl_drv_register);
index 7c7f9eb..26d3519 100644 (file)
@@ -127,6 +127,7 @@ struct samsung_pin_bank_type {
  * @gpio_chip: GPIO chip of the bank.
  * @grange: linux gpio pin range supported by this bank.
  * @slock: spinlock protecting bank registers
+ * @pm_save: saved register values during suspend
  */
 struct samsung_pin_bank {
        struct samsung_pin_bank_type *type;
@@ -138,12 +139,15 @@ struct samsung_pin_bank {
        u32             eint_mask;
        u32             eint_offset;
        char            *name;
+       void            *soc_priv;
        struct device_node *of_node;
        struct samsung_pinctrl_drv_data *drvdata;
        struct irq_domain *irq_domain;
        struct gpio_chip gpio_chip;
        struct pinctrl_gpio_range grange;
        spinlock_t slock;
+
+       u32 pm_save[PINCFG_TYPE_NUM + 1]; /* +1 to handle double CON registers*/
 };
 
 /**
@@ -184,11 +188,15 @@ struct samsung_pin_ctrl {
 
        int             (*eint_gpio_init)(struct samsung_pinctrl_drv_data *);
        int             (*eint_wkup_init)(struct samsung_pinctrl_drv_data *);
+       void            (*suspend)(struct samsung_pinctrl_drv_data *);
+       void            (*resume)(struct samsung_pinctrl_drv_data *);
+
        char            *label;
 };
 
 /**
  * struct samsung_pinctrl_drv_data: wrapper for holding driver data together.
+ * @node: global list node
  * @virt_base: register base address of the controller.
  * @dev: device instance representing the controller.
  * @irq: interrpt number used by the controller to notify gpio interrupts.
@@ -201,6 +209,7 @@ struct samsung_pin_ctrl {
  * @nr_function: number of such pin functions.
  */
 struct samsung_pinctrl_drv_data {
+       struct list_head                node;
        void __iomem                    *virt_base;
        struct device                   *dev;
        int                             irq;
index 5f2d2bf..b9fa046 100644 (file)
@@ -1166,7 +1166,8 @@ static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs,
        (*map)->data.mux.function = np->name;
 
        if (pcs->is_pinconf) {
-               if (pcs_parse_pinconf(pcs, np, function, map))
+               res = pcs_parse_pinconf(pcs, np, function, map);
+               if (res)
                        goto free_pingroups;
                *num_maps = 2;
        } else {
index c52fc2c..b7d8c89 100644 (file)
@@ -1990,8 +1990,10 @@ static int sunxi_pinctrl_probe(struct platform_device *pdev)
        }
 
        clk = devm_clk_get(&pdev->dev, NULL);
-       if (IS_ERR(clk))
+       if (IS_ERR(clk)) {
+               ret = PTR_ERR(clk);
                goto gpiochip_error;
+       }
 
        clk_prepare_enable(clk);
 
@@ -2000,7 +2002,8 @@ static int sunxi_pinctrl_probe(struct platform_device *pdev)
        return 0;
 
 gpiochip_error:
-       ret = gpiochip_remove(pctl->chip);
+       if (gpiochip_remove(pctl->chip))
+               dev_err(&pdev->dev, "failed to remove gpio chip\n");
 pinctrl_error:
        pinctrl_unregister(pctl->pctl_dev);
        return ret;
index f2977cf..e92132c 100644 (file)
@@ -716,10 +716,6 @@ static int pinmux_xway_probe(struct platform_device *pdev)
 
        /* get and remap our register range */
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(&pdev->dev, "Failed to get resource\n");
-               return -ENOENT;
-       }
        xway_info.membase[0] = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(xway_info.membase[0]))
                return PTR_ERR(xway_info.membase[0]);
index 791a671..8cd90e7 100644 (file)
@@ -2357,27 +2357,48 @@ static const unsigned int sdhi3_wp_mux[] = {
 };
 /* - USB0 ------------------------------------------------------------------- */
 static const unsigned int usb0_pins[] = {
-       /* OVC */
-       150, 154,
+       /* PENC */
+       154,
 };
 static const unsigned int usb0_mux[] = {
-       USB_OVC0_MARK, USB_PENC0_MARK,
+       USB_PENC0_MARK,
+};
+static const unsigned int usb0_ovc_pins[] = {
+       /* USB_OVC */
+       150
+};
+static const unsigned int usb0_ovc_mux[] = {
+       USB_OVC0_MARK,
 };
 /* - USB1 ------------------------------------------------------------------- */
 static const unsigned int usb1_pins[] = {
-       /* OVC */
-       152, 155,
+       /* PENC */
+       155,
 };
 static const unsigned int usb1_mux[] = {
-       USB_OVC1_MARK, USB_PENC1_MARK,
+       USB_PENC1_MARK,
+};
+static const unsigned int usb1_ovc_pins[] = {
+       /* USB_OVC */
+       152,
+};
+static const unsigned int usb1_ovc_mux[] = {
+       USB_OVC1_MARK,
 };
 /* - USB2 ------------------------------------------------------------------- */
 static const unsigned int usb2_pins[] = {
-       /* OVC, PENC */
-       125, 156,
+       /* PENC */
+       156,
 };
 static const unsigned int usb2_mux[] = {
-       USB_OVC2_MARK, USB_PENC2_MARK,
+       USB_PENC2_MARK,
+};
+static const unsigned int usb2_ovc_pins[] = {
+       /* USB_OVC */
+       125,
+};
+static const unsigned int usb2_ovc_mux[] = {
+       USB_OVC2_MARK,
 };
 
 static const struct sh_pfc_pin_group pinmux_groups[] = {
@@ -2501,8 +2522,11 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
        SH_PFC_PIN_GROUP(sdhi3_cd),
        SH_PFC_PIN_GROUP(sdhi3_wp),
        SH_PFC_PIN_GROUP(usb0),
+       SH_PFC_PIN_GROUP(usb0_ovc),
        SH_PFC_PIN_GROUP(usb1),
+       SH_PFC_PIN_GROUP(usb1_ovc),
        SH_PFC_PIN_GROUP(usb2),
+       SH_PFC_PIN_GROUP(usb2_ovc),
 };
 
 static const char * const du0_groups[] = {
@@ -2683,14 +2707,17 @@ static const char * const sdhi3_groups[] = {
 
 static const char * const usb0_groups[] = {
        "usb0",
+       "usb0_ovc",
 };
 
 static const char * const usb1_groups[] = {
        "usb1",
+       "usb1_ovc",
 };
 
 static const char * const usb2_groups[] = {
        "usb2",
+       "usb2_ovc",
 };
 
 static const struct sh_pfc_function pinmux_functions[] = {
index b964cc5..de43262 100644 (file)
@@ -53,7 +53,7 @@ static const struct wmt_pinctrl_bank_registers wm8750_banks[] = {
 #define WMT_PIN_EXTGPIO6       WMT_PIN(0, 6)
 #define WMT_PIN_EXTGPIO7       WMT_PIN(0, 7)
 #define WMT_PIN_WAKEUP0                WMT_PIN(0, 16)
-#define WMT_PIN_WAKEUP1                WMT_PIN(0, 16)
+#define WMT_PIN_WAKEUP1                WMT_PIN(0, 17)
 #define WMT_PIN_SD0CD          WMT_PIN(0, 28)
 #define WMT_PIN_VDOUT0         WMT_PIN(1, 0)
 #define WMT_PIN_VDOUT1         WMT_PIN(1, 1)
index ab63104..70d986e 100644 (file)
@@ -609,8 +609,7 @@ int wmt_pinctrl_probe(struct platform_device *pdev,
        return 0;
 
 fail_range:
-       err = gpiochip_remove(&data->gpio_chip);
-       if (err)
+       if (gpiochip_remove(&data->gpio_chip))
                dev_err(&pdev->dev, "failed to remove gpio chip\n");
 fail_gpio:
        pinctrl_unregister(data->pctl_dev);
index 3338437..8577261 100644 (file)
@@ -781,4 +781,12 @@ config APPLE_GMUX
          graphics as well as the backlight. Currently only backlight
          control is supported by the driver.
 
+config PVPANIC
+       tristate "pvpanic device support"
+       depends on ACPI
+       ---help---
+         This driver provides support for the pvpanic device.  pvpanic is
+         a paravirtualized device provided by QEMU; it lets a virtual machine
+         (guest) communicate panic events to the host.
+
 endif # X86_PLATFORM_DEVICES
index ace2b38..ef0ec74 100644 (file)
@@ -51,3 +51,5 @@ obj-$(CONFIG_INTEL_OAKTRAIL)  += intel_oaktrail.o
 obj-$(CONFIG_SAMSUNG_Q10)      += samsung-q10.o
 obj-$(CONFIG_APPLE_GMUX)       += apple-gmux.o
 obj-$(CONFIG_CHROMEOS_LAPTOP)  += chromeos_laptop.o
+
+obj-$(CONFIG_PVPANIC)           += pvpanic.o
index 210b5b8..8fcb41e 100644 (file)
@@ -171,6 +171,15 @@ static struct dmi_system_id asus_quirks[] = {
                },
                .driver_data = &quirk_asus_x401u,
        },
+       {
+               .callback = dmi_matched,
+               .ident = "ASUSTeK COMPUTER INC. X75A",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "X75A"),
+               },
+               .driver_data = &quirk_asus_x401u,
+       },
        {},
 };
 
index fa3ee62..1134119 100644 (file)
@@ -284,6 +284,7 @@ static void __init parse_da_table(const struct dmi_header *dm)
 {
        /* Final token is a terminator, so we don't want to copy it */
        int tokens = (dm->length-11)/sizeof(struct calling_interface_token)-1;
+       struct calling_interface_token *new_da_tokens;
        struct calling_interface_structure *table =
                container_of(dm, struct calling_interface_structure, header);
 
@@ -296,12 +297,13 @@ static void __init parse_da_table(const struct dmi_header *dm)
        da_command_address = table->cmdIOAddress;
        da_command_code = table->cmdIOCode;
 
-       da_tokens = krealloc(da_tokens, (da_num_tokens + tokens) *
-                            sizeof(struct calling_interface_token),
-                            GFP_KERNEL);
+       new_da_tokens = krealloc(da_tokens, (da_num_tokens + tokens) *
+                                sizeof(struct calling_interface_token),
+                                GFP_KERNEL);
 
-       if (!da_tokens)
+       if (!new_da_tokens)
                return;
+       da_tokens = new_da_tokens;
 
        memcpy(da_tokens+da_num_tokens, table->tokens,
               sizeof(struct calling_interface_token) * tokens);
index 3f94545..bcf8cc6 100644 (file)
@@ -34,6 +34,14 @@ MODULE_LICENSE("GPL");
 #define EVENT_GUID1 "284A0E6B-380E-472A-921F-E52786257FB4"
 #define EVENT_GUID2 "02314822-307C-4F66-BF0E-48AEAEB26CC8"
 
+struct dell_wmi_event {
+       u16     length;
+       /* 0x000: A hot key pressed or an event occurred
+        * 0x00F: A sequence of hot keys are pressed */
+       u16     type;
+       u16     event[];
+};
+
 static const char *dell_wmi_aio_guids[] = {
        EVENT_GUID1,
        EVENT_GUID2,
@@ -46,15 +54,41 @@ MODULE_ALIAS("wmi:"EVENT_GUID2);
 static const struct key_entry dell_wmi_aio_keymap[] = {
        { KE_KEY, 0xc0, { KEY_VOLUMEUP } },
        { KE_KEY, 0xc1, { KEY_VOLUMEDOWN } },
+       { KE_KEY, 0xe030, { KEY_VOLUMEUP } },
+       { KE_KEY, 0xe02e, { KEY_VOLUMEDOWN } },
+       { KE_KEY, 0xe020, { KEY_MUTE } },
+       { KE_KEY, 0xe027, { KEY_DISPLAYTOGGLE } },
+       { KE_KEY, 0xe006, { KEY_BRIGHTNESSUP } },
+       { KE_KEY, 0xe005, { KEY_BRIGHTNESSDOWN } },
+       { KE_KEY, 0xe00b, { KEY_SWITCHVIDEOMODE } },
        { KE_END, 0 }
 };
 
 static struct input_dev *dell_wmi_aio_input_dev;
 
+/*
+ * The new WMI event data format will follow the dell_wmi_event structure
+ * So, we will check if the buffer matches the format
+ */
+static bool dell_wmi_aio_event_check(u8 *buffer, int length)
+{
+       struct dell_wmi_event *event = (struct dell_wmi_event *)buffer;
+
+       if (event == NULL || length < 6)
+               return false;
+
+       if ((event->type == 0 || event->type == 0xf) &&
+                       event->length >= 2)
+               return true;
+
+       return false;
+}
+
 static void dell_wmi_aio_notify(u32 value, void *context)
 {
        struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
        union acpi_object *obj;
+       struct dell_wmi_event *event;
        acpi_status status;
 
        status = wmi_get_event_data(value, &response);
@@ -65,7 +99,7 @@ static void dell_wmi_aio_notify(u32 value, void *context)
 
        obj = (union acpi_object *)response.pointer;
        if (obj) {
-               unsigned int scancode;
+               unsigned int scancode = 0;
 
                switch (obj->type) {
                case ACPI_TYPE_INTEGER:
@@ -75,13 +109,22 @@ static void dell_wmi_aio_notify(u32 value, void *context)
                                scancode, 1, true);
                        break;
                case ACPI_TYPE_BUFFER:
-                       /* Broken machines return the scancode in a buffer */
-                       if (obj->buffer.pointer && obj->buffer.length > 0) {
-                               scancode = obj->buffer.pointer[0];
+                       if (dell_wmi_aio_event_check(obj->buffer.pointer,
+                                               obj->buffer.length)) {
+                               event = (struct dell_wmi_event *)
+                                       obj->buffer.pointer;
+                               scancode = event->event[0];
+                       } else {
+                               /* Broken machines return the scancode in a
+                                  buffer */
+                               if (obj->buffer.pointer &&
+                                               obj->buffer.length > 0)
+                                       scancode = obj->buffer.pointer[0];
+                       }
+                       if (scancode)
                                sparse_keymap_report_event(
                                        dell_wmi_aio_input_dev,
                                        scancode, 1, true);
-                       }
                        break;
                }
        }
index 1a779bb..d111c86 100644 (file)
@@ -71,6 +71,14 @@ enum hp_wmi_event_ids {
        HPWMI_WIRELESS = 5,
        HPWMI_CPU_BATTERY_THROTTLE = 6,
        HPWMI_LOCK_SWITCH = 7,
+       HPWMI_LID_SWITCH = 8,
+       HPWMI_SCREEN_ROTATION = 9,
+       HPWMI_COOLSENSE_SYSTEM_MOBILE = 0x0A,
+       HPWMI_COOLSENSE_SYSTEM_HOT = 0x0B,
+       HPWMI_PROXIMITY_SENSOR = 0x0C,
+       HPWMI_BACKLIT_KB_BRIGHTNESS = 0x0D,
+       HPWMI_PEAKSHIFT_PERIOD = 0x0F,
+       HPWMI_BATTERY_CHARGE_PERIOD = 0x10,
 };
 
 struct bios_args {
@@ -536,6 +544,22 @@ static void hp_wmi_notify(u32 value, void *context)
                break;
        case HPWMI_LOCK_SWITCH:
                break;
+       case HPWMI_LID_SWITCH:
+               break;
+       case HPWMI_SCREEN_ROTATION:
+               break;
+       case HPWMI_COOLSENSE_SYSTEM_MOBILE:
+               break;
+       case HPWMI_COOLSENSE_SYSTEM_HOT:
+               break;
+       case HPWMI_PROXIMITY_SENSOR:
+               break;
+       case HPWMI_BACKLIT_KB_BRIGHTNESS:
+               break;
+       case HPWMI_PEAKSHIFT_PERIOD:
+               break;
+       case HPWMI_BATTERY_CHARGE_PERIOD:
+               break;
        default:
                pr_info("Unknown event_id - %d - 0x%x\n", event_id, event_data);
                break;
@@ -679,7 +703,7 @@ static int hp_wmi_rfkill_setup(struct platform_device *device)
                }
                rfkill_init_sw_state(gps_rfkill,
                                     hp_wmi_get_sw_state(HPWMI_GPS));
-               rfkill_set_hw_state(bluetooth_rfkill,
+               rfkill_set_hw_state(gps_rfkill,
                                    hp_wmi_get_hw_state(HPWMI_GPS));
                err = rfkill_register(gps_rfkill);
                if (err)
index e64a7a8..a8e43cf 100644 (file)
@@ -362,7 +362,8 @@ static int lis3lv02d_suspend(struct device *dev)
 
 static int lis3lv02d_resume(struct device *dev)
 {
-       return lis3lv02d_poweron(&lis3_dev);
+       lis3lv02d_poweron(&lis3_dev);
+       return 0;
 }
 
 static SIMPLE_DEV_PM_OPS(hp_accel_pm, lis3lv02d_suspend, lis3lv02d_resume);
index 17f00b8..89c4519 100644 (file)
@@ -640,7 +640,8 @@ static void ideapad_check_special_buttons(struct ideapad_private *priv)
        for (bit = 0; bit < 16; bit++) {
                if (test_bit(bit, &value)) {
                        switch (bit) {
-                       case 6:
+                       case 0: /* Z580 */
+                       case 6: /* Z570 */
                                /* Thermal Management button */
                                ideapad_input_report(priv, 65);
                                break;
@@ -648,6 +649,9 @@ static void ideapad_check_special_buttons(struct ideapad_private *priv)
                                /* OneKey Theater button */
                                ideapad_input_report(priv, 64);
                                break;
+                       default:
+                               pr_info("Unknown special button: %lu\n", bit);
+                               break;
                        }
                }
        }
diff --git a/drivers/platform/x86/pvpanic.c b/drivers/platform/x86/pvpanic.c
new file mode 100644 (file)
index 0000000..47ae0c4
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ *  pvpanic.c - pvpanic Device Support
+ *
+ *  Copyright (C) 2013 Fujitsu.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <acpi/acpi_bus.h>
+#include <acpi/acpi_drivers.h>
+
+MODULE_AUTHOR("Hu Tao <hutao@cn.fujitsu.com>");
+MODULE_DESCRIPTION("pvpanic device driver");
+MODULE_LICENSE("GPL");
+
+static int pvpanic_add(struct acpi_device *device);
+static int pvpanic_remove(struct acpi_device *device);
+
+static const struct acpi_device_id pvpanic_device_ids[] = {
+       { "QEMU0001", 0 },
+       { "", 0 },
+};
+MODULE_DEVICE_TABLE(acpi, pvpanic_device_ids);
+
+#define PVPANIC_PANICKED       (1 << 0)
+
+static u16 port;
+
+static struct acpi_driver pvpanic_driver = {
+       .name =         "pvpanic",
+       .class =        "QEMU",
+       .ids =          pvpanic_device_ids,
+       .ops =          {
+                               .add =          pvpanic_add,
+                               .remove =       pvpanic_remove,
+                       },
+       .owner =        THIS_MODULE,
+};
+
+static void
+pvpanic_send_event(unsigned int event)
+{
+       outb(event, port);
+}
+
+static int
+pvpanic_panic_notify(struct notifier_block *nb, unsigned long code,
+                    void *unused)
+{
+       pvpanic_send_event(PVPANIC_PANICKED);
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block pvpanic_panic_nb = {
+       .notifier_call = pvpanic_panic_notify,
+};
+
+
+static acpi_status
+pvpanic_walk_resources(struct acpi_resource *res, void *context)
+{
+       switch (res->type) {
+       case ACPI_RESOURCE_TYPE_END_TAG:
+               return AE_OK;
+
+       case ACPI_RESOURCE_TYPE_IO:
+               port = res->data.io.minimum;
+               return AE_OK;
+
+       default:
+               return AE_ERROR;
+       }
+}
+
+static int pvpanic_add(struct acpi_device *device)
+{
+       acpi_status status;
+       u64 ret;
+
+       status = acpi_evaluate_integer(device->handle, "_STA", NULL,
+                                      &ret);
+
+       if (ACPI_FAILURE(status) || (ret & 0x0B) != 0x0B)
+               return -ENODEV;
+
+       acpi_walk_resources(device->handle, METHOD_NAME__CRS,
+                           pvpanic_walk_resources, NULL);
+
+       if (!port)
+               return -ENODEV;
+
+       atomic_notifier_chain_register(&panic_notifier_list,
+                                      &pvpanic_panic_nb);
+
+       return 0;
+}
+
+static int pvpanic_remove(struct acpi_device *device)
+{
+
+       atomic_notifier_chain_unregister(&panic_notifier_list,
+                                        &pvpanic_panic_nb);
+       return 0;
+}
+
+module_acpi_driver(pvpanic_driver);
index 5f77005..1a90b62 100644 (file)
@@ -176,10 +176,7 @@ static int __init samsungq10_init(void)
                                                   samsungq10_probe,
                                                   NULL, 0, NULL, 0);
 
-       if (IS_ERR(samsungq10_device))
-               return PTR_ERR(samsungq10_device);
-
-       return 0;
+       return PTR_RET(samsungq10_device);
 }
 
 static void __exit samsungq10_exit(void)
index d544e3a..2ac045f 100644 (file)
@@ -1255,6 +1255,11 @@ static void sony_nc_notify(struct acpi_device *device, u32 event)
                        real_ev = __sony_nc_gfx_switch_status_get();
                        break;
 
+               case 0x015B:
+                       /* Hybrid GFX switching SVS151290S */
+                       ev_type = GFX_SWITCH;
+                       real_ev = __sony_nc_gfx_switch_status_get();
+                       break;
                default:
                        dprintk("Unknown event 0x%x for handle 0x%x\n",
                                        event, handle);
@@ -1353,6 +1358,7 @@ static void sony_nc_function_setup(struct acpi_device *device,
                        break;
                case 0x0128:
                case 0x0146:
+               case 0x015B:
                        result = sony_nc_gfx_switch_setup(pf_device, handle);
                        if (result)
                                pr_err("couldn't set up GFX Switch status (%d)\n",
@@ -1375,6 +1381,7 @@ static void sony_nc_function_setup(struct acpi_device *device,
                case 0x0143:
                case 0x014b:
                case 0x014c:
+               case 0x0163:
                        result = sony_nc_kbd_backlight_setup(pf_device, handle);
                        if (result)
                                pr_err("couldn't set up keyboard backlight function (%d)\n",
@@ -1426,6 +1433,7 @@ static void sony_nc_function_cleanup(struct platform_device *pd)
                        break;
                case 0x0128:
                case 0x0146:
+               case 0x015B:
                        sony_nc_gfx_switch_cleanup(pd);
                        break;
                case 0x0131:
@@ -1439,6 +1447,7 @@ static void sony_nc_function_cleanup(struct platform_device *pd)
                case 0x0143:
                case 0x014b:
                case 0x014c:
+               case 0x0163:
                        sony_nc_kbd_backlight_cleanup(pd);
                        break;
                default:
@@ -1485,6 +1494,7 @@ static void sony_nc_function_resume(void)
                case 0x0143:
                case 0x014b:
                case 0x014c:
+               case 0x0163:
                        sony_nc_kbd_backlight_resume();
                        break;
                default:
@@ -2390,7 +2400,9 @@ static int __sony_nc_gfx_switch_status_get(void)
 {
        unsigned int result;
 
-       if (sony_call_snc_handle(gfxs_ctl->handle, 0x0100, &result))
+       if (sony_call_snc_handle(gfxs_ctl->handle,
+                               gfxs_ctl->handle == 0x015B ? 0x0000 : 0x0100,
+                               &result))
                return -EIO;
 
        switch (gfxs_ctl->handle) {
@@ -2400,6 +2412,12 @@ static int __sony_nc_gfx_switch_status_get(void)
                 */
                return result & 0x1 ? SPEED : STAMINA;
                break;
+       case 0x015B:
+               /* 0: discrete GFX (speed)
+                * 1: integrated GFX (stamina)
+                */
+               return result & 0x1 ? STAMINA : SPEED;
+               break;
        case 0x0128:
                /* it's a more elaborated bitmask, for now:
                 * 2: integrated GFX (stamina)
index 0d0b5d7..7b8979c 100644 (file)
@@ -152,6 +152,7 @@ config BATTERY_SBS
 
 config BATTERY_BQ27x00
        tristate "BQ27x00 battery driver"
+       depends on I2C || I2C=n
        help
          Say Y here to enable support for batteries with BQ27x00 (I2C/HDQ) chips.
 
@@ -284,6 +285,7 @@ config CHARGER_LP8788
        tristate "TI LP8788 charger driver"
        depends on MFD_LP8788
        depends on LP8788_ADC
+       depends on IIO
        help
          Say Y to enable support for the LP8788 linear charger.
 
index a441751..fef56e2 100644 (file)
@@ -1269,5 +1269,5 @@ module_exit(pm2xxx_charger_exit);
 
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Rajkumar kasirajan, Olivier Launay");
-MODULE_ALIAS("platform:pm2xxx-charger");
+MODULE_ALIAS("i2c:pm2xxx-charger");
 MODULE_DESCRIPTION("PM2xxx charger management driver");
index 58cbb00..56fb509 100644 (file)
@@ -207,7 +207,6 @@ static int wm831x_backup_remove(struct platform_device *pdev)
        struct wm831x_backup *devdata = platform_get_drvdata(pdev);
 
        power_supply_unregister(&devdata->backup);
-       kfree(devdata->backup.name);
 
        return 0;
 }
index bea9451..71a2559 100644 (file)
@@ -628,9 +628,10 @@ pch_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
        chip->caps = ptp_pch_caps;
        chip->ptp_clock = ptp_clock_register(&chip->caps, &pdev->dev);
-
-       if (IS_ERR(chip->ptp_clock))
-               return PTR_ERR(chip->ptp_clock);
+       if (IS_ERR(chip->ptp_clock)) {
+               ret = PTR_ERR(chip->ptp_clock);
+               goto err_ptp_clock_reg;
+       }
 
        spin_lock_init(&chip->register_lock);
 
@@ -669,6 +670,7 @@ pch_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
 err_req_irq:
        ptp_clock_unregister(chip->ptp_clock);
+err_ptp_clock_reg:
        iounmap(chip->regs);
        chip->regs = NULL;
 
index ec28798..c938bae 100644 (file)
@@ -265,11 +265,6 @@ static int imx_pwm_probe(struct platform_device *pdev)
        imx->chip.npwm = 1;
 
        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (r == NULL) {
-               dev_err(&pdev->dev, "no memory resource defined\n");
-               return -ENODEV;
-       }
-
        imx->mmio_base = devm_ioremap_resource(&pdev->dev, r);
        if (IS_ERR(imx->mmio_base))
                return PTR_ERR(imx->mmio_base);
index d1eb499..ed6007b 100644 (file)
@@ -117,11 +117,6 @@ static int pwm_probe(struct platform_device *pdev)
                return PTR_ERR(puv3->clk);
 
        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (r == NULL) {
-               dev_err(&pdev->dev, "no memory resource defined\n");
-               return -ENODEV;
-       }
-
        puv3->base = devm_ioremap_resource(&pdev->dev, r);
        if (IS_ERR(puv3->base))
                return PTR_ERR(puv3->base);
index dee6ab5..dc97175 100644 (file)
@@ -147,11 +147,6 @@ static int pwm_probe(struct platform_device *pdev)
        pwm->chip.npwm = (id->driver_data & HAS_SECONDARY_PWM) ? 2 : 1;
 
        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (r == NULL) {
-               dev_err(&pdev->dev, "no memory resource defined\n");
-               return -ENODEV;
-       }
-
        pwm->mmio_base = devm_ioremap_resource(&pdev->dev, r);
        if (IS_ERR(pwm->mmio_base))
                return PTR_ERR(pwm->mmio_base);
index 3d75f4a..a540293 100644 (file)
@@ -181,11 +181,6 @@ static int tegra_pwm_probe(struct platform_device *pdev)
        pwm->dev = &pdev->dev;
 
        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!r) {
-               dev_err(&pdev->dev, "no memory resources defined\n");
-               return -ENODEV;
-       }
-
        pwm->mmio_base = devm_ioremap_resource(&pdev->dev, r);
        if (IS_ERR(pwm->mmio_base))
                return PTR_ERR(pwm->mmio_base);
index 0d65fb2..72ca42d 100644 (file)
@@ -240,11 +240,6 @@ static int ecap_pwm_probe(struct platform_device *pdev)
        pc->chip.npwm = 1;
 
        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!r) {
-               dev_err(&pdev->dev, "no memory resource defined\n");
-               return -ENODEV;
-       }
-
        pc->mmio_base = devm_ioremap_resource(&pdev->dev, r);
        if (IS_ERR(pc->mmio_base))
                return PTR_ERR(pc->mmio_base);
index 6a21759..48a485c 100644 (file)
@@ -471,11 +471,6 @@ static int ehrpwm_pwm_probe(struct platform_device *pdev)
        pc->chip.npwm = NUM_PWM_CHANNEL;
 
        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!r) {
-               dev_err(&pdev->dev, "no memory resource defined\n");
-               return -ENODEV;
-       }
-
        pc->mmio_base = devm_ioremap_resource(&pdev->dev, r);
        if (IS_ERR(pc->mmio_base))
                return PTR_ERR(pc->mmio_base);
index c9c3d3a..3b119bc 100644 (file)
@@ -70,11 +70,6 @@ static int pwmss_probe(struct platform_device *pdev)
        mutex_init(&info->pwmss_lock);
 
        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!r) {
-               dev_err(&pdev->dev, "no memory resource defined\n");
-               return -ENODEV;
-       }
-
        info->mmio_base = devm_ioremap_resource(&pdev->dev, r);
        if (IS_ERR(info->mmio_base))
                return PTR_ERR(info->mmio_base);
index 69effd1..323125a 100644 (file)
@@ -230,11 +230,6 @@ static int vt8500_pwm_probe(struct platform_device *pdev)
        }
 
        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (r == NULL) {
-               dev_err(&pdev->dev, "no memory resource defined\n");
-               return -ENODEV;
-       }
-
        chip->base = devm_ioremap_resource(&pdev->dev, r);
        if (IS_ERR(chip->base))
                return PTR_ERR(chip->base);
index 6194d35..5ab0564 100644 (file)
@@ -47,4 +47,24 @@ config RAPIDIO_DEBUG
 
          If you are unsure about this, say N here.
 
+choice
+       prompt "Enumeration method"
+       depends on RAPIDIO
+       default RAPIDIO_ENUM_BASIC
+       help
+         There are different enumeration and discovery mechanisms offered
+         for RapidIO subsystem. You may select single built-in method or
+         or any number of methods to be built as modules.
+         Selecting a built-in method disables use of loadable methods.
+
+         If unsure, select Basic built-in.
+
+config RAPIDIO_ENUM_BASIC
+       tristate "Basic"
+       help
+         This option includes basic RapidIO fabric enumeration and discovery
+         mechanism similar to one described in RapidIO specification Annex 1.
+
+endchoice
+
 source "drivers/rapidio/switches/Kconfig"
index ec3fb81..3036702 100644 (file)
@@ -1,7 +1,8 @@
 #
 # Makefile for RapidIO interconnect services
 #
-obj-y += rio.o rio-access.o rio-driver.o rio-scan.o rio-sysfs.o
+obj-y += rio.o rio-access.o rio-driver.o rio-sysfs.o
+obj-$(CONFIG_RAPIDIO_ENUM_BASIC) += rio-scan.o
 
 obj-$(CONFIG_RAPIDIO)          += switches/
 obj-$(CONFIG_RAPIDIO)          += devices/
index 6faba40..a8b2c23 100644 (file)
@@ -471,6 +471,10 @@ static irqreturn_t tsi721_irqhandler(int irq, void *ptr)
        u32 intval;
        u32 ch_inte;
 
+       /* For MSI mode disable all device-level interrupts */
+       if (priv->flags & TSI721_USING_MSI)
+               iowrite32(0, priv->regs + TSI721_DEV_INTE);
+
        dev_int = ioread32(priv->regs + TSI721_DEV_INT);
        if (!dev_int)
                return IRQ_NONE;
@@ -560,6 +564,14 @@ static irqreturn_t tsi721_irqhandler(int irq, void *ptr)
                }
        }
 #endif
+
+       /* For MSI mode re-enable device-level interrupts */
+       if (priv->flags & TSI721_USING_MSI) {
+               dev_int = TSI721_DEV_INT_SR2PC_CH | TSI721_DEV_INT_SRIO |
+                       TSI721_DEV_INT_SMSG_CH | TSI721_DEV_INT_BDMA_CH;
+               iowrite32(dev_int, priv->regs + TSI721_DEV_INTE);
+       }
+
        return IRQ_HANDLED;
 }
 
index 0f4a53b..a0c8755 100644 (file)
@@ -164,6 +164,13 @@ void rio_unregister_driver(struct rio_driver *rdrv)
        driver_unregister(&rdrv->driver);
 }
 
+void rio_attach_device(struct rio_dev *rdev)
+{
+       rdev->dev.bus = &rio_bus_type;
+       rdev->dev.parent = &rio_bus;
+}
+EXPORT_SYMBOL_GPL(rio_attach_device);
+
 /**
  *  rio_match_bus - Tell if a RIO device structure has a matching RIO driver device id structure
  *  @dev: the standard device structure to match against
@@ -200,6 +207,7 @@ struct bus_type rio_bus_type = {
        .name = "rapidio",
        .match = rio_match_bus,
        .dev_attrs = rio_dev_attrs,
+       .bus_attrs = rio_bus_attrs,
        .probe = rio_device_probe,
        .remove = rio_device_remove,
 };
index a965acd..4c15dbf 100644 (file)
 
 #include "rio.h"
 
-LIST_HEAD(rio_devices);
-
 static void rio_init_em(struct rio_dev *rdev);
 
-DEFINE_SPINLOCK(rio_global_list_lock);
-
 static int next_destid = 0;
 static int next_comptag = 1;
 
@@ -326,127 +322,6 @@ static int rio_is_switch(struct rio_dev *rdev)
        return 0;
 }
 
-/**
- * rio_switch_init - Sets switch operations for a particular vendor switch
- * @rdev: RIO device
- * @do_enum: Enumeration/Discovery mode flag
- *
- * Searches the RIO switch ops table for known switch types. If the vid
- * and did match a switch table entry, then call switch initialization
- * routine to setup switch-specific routines.
- */
-static void rio_switch_init(struct rio_dev *rdev, int do_enum)
-{
-       struct rio_switch_ops *cur = __start_rio_switch_ops;
-       struct rio_switch_ops *end = __end_rio_switch_ops;
-
-       while (cur < end) {
-               if ((cur->vid == rdev->vid) && (cur->did == rdev->did)) {
-                       pr_debug("RIO: calling init routine for %s\n",
-                                rio_name(rdev));
-                       cur->init_hook(rdev, do_enum);
-                       break;
-               }
-               cur++;
-       }
-
-       if ((cur >= end) && (rdev->pef & RIO_PEF_STD_RT)) {
-               pr_debug("RIO: adding STD routing ops for %s\n",
-                       rio_name(rdev));
-               rdev->rswitch->add_entry = rio_std_route_add_entry;
-               rdev->rswitch->get_entry = rio_std_route_get_entry;
-               rdev->rswitch->clr_table = rio_std_route_clr_table;
-       }
-
-       if (!rdev->rswitch->add_entry || !rdev->rswitch->get_entry)
-               printk(KERN_ERR "RIO: missing routing ops for %s\n",
-                      rio_name(rdev));
-}
-
-/**
- * rio_add_device- Adds a RIO device to the device model
- * @rdev: RIO device
- *
- * Adds the RIO device to the global device list and adds the RIO
- * device to the RIO device list.  Creates the generic sysfs nodes
- * for an RIO device.
- */
-static int rio_add_device(struct rio_dev *rdev)
-{
-       int err;
-
-       err = device_add(&rdev->dev);
-       if (err)
-               return err;
-
-       spin_lock(&rio_global_list_lock);
-       list_add_tail(&rdev->global_list, &rio_devices);
-       spin_unlock(&rio_global_list_lock);
-
-       rio_create_sysfs_dev_files(rdev);
-
-       return 0;
-}
-
-/**
- * rio_enable_rx_tx_port - enable input receiver and output transmitter of
- * given port
- * @port: Master port associated with the RIO network
- * @local: local=1 select local port otherwise a far device is reached
- * @destid: Destination ID of the device to check host bit
- * @hopcount: Number of hops to reach the target
- * @port_num: Port (-number on switch) to enable on a far end device
- *
- * Returns 0 or 1 from on General Control Command and Status Register
- * (EXT_PTR+0x3C)
- */
-inline int rio_enable_rx_tx_port(struct rio_mport *port,
-                                int local, u16 destid,
-                                u8 hopcount, u8 port_num) {
-#ifdef CONFIG_RAPIDIO_ENABLE_RX_TX_PORTS
-       u32 regval;
-       u32 ext_ftr_ptr;
-
-       /*
-       * enable rx input tx output port
-       */
-       pr_debug("rio_enable_rx_tx_port(local = %d, destid = %d, hopcount = "
-                "%d, port_num = %d)\n", local, destid, hopcount, port_num);
-
-       ext_ftr_ptr = rio_mport_get_physefb(port, local, destid, hopcount);
-
-       if (local) {
-               rio_local_read_config_32(port, ext_ftr_ptr +
-                               RIO_PORT_N_CTL_CSR(0),
-                               &regval);
-       } else {
-               if (rio_mport_read_config_32(port, destid, hopcount,
-               ext_ftr_ptr + RIO_PORT_N_CTL_CSR(port_num), &regval) < 0)
-                       return -EIO;
-       }
-
-       if (regval & RIO_PORT_N_CTL_P_TYP_SER) {
-               /* serial */
-               regval = regval | RIO_PORT_N_CTL_EN_RX_SER
-                               | RIO_PORT_N_CTL_EN_TX_SER;
-       } else {
-               /* parallel */
-               regval = regval | RIO_PORT_N_CTL_EN_RX_PAR
-                               | RIO_PORT_N_CTL_EN_TX_PAR;
-       }
-
-       if (local) {
-               rio_local_write_config_32(port, ext_ftr_ptr +
-                                         RIO_PORT_N_CTL_CSR(0), regval);
-       } else {
-               if (rio_mport_write_config_32(port, destid, hopcount,
-                   ext_ftr_ptr + RIO_PORT_N_CTL_CSR(port_num), regval) < 0)
-                       return -EIO;
-       }
-#endif
-       return 0;
-}
-
 /**
  * rio_setup_device- Allocates and sets up a RIO device
  * @net: RIO network
@@ -587,8 +462,7 @@ static struct rio_dev *rio_setup_device(struct rio_net *net,
                             rdev->destid);
        }
 
-       rdev->dev.bus = &rio_bus_type;
-       rdev->dev.parent = &rio_bus;
+       rio_attach_device(rdev);
 
        device_initialize(&rdev->dev);
        rdev->dev.release = rio_release_dev;
@@ -1260,19 +1134,30 @@ static void rio_pw_enable(struct rio_mport *port, int enable)
 /**
  * rio_enum_mport- Start enumeration through a master port
  * @mport: Master port to send transactions
+ * @flags: Enumeration control flags
  *
  * Starts the enumeration process. If somebody has enumerated our
  * master port device, then give up. If not and we have an active
  * link, then start recursive peer enumeration. Returns %0 if
  * enumeration succeeds or %-EBUSY if enumeration fails.
  */
-int rio_enum_mport(struct rio_mport *mport)
+int rio_enum_mport(struct rio_mport *mport, u32 flags)
 {
        struct rio_net *net = NULL;
        int rc = 0;
 
        printk(KERN_INFO "RIO: enumerate master port %d, %s\n", mport->id,
               mport->name);
+
+       /*
+        * To avoid multiple start requests (repeat enumeration is not supported
+        * by this method) check if enumeration/discovery was performed for this
+        * mport: if mport was added into the list of mports for a net exit
+        * with error.
+        */
+       if (mport->nnode.next || mport->nnode.prev)
+               return -EBUSY;
+
        /* If somebody else enumerated our master port device, bail. */
        if (rio_enum_host(mport) < 0) {
                printk(KERN_INFO
@@ -1362,14 +1247,16 @@ static void rio_build_route_tables(struct rio_net *net)
 /**
  * rio_disc_mport- Start discovery through a master port
  * @mport: Master port to send transactions
+ * @flags: discovery control flags
  *
  * Starts the discovery process. If we have an active link,
- * then wait for the signal that enumeration is complete.
+ * then wait for the signal that enumeration is complete (if wait
+ * is allowed).
  * When enumeration completion is signaled, start recursive
  * peer discovery. Returns %0 if discovery succeeds or %-EBUSY
  * on failure.
  */
-int rio_disc_mport(struct rio_mport *mport)
+int rio_disc_mport(struct rio_mport *mport, u32 flags)
 {
        struct rio_net *net = NULL;
        unsigned long to_end;
@@ -1379,6 +1266,11 @@ int rio_disc_mport(struct rio_mport *mport)
 
        /* If master port has an active link, allocate net and discover peers */
        if (rio_mport_is_active(mport)) {
+               if (rio_enum_complete(mport))
+                       goto enum_done;
+               else if (flags & RIO_SCAN_ENUM_NO_WAIT)
+                       return -EAGAIN;
+
                pr_debug("RIO: wait for enumeration to complete...\n");
 
                to_end = jiffies + CONFIG_RAPIDIO_DISC_TIMEOUT * HZ;
@@ -1421,3 +1313,41 @@ enum_done:
 bail:
        return -EBUSY;
 }
+
+static struct rio_scan rio_scan_ops = {
+       .enumerate = rio_enum_mport,
+       .discover = rio_disc_mport,
+};
+
+static bool scan;
+module_param(scan, bool, 0);
+MODULE_PARM_DESC(scan, "Start RapidIO network enumeration/discovery "
+                       "(default = 0)");
+
+/**
+ * rio_basic_attach:
+ *
+ * When this enumeration/discovery method is loaded as a module this function
+ * registers its specific enumeration and discover routines for all available
+ * RapidIO mport devices. The "scan" command line parameter controls ability of
+ * the module to start RapidIO enumeration/discovery automatically.
+ *
+ * Returns 0 for success or -EIO if unable to register itself.
+ *
+ * This enumeration/discovery method cannot be unloaded and therefore does not
+ * provide a matching cleanup_module routine.
+ */
+
+static int __init rio_basic_attach(void)
+{
+       if (rio_register_scan(RIO_MPORT_ANY, &rio_scan_ops))
+               return -EIO;
+       if (scan)
+               rio_init_mports();
+       return 0;
+}
+
+late_initcall(rio_basic_attach);
+
+MODULE_DESCRIPTION("Basic RapidIO enumeration/discovery");
+MODULE_LICENSE("GPL");
index 4dbe360..66d4acd 100644 (file)
@@ -285,3 +285,48 @@ void rio_remove_sysfs_dev_files(struct rio_dev *rdev)
                        rdev->rswitch->sw_sysfs(rdev, RIO_SW_SYSFS_REMOVE);
        }
 }
+
+static ssize_t bus_scan_store(struct bus_type *bus, const char *buf,
+                               size_t count)
+{
+       long val;
+       struct rio_mport *port = NULL;
+       int rc;
+
+       if (kstrtol(buf, 0, &val) < 0)
+               return -EINVAL;
+
+       if (val == RIO_MPORT_ANY) {
+               rc = rio_init_mports();
+               goto exit;
+       }
+
+       if (val < 0 || val >= RIO_MAX_MPORTS)
+               return -EINVAL;
+
+       port = rio_find_mport((int)val);
+
+       if (!port) {
+               pr_debug("RIO: %s: mport_%d not available\n",
+                        __func__, (int)val);
+               return -EINVAL;
+       }
+
+       if (!port->nscan)
+               return -EINVAL;
+
+       if (port->host_deviceid >= 0)
+               rc = port->nscan->enumerate(port, 0);
+       else
+               rc = port->nscan->discover(port, RIO_SCAN_ENUM_NO_WAIT);
+exit:
+       if (!rc)
+               rc = count;
+
+       return rc;
+}
+
+struct bus_attribute rio_bus_attrs[] = {
+       __ATTR(scan, (S_IWUSR|S_IWGRP), NULL, bus_scan_store),
+       __ATTR_NULL
+};
index d553b5d..cb1c089 100644 (file)
 
 #include "rio.h"
 
+static LIST_HEAD(rio_devices);
+static DEFINE_SPINLOCK(rio_global_list_lock);
+
 static LIST_HEAD(rio_mports);
+static DEFINE_MUTEX(rio_mport_list_lock);
 static unsigned char next_portid;
 static DEFINE_SPINLOCK(rio_mmap_lock);
 
@@ -52,6 +56,32 @@ u16 rio_local_get_device_id(struct rio_mport *port)
        return (RIO_GET_DID(port->sys_size, result));
 }
 
+/**
+ * rio_add_device- Adds a RIO device to the device model
+ * @rdev: RIO device
+ *
+ * Adds the RIO device to the global device list and adds the RIO
+ * device to the RIO device list.  Creates the generic sysfs nodes
+ * for an RIO device.
+ */
+int rio_add_device(struct rio_dev *rdev)
+{
+       int err;
+
+       err = device_add(&rdev->dev);
+       if (err)
+               return err;
+
+       spin_lock(&rio_global_list_lock);
+       list_add_tail(&rdev->global_list, &rio_devices);
+       spin_unlock(&rio_global_list_lock);
+
+       rio_create_sysfs_dev_files(rdev);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rio_add_device);
+
 /**
  * rio_request_inb_mbox - request inbound mailbox service
  * @mport: RIO master port from which to allocate the mailbox resource
@@ -489,6 +519,7 @@ rio_mport_get_physefb(struct rio_mport *port, int local,
 
        return ext_ftr_ptr;
 }
+EXPORT_SYMBOL_GPL(rio_mport_get_physefb);
 
 /**
  * rio_get_comptag - Begin or continue searching for a RIO device by component tag
@@ -521,6 +552,7 @@ exit:
        spin_unlock(&rio_global_list_lock);
        return rdev;
 }
+EXPORT_SYMBOL_GPL(rio_get_comptag);
 
 /**
  * rio_set_port_lockout - Sets/clears LOCKOUT bit (RIO EM 1.3) for a switch port.
@@ -545,6 +577,107 @@ int rio_set_port_lockout(struct rio_dev *rdev, u32 pnum, int lock)
                                  regval);
        return 0;
 }
+EXPORT_SYMBOL_GPL(rio_set_port_lockout);
+
+/**
+ * rio_switch_init - Sets switch operations for a particular vendor switch
+ * @rdev: RIO device
+ * @do_enum: Enumeration/Discovery mode flag
+ *
+ * Searches the RIO switch ops table for known switch types. If the vid
+ * and did match a switch table entry, then call switch initialization
+ * routine to setup switch-specific routines.
+ */
+void rio_switch_init(struct rio_dev *rdev, int do_enum)
+{
+       struct rio_switch_ops *cur = __start_rio_switch_ops;
+       struct rio_switch_ops *end = __end_rio_switch_ops;
+
+       while (cur < end) {
+               if ((cur->vid == rdev->vid) && (cur->did == rdev->did)) {
+                       pr_debug("RIO: calling init routine for %s\n",
+                                rio_name(rdev));
+                       cur->init_hook(rdev, do_enum);
+                       break;
+               }
+               cur++;
+       }
+
+       if ((cur >= end) && (rdev->pef & RIO_PEF_STD_RT)) {
+               pr_debug("RIO: adding STD routing ops for %s\n",
+                       rio_name(rdev));
+               rdev->rswitch->add_entry = rio_std_route_add_entry;
+               rdev->rswitch->get_entry = rio_std_route_get_entry;
+               rdev->rswitch->clr_table = rio_std_route_clr_table;
+       }
+
+       if (!rdev->rswitch->add_entry || !rdev->rswitch->get_entry)
+               printk(KERN_ERR "RIO: missing routing ops for %s\n",
+                      rio_name(rdev));
+}
+EXPORT_SYMBOL_GPL(rio_switch_init);
+
+/**
+ * rio_enable_rx_tx_port - enable input receiver and output transmitter of
+ * given port
+ * @port: Master port associated with the RIO network
+ * @local: local=1 select local port otherwise a far device is reached
+ * @destid: Destination ID of the device to check host bit
+ * @hopcount: Number of hops to reach the target
+ * @port_num: Port (-number on switch) to enable on a far end device
+ *
+ * Returns 0 or 1 from on General Control Command and Status Register
+ * (EXT_PTR+0x3C)
+ */
+int rio_enable_rx_tx_port(struct rio_mport *port,
+                         int local, u16 destid,
+                         u8 hopcount, u8 port_num)
+{
+#ifdef CONFIG_RAPIDIO_ENABLE_RX_TX_PORTS
+       u32 regval;
+       u32 ext_ftr_ptr;
+
+       /*
+       * enable rx input tx output port
+       */
+       pr_debug("rio_enable_rx_tx_port(local = %d, destid = %d, hopcount = "
+                "%d, port_num = %d)\n", local, destid, hopcount, port_num);
+
+       ext_ftr_ptr = rio_mport_get_physefb(port, local, destid, hopcount);
+
+       if (local) {
+               rio_local_read_config_32(port, ext_ftr_ptr +
+                               RIO_PORT_N_CTL_CSR(0),
+                               &regval);
+       } else {
+               if (rio_mport_read_config_32(port, destid, hopcount,
+               ext_ftr_ptr + RIO_PORT_N_CTL_CSR(port_num), &regval) < 0)
+                       return -EIO;
+       }
+
+       if (regval & RIO_PORT_N_CTL_P_TYP_SER) {
+               /* serial */
+               regval = regval | RIO_PORT_N_CTL_EN_RX_SER
+                               | RIO_PORT_N_CTL_EN_TX_SER;
+       } else {
+               /* parallel */
+               regval = regval | RIO_PORT_N_CTL_EN_RX_PAR
+                               | RIO_PORT_N_CTL_EN_TX_PAR;
+       }
+
+       if (local) {
+               rio_local_write_config_32(port, ext_ftr_ptr +
+                                         RIO_PORT_N_CTL_CSR(0), regval);
+       } else {
+               if (rio_mport_write_config_32(port, destid, hopcount,
+                   ext_ftr_ptr + RIO_PORT_N_CTL_CSR(port_num), regval) < 0)
+                       return -EIO;
+       }
+#endif
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rio_enable_rx_tx_port);
+
 
 /**
  * rio_chk_dev_route - Validate route to the specified device.
@@ -610,6 +743,7 @@ rio_mport_chk_dev_access(struct rio_mport *mport, u16 destid, u8 hopcount)
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(rio_mport_chk_dev_access);
 
 /**
  * rio_chk_dev_access - Validate access to the specified device.
@@ -941,6 +1075,7 @@ rio_mport_get_efb(struct rio_mport *port, int local, u16 destid,
                return RIO_GET_BLOCK_ID(reg_val);
        }
 }
+EXPORT_SYMBOL_GPL(rio_mport_get_efb);
 
 /**
  * rio_mport_get_feature - query for devices' extended features
@@ -997,6 +1132,7 @@ rio_mport_get_feature(struct rio_mport * port, int local, u16 destid,
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(rio_mport_get_feature);
 
 /**
  * rio_get_asm - Begin or continue searching for a RIO device by vid/did/asm_vid/asm_did
@@ -1246,6 +1382,95 @@ EXPORT_SYMBOL_GPL(rio_dma_prep_slave_sg);
 
 #endif /* CONFIG_RAPIDIO_DMA_ENGINE */
 
+/**
+ * rio_find_mport - find RIO mport by its ID
+ * @mport_id: number (ID) of mport device
+ *
+ * Given a RIO mport number, the desired mport is located
+ * in the global list of mports. If the mport is found, a pointer to its
+ * data structure is returned.  If no mport is found, %NULL is returned.
+ */
+struct rio_mport *rio_find_mport(int mport_id)
+{
+       struct rio_mport *port;
+
+       mutex_lock(&rio_mport_list_lock);
+       list_for_each_entry(port, &rio_mports, node) {
+               if (port->id == mport_id)
+                       goto found;
+       }
+       port = NULL;
+found:
+       mutex_unlock(&rio_mport_list_lock);
+
+       return port;
+}
+
+/**
+ * rio_register_scan - enumeration/discovery method registration interface
+ * @mport_id: mport device ID for which fabric scan routine has to be set
+ *            (RIO_MPORT_ANY = set for all available mports)
+ * @scan_ops: enumeration/discovery control structure
+ *
+ * Assigns enumeration or discovery method to the specified mport device (or all
+ * available mports if RIO_MPORT_ANY is specified).
+ * Returns error if the mport already has an enumerator attached to it.
+ * In case of RIO_MPORT_ANY ignores ports with valid scan routines and returns
+ * an error if was unable to find at least one available mport.
+ */
+int rio_register_scan(int mport_id, struct rio_scan *scan_ops)
+{
+       struct rio_mport *port;
+       int rc = -EBUSY;
+
+       mutex_lock(&rio_mport_list_lock);
+       list_for_each_entry(port, &rio_mports, node) {
+               if (port->id == mport_id || mport_id == RIO_MPORT_ANY) {
+                       if (port->nscan && mport_id == RIO_MPORT_ANY)
+                               continue;
+                       else if (port->nscan)
+                               break;
+
+                       port->nscan = scan_ops;
+                       rc = 0;
+
+                       if (mport_id != RIO_MPORT_ANY)
+                               break;
+               }
+       }
+       mutex_unlock(&rio_mport_list_lock);
+
+       return rc;
+}
+EXPORT_SYMBOL_GPL(rio_register_scan);
+
+/**
+ * rio_unregister_scan - removes enumeration/discovery method from mport
+ * @mport_id: mport device ID for which fabric scan routine has to be
+ *            unregistered (RIO_MPORT_ANY = set for all available mports)
+ *
+ * Removes enumeration or discovery method assigned to the specified mport
+ * device (or all available mports if RIO_MPORT_ANY is specified).
+ */
+int rio_unregister_scan(int mport_id)
+{
+       struct rio_mport *port;
+
+       mutex_lock(&rio_mport_list_lock);
+       list_for_each_entry(port, &rio_mports, node) {
+               if (port->id == mport_id || mport_id == RIO_MPORT_ANY) {
+                       if (port->nscan)
+                               port->nscan = NULL;
+                       if (mport_id != RIO_MPORT_ANY)
+                               break;
+               }
+       }
+       mutex_unlock(&rio_mport_list_lock);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rio_unregister_scan);
+
 static void rio_fixup_device(struct rio_dev *dev)
 {
 }
@@ -1274,7 +1499,7 @@ static void disc_work_handler(struct work_struct *_work)
        work = container_of(_work, struct rio_disc_work, work);
        pr_debug("RIO: discovery work for mport %d %s\n",
                 work->mport->id, work->mport->name);
-       rio_disc_mport(work->mport);
+       work->mport->nscan->discover(work->mport, 0);
 }
 
 int rio_init_mports(void)
@@ -1290,12 +1515,15 @@ int rio_init_mports(void)
         * First, run enumerations and check if we need to perform discovery
         * on any of the registered mports.
         */
+       mutex_lock(&rio_mport_list_lock);
        list_for_each_entry(port, &rio_mports, node) {
-               if (port->host_deviceid >= 0)
-                       rio_enum_mport(port);
-               else
+               if (port->host_deviceid >= 0) {
+                       if (port->nscan)
+                               port->nscan->enumerate(port, 0);
+               } else
                        n++;
        }
+       mutex_unlock(&rio_mport_list_lock);
 
        if (!n)
                goto no_disc;
@@ -1322,14 +1550,16 @@ int rio_init_mports(void)
        }
 
        n = 0;
+       mutex_lock(&rio_mport_list_lock);
        list_for_each_entry(port, &rio_mports, node) {
-               if (port->host_deviceid < 0) {
+               if (port->host_deviceid < 0 && port->nscan) {
                        work[n].mport = port;
                        INIT_WORK(&work[n].work, disc_work_handler);
                        queue_work(rio_wq, &work[n].work);
                        n++;
                }
        }
+       mutex_unlock(&rio_mport_list_lock);
 
        flush_workqueue(rio_wq);
        pr_debug("RIO: destroy discovery workqueue\n");
@@ -1342,8 +1572,6 @@ no_disc:
        return 0;
 }
 
-device_initcall_sync(rio_init_mports);
-
 static int hdids[RIO_MAX_MPORTS + 1];
 
 static int rio_get_hdid(int index)
@@ -1371,7 +1599,10 @@ int rio_register_mport(struct rio_mport *port)
 
        port->id = next_portid++;
        port->host_deviceid = rio_get_hdid(port->id);
+       port->nscan = NULL;
+       mutex_lock(&rio_mport_list_lock);
        list_add_tail(&port->node, &rio_mports);
+       mutex_unlock(&rio_mport_list_lock);
        return 0;
 }
 
@@ -1386,3 +1617,4 @@ EXPORT_SYMBOL_GPL(rio_request_inb_mbox);
 EXPORT_SYMBOL_GPL(rio_release_inb_mbox);
 EXPORT_SYMBOL_GPL(rio_request_outb_mbox);
 EXPORT_SYMBOL_GPL(rio_release_outb_mbox);
+EXPORT_SYMBOL_GPL(rio_init_mports);
index b1af414..c14f864 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/rio.h>
 
 #define RIO_MAX_CHK_RETRY      3
+#define RIO_MPORT_ANY          (-1)
 
 /* Functions internal to the RIO core code */
 
@@ -27,8 +28,6 @@ extern u32 rio_mport_get_efb(struct rio_mport *port, int local, u16 destid,
 extern int rio_mport_chk_dev_access(struct rio_mport *mport, u16 destid,
                                    u8 hopcount);
 extern int rio_create_sysfs_dev_files(struct rio_dev *rdev);
-extern int rio_enum_mport(struct rio_mport *mport);
-extern int rio_disc_mport(struct rio_mport *mport);
 extern int rio_std_route_add_entry(struct rio_mport *mport, u16 destid,
                                   u8 hopcount, u16 table, u16 route_destid,
                                   u8 route_port);
@@ -39,10 +38,18 @@ extern int rio_std_route_clr_table(struct rio_mport *mport, u16 destid,
                                   u8 hopcount, u16 table);
 extern int rio_set_port_lockout(struct rio_dev *rdev, u32 pnum, int lock);
 extern struct rio_dev *rio_get_comptag(u32 comp_tag, struct rio_dev *from);
+extern int rio_add_device(struct rio_dev *rdev);
+extern void rio_switch_init(struct rio_dev *rdev, int do_enum);
+extern int rio_enable_rx_tx_port(struct rio_mport *port, int local, u16 destid,
+                                u8 hopcount, u8 port_num);
+extern int rio_register_scan(int mport_id, struct rio_scan *scan_ops);
+extern int rio_unregister_scan(int mport_id);
+extern void rio_attach_device(struct rio_dev *rdev);
+extern struct rio_mport *rio_find_mport(int mport_id);
 
 /* Structures internal to the RIO core code */
 extern struct device_attribute rio_dev_attrs[];
-extern spinlock_t rio_global_list_lock;
+extern struct bus_attribute rio_bus_attrs[];
 
 extern struct rio_switch_ops __start_rio_switch_ops[];
 extern struct rio_switch_ops __end_rio_switch_ops[];
index 6e50178..815d6df 100644 (file)
@@ -1539,7 +1539,10 @@ static void regulator_ena_gpio_free(struct regulator_dev *rdev)
 }
 
 /**
- * Balance enable_count of each GPIO and actual GPIO pin control.
+ * regulator_ena_gpio_ctrl - balance enable_count of each GPIO and actual GPIO pin control
+ * @rdev: regulator_dev structure
+ * @enable: enable GPIO at initial use?
+ *
  * GPIO is enabled in case of initial use. (enable_count is 0)
  * GPIO is disabled when it is not shared any more. (enable_count <= 1)
  */
@@ -2702,7 +2705,7 @@ EXPORT_SYMBOL_GPL(regulator_get_voltage);
 /**
  * regulator_set_current_limit - set regulator output current limit
  * @regulator: regulator source
- * @min_uA: Minimuum supported current in uA
+ * @min_uA: Minimum supported current in uA
  * @max_uA: Maximum supported current in uA
  *
  * Sets current sink to the desired output current. This can be set during
index 89bd2fa..ce89f78 100644 (file)
 static int power_state_active_cnt; /* will initialize to zero */
 static DEFINE_SPINLOCK(power_state_active_lock);
 
-int power_state_active_get(void)
-{
-       unsigned long flags;
-       int cnt;
-
-       spin_lock_irqsave(&power_state_active_lock, flags);
-       cnt = power_state_active_cnt;
-       spin_unlock_irqrestore(&power_state_active_lock, flags);
-
-       return cnt;
-}
-
 void power_state_active_enable(void)
 {
        unsigned long flags;
@@ -65,6 +53,18 @@ out:
 
 #ifdef CONFIG_REGULATOR_DEBUG
 
+static int power_state_active_get(void)
+{
+       unsigned long flags;
+       int cnt;
+
+       spin_lock_irqsave(&power_state_active_lock, flags);
+       cnt = power_state_active_cnt;
+       spin_unlock_irqrestore(&power_state_active_lock, flags);
+
+       return cnt;
+}
+
 static struct ux500_regulator_debug {
        struct dentry *dir;
        struct dentry *status_file;
index 92ceed0..3ae44ac 100644 (file)
@@ -840,7 +840,7 @@ static int palmas_regulators_probe(struct platform_device *pdev)
                        break;
                }
 
-               if ((id == PALMAS_REG_SMPS6) && (id == PALMAS_REG_SMPS8))
+               if ((id == PALMAS_REG_SMPS6) || (id == PALMAS_REG_SMPS8))
                        ramp_delay_support = true;
 
                if (ramp_delay_support) {
@@ -878,7 +878,7 @@ static int palmas_regulators_probe(struct platform_device *pdev)
                        pmic->desc[id].vsel_mask = SMPS10_VSEL;
                        pmic->desc[id].enable_reg =
                                        PALMAS_BASE_TO_REG(PALMAS_SMPS_BASE,
-                                                       PALMAS_SMPS10_STATUS);
+                                                       PALMAS_SMPS10_CTRL);
                        pmic->desc[id].enable_mask = SMPS10_BOOST_EN;
                        pmic->desc[id].min_uV = 3750000;
                        pmic->desc[id].uV_step = 1250000;
index 0c81915..b983813 100644 (file)
@@ -20,7 +20,6 @@ if RTC_CLASS
 config RTC_HCTOSYS
        bool "Set system time from RTC on startup and resume"
        default y
-       depends on !ALWAYS_USE_PERSISTENT_CLOCK
        help
          If you say yes here, the system time (wall clock) will be set using
          the value read from a specified RTC device. This is useful to avoid
@@ -29,7 +28,6 @@ config RTC_HCTOSYS
 config RTC_SYSTOHC
        bool "Set the RTC time based on NTP synchronization"
        default y
-       depends on !ALWAYS_USE_PERSISTENT_CLOCK
        help
          If you say yes here, the system time (wall clock) will be stored
          in the RTC specified by RTC_HCTOSYS_DEVICE approximately every 11
index 0eab77b..f296f3f 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/rtc.h>
 #include <linux/bcd.h>
 #include <linux/interrupt.h>
+#include <linux/spinlock.h>
 #include <linux/ioctl.h>
 #include <linux/completion.h>
 #include <linux/io.h>
 
 #define AT91_RTC_EPOCH         1900UL  /* just like arch/arm/common/rtctime.c */
 
+struct at91_rtc_config {
+       bool use_shadow_imr;
+};
+
+static const struct at91_rtc_config *at91_rtc_config;
 static DECLARE_COMPLETION(at91_rtc_updated);
 static unsigned int at91_alarm_year = AT91_RTC_EPOCH;
 static void __iomem *at91_rtc_regs;
 static int irq;
+static DEFINE_SPINLOCK(at91_rtc_lock);
+static u32 at91_rtc_shadow_imr;
+
+static void at91_rtc_write_ier(u32 mask)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&at91_rtc_lock, flags);
+       at91_rtc_shadow_imr |= mask;
+       at91_rtc_write(AT91_RTC_IER, mask);
+       spin_unlock_irqrestore(&at91_rtc_lock, flags);
+}
+
+static void at91_rtc_write_idr(u32 mask)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&at91_rtc_lock, flags);
+       at91_rtc_write(AT91_RTC_IDR, mask);
+       /*
+        * Register read back (of any RTC-register) needed to make sure
+        * IDR-register write has reached the peripheral before updating
+        * shadow mask.
+        *
+        * Note that there is still a possibility that the mask is updated
+        * before interrupts have actually been disabled in hardware. The only
+        * way to be certain would be to poll the IMR-register, which is is
+        * the very register we are trying to emulate. The register read back
+        * is a reasonable heuristic.
+        */
+       at91_rtc_read(AT91_RTC_SR);
+       at91_rtc_shadow_imr &= ~mask;
+       spin_unlock_irqrestore(&at91_rtc_lock, flags);
+}
+
+static u32 at91_rtc_read_imr(void)
+{
+       unsigned long flags;
+       u32 mask;
+
+       if (at91_rtc_config->use_shadow_imr) {
+               spin_lock_irqsave(&at91_rtc_lock, flags);
+               mask = at91_rtc_shadow_imr;
+               spin_unlock_irqrestore(&at91_rtc_lock, flags);
+       } else {
+               mask = at91_rtc_read(AT91_RTC_IMR);
+       }
+
+       return mask;
+}
 
 /*
  * Decode time/date into rtc_time structure
@@ -110,9 +166,9 @@ static int at91_rtc_settime(struct device *dev, struct rtc_time *tm)
        cr = at91_rtc_read(AT91_RTC_CR);
        at91_rtc_write(AT91_RTC_CR, cr | AT91_RTC_UPDCAL | AT91_RTC_UPDTIM);
 
-       at91_rtc_write(AT91_RTC_IER, AT91_RTC_ACKUPD);
+       at91_rtc_write_ier(AT91_RTC_ACKUPD);
        wait_for_completion(&at91_rtc_updated); /* wait for ACKUPD interrupt */
-       at91_rtc_write(AT91_RTC_IDR, AT91_RTC_ACKUPD);
+       at91_rtc_write_idr(AT91_RTC_ACKUPD);
 
        at91_rtc_write(AT91_RTC_TIMR,
                          bin2bcd(tm->tm_sec) << 0
@@ -144,7 +200,7 @@ static int at91_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
        tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year);
        tm->tm_year = at91_alarm_year - 1900;
 
-       alrm->enabled = (at91_rtc_read(AT91_RTC_IMR) & AT91_RTC_ALARM)
+       alrm->enabled = (at91_rtc_read_imr() & AT91_RTC_ALARM)
                        ? 1 : 0;
 
        dev_dbg(dev, "%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__,
@@ -169,7 +225,7 @@ static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
        tm.tm_min = alrm->time.tm_min;
        tm.tm_sec = alrm->time.tm_sec;
 
-       at91_rtc_write(AT91_RTC_IDR, AT91_RTC_ALARM);
+       at91_rtc_write_idr(AT91_RTC_ALARM);
        at91_rtc_write(AT91_RTC_TIMALR,
                  bin2bcd(tm.tm_sec) << 0
                | bin2bcd(tm.tm_min) << 8
@@ -182,7 +238,7 @@ static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
 
        if (alrm->enabled) {
                at91_rtc_write(AT91_RTC_SCCR, AT91_RTC_ALARM);
-               at91_rtc_write(AT91_RTC_IER, AT91_RTC_ALARM);
+               at91_rtc_write_ier(AT91_RTC_ALARM);
        }
 
        dev_dbg(dev, "%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__,
@@ -198,9 +254,9 @@ static int at91_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
 
        if (enabled) {
                at91_rtc_write(AT91_RTC_SCCR, AT91_RTC_ALARM);
-               at91_rtc_write(AT91_RTC_IER, AT91_RTC_ALARM);
+               at91_rtc_write_ier(AT91_RTC_ALARM);
        } else
-               at91_rtc_write(AT91_RTC_IDR, AT91_RTC_ALARM);
+               at91_rtc_write_idr(AT91_RTC_ALARM);
 
        return 0;
 }
@@ -209,7 +265,7 @@ static int at91_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
  */
 static int at91_rtc_proc(struct device *dev, struct seq_file *seq)
 {
-       unsigned long imr = at91_rtc_read(AT91_RTC_IMR);
+       unsigned long imr = at91_rtc_read_imr();
 
        seq_printf(seq, "update_IRQ\t: %s\n",
                        (imr & AT91_RTC_ACKUPD) ? "yes" : "no");
@@ -229,7 +285,7 @@ static irqreturn_t at91_rtc_interrupt(int irq, void *dev_id)
        unsigned int rtsr;
        unsigned long events = 0;
 
-       rtsr = at91_rtc_read(AT91_RTC_SR) & at91_rtc_read(AT91_RTC_IMR);
+       rtsr = at91_rtc_read(AT91_RTC_SR) & at91_rtc_read_imr();
        if (rtsr) {             /* this interrupt is shared!  Is it ours? */
                if (rtsr & AT91_RTC_ALARM)
                        events |= (RTC_AF | RTC_IRQF);
@@ -250,6 +306,43 @@ static irqreturn_t at91_rtc_interrupt(int irq, void *dev_id)
        return IRQ_NONE;                /* not handled */
 }
 
+static const struct at91_rtc_config at91rm9200_config = {
+};
+
+static const struct at91_rtc_config at91sam9x5_config = {
+       .use_shadow_imr = true,
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id at91_rtc_dt_ids[] = {
+       {
+               .compatible = "atmel,at91rm9200-rtc",
+               .data = &at91rm9200_config,
+       }, {
+               .compatible = "atmel,at91sam9x5-rtc",
+               .data = &at91sam9x5_config,
+       }, {
+               /* sentinel */
+       }
+};
+MODULE_DEVICE_TABLE(of, at91_rtc_dt_ids);
+#endif
+
+static const struct at91_rtc_config *
+at91_rtc_get_config(struct platform_device *pdev)
+{
+       const struct of_device_id *match;
+
+       if (pdev->dev.of_node) {
+               match = of_match_node(at91_rtc_dt_ids, pdev->dev.of_node);
+               if (!match)
+                       return NULL;
+               return (const struct at91_rtc_config *)match->data;
+       }
+
+       return &at91rm9200_config;
+}
+
 static const struct rtc_class_ops at91_rtc_ops = {
        .read_time      = at91_rtc_readtime,
        .set_time       = at91_rtc_settime,
@@ -268,6 +361,10 @@ static int __init at91_rtc_probe(struct platform_device *pdev)
        struct resource *regs;
        int ret = 0;
 
+       at91_rtc_config = at91_rtc_get_config(pdev);
+       if (!at91_rtc_config)
+               return -ENODEV;
+
        regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!regs) {
                dev_err(&pdev->dev, "no mmio resource defined\n");
@@ -290,7 +387,7 @@ static int __init at91_rtc_probe(struct platform_device *pdev)
        at91_rtc_write(AT91_RTC_MR, 0);         /* 24 hour mode */
 
        /* Disable all interrupts */
-       at91_rtc_write(AT91_RTC_IDR, AT91_RTC_ACKUPD | AT91_RTC_ALARM |
+       at91_rtc_write_idr(AT91_RTC_ACKUPD | AT91_RTC_ALARM |
                                        AT91_RTC_SECEV | AT91_RTC_TIMEV |
                                        AT91_RTC_CALEV);
 
@@ -335,7 +432,7 @@ static int __exit at91_rtc_remove(struct platform_device *pdev)
        struct rtc_device *rtc = platform_get_drvdata(pdev);
 
        /* Disable all interrupts */
-       at91_rtc_write(AT91_RTC_IDR, AT91_RTC_ACKUPD | AT91_RTC_ALARM |
+       at91_rtc_write_idr(AT91_RTC_ACKUPD | AT91_RTC_ALARM |
                                        AT91_RTC_SECEV | AT91_RTC_TIMEV |
                                        AT91_RTC_CALEV);
        free_irq(irq, pdev);
@@ -358,13 +455,13 @@ static int at91_rtc_suspend(struct device *dev)
        /* this IRQ is shared with DBGU and other hardware which isn't
         * necessarily doing PM like we are...
         */
-       at91_rtc_imr = at91_rtc_read(AT91_RTC_IMR)
+       at91_rtc_imr = at91_rtc_read_imr()
                        & (AT91_RTC_ALARM|AT91_RTC_SECEV);
        if (at91_rtc_imr) {
                if (device_may_wakeup(dev))
                        enable_irq_wake(irq);
                else
-                       at91_rtc_write(AT91_RTC_IDR, at91_rtc_imr);
+                       at91_rtc_write_idr(at91_rtc_imr);
        }
        return 0;
 }
@@ -375,7 +472,7 @@ static int at91_rtc_resume(struct device *dev)
                if (device_may_wakeup(dev))
                        disable_irq_wake(irq);
                else
-                       at91_rtc_write(AT91_RTC_IER, at91_rtc_imr);
+                       at91_rtc_write_ier(at91_rtc_imr);
        }
        return 0;
 }
@@ -383,12 +480,6 @@ static int at91_rtc_resume(struct device *dev)
 
 static SIMPLE_DEV_PM_OPS(at91_rtc_pm_ops, at91_rtc_suspend, at91_rtc_resume);
 
-static const struct of_device_id at91_rtc_dt_ids[] = {
-       { .compatible = "atmel,at91rm9200-rtc" },
-       { /* sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, at91_rtc_dt_ids);
-
 static struct platform_driver at91_rtc_driver = {
        .remove         = __exit_p(at91_rtc_remove),
        .driver         = {
index cc5bea9..f1cb706 100644 (file)
@@ -854,6 +854,9 @@ static int cmos_resume(struct device *dev)
                }
 
                spin_lock_irq(&rtc_lock);
+               if (device_may_wakeup(dev))
+                       hpet_rtc_timer_init();
+
                do {
                        CMOS_WRITE(tmp, RTC_CONTROL);
                        hpet_set_rtc_irq_bit(tmp & RTC_IRQMASK);
@@ -869,7 +872,6 @@ static int cmos_resume(struct device *dev)
                        rtc_update_irq(cmos->rtc, 1, mask);
                        tmp &= ~RTC_AIE;
                        hpet_mask_rtc_irq_bit(RTC_AIE);
-                       hpet_rtc_timer_init();
                } while (mask & RTC_AIE);
                spin_unlock_irq(&rtc_lock);
        }
index 48b6612..d5af7ba 100644 (file)
@@ -285,7 +285,7 @@ static int max8998_rtc_probe(struct platform_device *pdev)
                        info->irq, ret);
 
        dev_info(&pdev->dev, "RTC CHIP NAME: %s\n", pdev->id_entry->name);
-       if (pdata->rtc_delay) {
+       if (pdata && pdata->rtc_delay) {
                info->lp3974_bug_workaround = true;
                dev_warn(&pdev->dev, "LP3974 with RTC REGERR option."
                                " RTC updates will be extremely slow.\n");
index f5dfb6e..d592e2f 100644 (file)
@@ -234,11 +234,6 @@ static int __init nuc900_rtc_probe(struct platform_device *pdev)
                return -ENOMEM;
        }
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(&pdev->dev, "platform_get_resource failed\n");
-               return -ENXIO;
-       }
-
        nuc900_rtc->rtc_reg = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(nuc900_rtc->rtc_reg))
                return PTR_ERR(nuc900_rtc->rtc_reg);
index 4e1bdb8..b0ba3fc 100644 (file)
@@ -347,11 +347,6 @@ static int __init omap_rtc_probe(struct platform_device *pdev)
        }
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               pr_debug("%s: RTC resource data missing\n", pdev->name);
-               return -ENOENT;
-       }
-
        rtc_base = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(rtc_base))
                return PTR_ERR(rtc_base);
index 8900ea7..0f0609b 100644 (file)
@@ -306,7 +306,7 @@ static int pl031_remove(struct amba_device *adev)
        struct pl031_local *ldata = dev_get_drvdata(&adev->dev);
 
        amba_set_drvdata(adev, NULL);
-       free_irq(adev->irq[0], ldata->rtc);
+       free_irq(adev->irq[0], ldata);
        rtc_device_unregister(ldata->rtc);
        iounmap(ldata->base);
        kfree(ldata);
index 14040b2..0b495e8 100644 (file)
@@ -477,11 +477,6 @@ static int s3c_rtc_probe(struct platform_device *pdev)
        /* get the memory region */
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (res == NULL) {
-               dev_err(&pdev->dev, "failed to get memory region resource\n");
-               return -ENOENT;
-       }
-
        s3c_rtc_base = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(s3c_rtc_base))
                return PTR_ERR(s3c_rtc_base);
index a34315d..76af92a 100644 (file)
@@ -322,12 +322,6 @@ static int __init tegra_rtc_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(&pdev->dev,
-                       "Unable to allocate resources for device.\n");
-               return -EBUSY;
-       }
-
        info->rtc_base = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(info->rtc_base))
                return PTR_ERR(info->rtc_base);
index 459c2ff..426901c 100644 (file)
@@ -273,6 +273,8 @@ static int tps6586x_rtc_probe(struct platform_device *pdev)
                return ret;
        }
 
+       device_init_wakeup(&pdev->dev, 1);
+
        platform_set_drvdata(pdev, rtc);
        rtc->rtc = devm_rtc_device_register(&pdev->dev, dev_name(&pdev->dev),
                                       &tps6586x_rtc_ops, THIS_MODULE);
@@ -292,7 +294,6 @@ static int tps6586x_rtc_probe(struct platform_device *pdev)
                goto fail_rtc_register;
        }
        disable_irq(rtc->irq);
-       device_set_wakeup_capable(&pdev->dev, 1);
        return 0;
 
 fail_rtc_register:
index 8751a52..b2eab34 100644 (file)
@@ -524,6 +524,7 @@ static int twl_rtc_probe(struct platform_device *pdev)
        }
 
        platform_set_drvdata(pdev, rtc);
+       device_init_wakeup(&pdev->dev, 1);
        return 0;
 
 out2:
index 4361d97..d72a921 100644 (file)
@@ -3440,8 +3440,16 @@ void dasd_generic_path_event(struct ccw_device *cdev, int *path_event)
                        device->path_data.opm &= ~eventlpm;
                        device->path_data.ppm &= ~eventlpm;
                        device->path_data.npm &= ~eventlpm;
-                       if (oldopm && !device->path_data.opm)
-                               dasd_generic_last_path_gone(device);
+                       if (oldopm && !device->path_data.opm) {
+                               dev_warn(&device->cdev->dev,
+                                        "No verified channel paths remain "
+                                        "for the device\n");
+                               DBF_DEV_EVENT(DBF_WARNING, device,
+                                             "%s", "last verified path gone");
+                               dasd_eer_write(device, NULL, DASD_EER_NOPATH);
+                               dasd_device_set_stop_bits(device,
+                                                         DASD_STOPPED_DC_WAIT);
+                       }
                }
                if (path_event[chp] & PE_PATH_AVAILABLE) {
                        device->path_data.opm &= ~eventlpm;
index 690c333..464dd29 100644 (file)
@@ -343,6 +343,7 @@ static int __init xpram_setup_blkdev(void)
                        put_disk(xpram_disks[i]);
                        goto out;
                }
+               queue_flag_set_unlocked(QUEUE_FLAG_NONROT, xpram_queues[i]);
                blk_queue_make_request(xpram_queues[i], xpram_make_request);
                blk_queue_logical_block_size(xpram_queues[i], 4096);
        }
index 21fabc6..6c440d4 100644 (file)
@@ -352,12 +352,48 @@ static ssize_t chp_shared_show(struct device *dev,
 
 static DEVICE_ATTR(shared, 0444, chp_shared_show, NULL);
 
+static ssize_t chp_chid_show(struct device *dev, struct device_attribute *attr,
+                            char *buf)
+{
+       struct channel_path *chp = to_channelpath(dev);
+       ssize_t rc;
+
+       mutex_lock(&chp->lock);
+       if (chp->desc_fmt1.flags & 0x10)
+               rc = sprintf(buf, "%04x\n", chp->desc_fmt1.chid);
+       else
+               rc = 0;
+       mutex_unlock(&chp->lock);
+
+       return rc;
+}
+static DEVICE_ATTR(chid, 0444, chp_chid_show, NULL);
+
+static ssize_t chp_chid_external_show(struct device *dev,
+                                     struct device_attribute *attr, char *buf)
+{
+       struct channel_path *chp = to_channelpath(dev);
+       ssize_t rc;
+
+       mutex_lock(&chp->lock);
+       if (chp->desc_fmt1.flags & 0x10)
+               rc = sprintf(buf, "%x\n", chp->desc_fmt1.flags & 0x8 ? 1 : 0);
+       else
+               rc = 0;
+       mutex_unlock(&chp->lock);
+
+       return rc;
+}
+static DEVICE_ATTR(chid_external, 0444, chp_chid_external_show, NULL);
+
 static struct attribute *chp_attrs[] = {
        &dev_attr_status.attr,
        &dev_attr_configure.attr,
        &dev_attr_type.attr,
        &dev_attr_cmg.attr,
        &dev_attr_shared.attr,
+       &dev_attr_chid.attr,
+       &dev_attr_chid_external.attr,
        NULL,
 };
 static struct attribute_group chp_attr_group = {
index 349d5fc..e7ef2a6 100644 (file)
@@ -43,7 +43,9 @@ struct channel_path_desc_fmt1 {
        u8 chpid;
        u32:24;
        u8 chpp;
-       u32 unused[3];
+       u32 unused[2];
+       u16 chid;
+       u32:16;
        u16 mdc;
        u16:13;
        u8 r:1;
index db95c54..86af29f 100644 (file)
@@ -1353,6 +1353,8 @@ config SCSI_LPFC
        tristate "Emulex LightPulse Fibre Channel Support"
        depends on PCI && SCSI
        select SCSI_FC_ATTRS
+       select GENERIC_CSUM
+       select CRC_T10DIF
        help
           This lpfc driver supports the Emulex LightPulse
           Family of Fibre Channel PCI host adapters.
index 64136c5..3307238 100644 (file)
@@ -84,7 +84,7 @@ static void asd_set_ddb_type(struct domain_device *dev)
        struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha;
        int ddb = (int) (unsigned long) dev->lldd_dev;
 
-       if (dev->dev_type == SATA_PM_PORT)
+       if (dev->dev_type == SAS_SATA_PM_PORT)
                asd_ddbsite_write_byte(asd_ha,ddb, DDB_TYPE, DDB_TYPE_PM_PORT);
        else if (dev->tproto)
                asd_ddbsite_write_byte(asd_ha,ddb, DDB_TYPE, DDB_TYPE_TARGET);
@@ -116,7 +116,7 @@ void asd_set_dmamode(struct domain_device *dev)
        int ddb = (int) (unsigned long) dev->lldd_dev;
        u32 qdepth = 0;
 
-       if (dev->dev_type == SATA_DEV || dev->dev_type == SATA_PM_PORT) {
+       if (dev->dev_type == SAS_SATA_DEV || dev->dev_type == SAS_SATA_PM_PORT) {
                if (ata_id_has_ncq(ata_dev->id))
                        qdepth = ata_id_queue_depth(ata_dev->id);
                asd_ddbsite_write_dword(asd_ha, ddb, SATA_TAG_ALLOC_MASK,
@@ -140,8 +140,8 @@ static int asd_init_sata(struct domain_device *dev)
        int ddb = (int) (unsigned long) dev->lldd_dev;
 
        asd_ddbsite_write_word(asd_ha, ddb, ATA_CMD_SCBPTR, 0xFFFF);
-       if (dev->dev_type == SATA_DEV || dev->dev_type == SATA_PM ||
-           dev->dev_type == SATA_PM_PORT) {
+       if (dev->dev_type == SAS_SATA_DEV || dev->dev_type == SAS_SATA_PM ||
+           dev->dev_type == SAS_SATA_PM_PORT) {
                struct dev_to_host_fis *fis = (struct dev_to_host_fis *)
                        dev->frame_rcvd;
                asd_ddbsite_write_byte(asd_ha, ddb, SATA_STATUS, fis->status);
@@ -174,7 +174,7 @@ static int asd_init_target_ddb(struct domain_device *dev)
        asd_ddbsite_write_byte(asd_ha, ddb, CONN_MASK, dev->port->phy_mask);
        if (dev->port->oob_mode != SATA_OOB_MODE) {
                flags |= OPEN_REQUIRED;
-               if ((dev->dev_type == SATA_DEV) ||
+               if ((dev->dev_type == SAS_SATA_DEV) ||
                    (dev->tproto & SAS_PROTOCOL_STP)) {
                        struct smp_resp *rps_resp = &dev->sata_dev.rps_resp;
                        if (rps_resp->frame_type == SMP_RESPONSE &&
@@ -188,8 +188,8 @@ static int asd_init_target_ddb(struct domain_device *dev)
                } else {
                        flags |= CONCURRENT_CONN_SUPP;
                        if (!dev->parent &&
-                           (dev->dev_type == EDGE_DEV ||
-                            dev->dev_type == FANOUT_DEV))
+                           (dev->dev_type == SAS_EDGE_EXPANDER_DEVICE ||
+                            dev->dev_type == SAS_FANOUT_EXPANDER_DEVICE))
                                asd_ddbsite_write_byte(asd_ha, ddb, MAX_CCONN,
                                                       4);
                        else
@@ -198,7 +198,7 @@ static int asd_init_target_ddb(struct domain_device *dev)
                        asd_ddbsite_write_byte(asd_ha, ddb, NUM_CTX, 1);
                }
        }
-       if (dev->dev_type == SATA_PM)
+       if (dev->dev_type == SAS_SATA_PM)
                flags |= SATA_MULTIPORT;
        asd_ddbsite_write_byte(asd_ha, ddb, DDB_TARG_FLAGS, flags);
 
@@ -211,7 +211,7 @@ static int asd_init_target_ddb(struct domain_device *dev)
        asd_ddbsite_write_word(asd_ha, ddb, SEND_QUEUE_TAIL, 0xFFFF);
        asd_ddbsite_write_word(asd_ha, ddb, SISTER_DDB, 0xFFFF);
 
-       if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) {
+       if (dev->dev_type == SAS_SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) {
                i = asd_init_sata(dev);
                if (i < 0) {
                        asd_free_ddb(asd_ha, ddb);
@@ -219,7 +219,7 @@ static int asd_init_target_ddb(struct domain_device *dev)
                }
        }
 
-       if (dev->dev_type == SAS_END_DEV) {
+       if (dev->dev_type == SAS_END_DEVICE) {
                struct sas_end_device *rdev = rphy_to_end_device(dev->rphy);
                if (rdev->I_T_nexus_loss_timeout > 0)
                        asd_ddbsite_write_word(asd_ha, ddb, ITNL_TIMEOUT,
@@ -328,10 +328,10 @@ int asd_dev_found(struct domain_device *dev)
 
        spin_lock_irqsave(&asd_ha->hw_prof.ddb_lock, flags);
        switch (dev->dev_type) {
-       case SATA_PM:
+       case SAS_SATA_PM:
                res = asd_init_sata_pm_ddb(dev);
                break;
-       case SATA_PM_PORT:
+       case SAS_SATA_PM_PORT:
                res = asd_init_sata_pm_port_ddb(dev);
                break;
        default:
index 81b736c..4df867e 100644 (file)
@@ -74,7 +74,7 @@ static void asd_init_phy_identify(struct asd_phy *phy)
 
        memset(phy->identify_frame, 0, sizeof(*phy->identify_frame));
 
-       phy->identify_frame->dev_type = SAS_END_DEV;
+       phy->identify_frame->dev_type = SAS_END_DEVICE;
        if (phy->sas_phy.role & PHY_ROLE_INITIATOR)
                phy->identify_frame->initiator_bits = phy->sas_phy.iproto;
        if (phy->sas_phy.role & PHY_ROLE_TARGET)
index cf90409..d4c35df 100644 (file)
@@ -184,7 +184,7 @@ int asd_I_T_nexus_reset(struct domain_device *dev)
        struct sas_phy *phy = sas_get_local_phy(dev);
        /* Standard mandates link reset for ATA  (type 0) and
         * hard reset for SSP (type 1) */
-       int reset_type = (dev->dev_type == SATA_DEV ||
+       int reset_type = (dev->dev_type == SAS_SATA_DEV ||
                          (dev->tproto & SAS_PROTOCOL_STP)) ? 0 : 1;
 
        asd_clear_nexus_I_T(dev, NEXUS_PHASE_PRE);
index f1733df..777e7c0 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2005 - 2012 Emulex
+ * Copyright (C) 2005 - 2013 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
index 5c87768..e66aa7c 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2005 - 2012 Emulex
+ * Copyright (C) 2005 - 2013 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -155,6 +155,7 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba,
        uint16_t status = 0, addl_status = 0, wrb_num = 0;
        struct be_mcc_wrb *temp_wrb;
        struct be_cmd_req_hdr *ioctl_hdr;
+       struct be_cmd_resp_hdr *ioctl_resp_hdr;
        struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;
 
        if (beiscsi_error(phba))
@@ -204,6 +205,12 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba,
                            ioctl_hdr->subsystem,
                            ioctl_hdr->opcode,
                            status, addl_status);
+
+               if (status == MCC_STATUS_INSUFFICIENT_BUFFER) {
+                       ioctl_resp_hdr = (struct be_cmd_resp_hdr *) ioctl_hdr;
+                       if (ioctl_resp_hdr->response_length)
+                               goto release_mcc_tag;
+               }
                rc = -EAGAIN;
        }
 
@@ -267,6 +274,7 @@ static int be_mcc_compl_process(struct be_ctrl_info *ctrl,
        struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
        struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev);
        struct be_cmd_req_hdr *hdr = embedded_payload(wrb);
+       struct be_cmd_resp_hdr *resp_hdr;
 
        be_dws_le_to_cpu(compl, 4);
 
@@ -284,6 +292,11 @@ static int be_mcc_compl_process(struct be_ctrl_info *ctrl,
                            hdr->subsystem, hdr->opcode,
                            compl_status, extd_status);
 
+               if (compl_status == MCC_STATUS_INSUFFICIENT_BUFFER) {
+                       resp_hdr = (struct be_cmd_resp_hdr *) hdr;
+                       if (resp_hdr->response_length)
+                               return 0;
+               }
                return -EBUSY;
        }
        return 0;
@@ -335,30 +348,26 @@ static void be2iscsi_fail_session(struct iscsi_cls_session *cls_session)
 void beiscsi_async_link_state_process(struct beiscsi_hba *phba,
                struct be_async_event_link_state *evt)
 {
-       switch (evt->port_link_status) {
-       case ASYNC_EVENT_LINK_DOWN:
+       if ((evt->port_link_status == ASYNC_EVENT_LINK_DOWN) ||
+           ((evt->port_link_status & ASYNC_EVENT_LOGICAL) &&
+            (evt->port_fault != BEISCSI_PHY_LINK_FAULT_NONE))) {
+               phba->state = BE_ADAPTER_LINK_DOWN;
+
                beiscsi_log(phba, KERN_ERR,
                            BEISCSI_LOG_CONFIG | BEISCSI_LOG_INIT,
-                           "BC_%d : Link Down on Physical Port %d\n",
+                           "BC_%d : Link Down on Port %d\n",
                            evt->physical_port);
 
-               phba->state |= BE_ADAPTER_LINK_DOWN;
                iscsi_host_for_each_session(phba->shost,
                                            be2iscsi_fail_session);
-               break;
-       case ASYNC_EVENT_LINK_UP:
+       } else if ((evt->port_link_status & ASYNC_EVENT_LINK_UP) ||
+                   ((evt->port_link_status & ASYNC_EVENT_LOGICAL) &&
+                    (evt->port_fault == BEISCSI_PHY_LINK_FAULT_NONE))) {
                phba->state = BE_ADAPTER_UP;
+
                beiscsi_log(phba, KERN_ERR,
                            BEISCSI_LOG_CONFIG | BEISCSI_LOG_INIT,
-                           "BC_%d : Link UP on Physical Port %d\n",
-                           evt->physical_port);
-               break;
-       default:
-               beiscsi_log(phba, KERN_ERR,
-                           BEISCSI_LOG_CONFIG | BEISCSI_LOG_INIT,
-                           "BC_%d : Unexpected Async Notification %d on"
-                           "Physical Port %d\n",
-                           evt->port_link_status,
+                           "BC_%d : Link UP on Port %d\n",
                            evt->physical_port);
        }
 }
@@ -479,7 +488,7 @@ static int be_mbox_db_ready_wait(struct be_ctrl_info *ctrl)
 {
        void __iomem *db = ctrl->db + MPU_MAILBOX_DB_OFFSET;
        struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev);
-       int wait = 0;
+       uint32_t wait = 0;
        u32 ready;
 
        do {
@@ -527,6 +536,10 @@ int be_mbox_notify(struct be_ctrl_info *ctrl)
        struct be_mcc_compl *compl = &mbox->compl;
        struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev);
 
+       status = be_mbox_db_ready_wait(ctrl);
+       if (status)
+               return status;
+
        val &= ~MPU_MAILBOX_DB_RDY_MASK;
        val |= MPU_MAILBOX_DB_HI_MASK;
        val |= (upper_32_bits(mbox_mem->dma) >> 2) << 2;
@@ -580,6 +593,10 @@ static int be_mbox_notify_wait(struct beiscsi_hba *phba)
        struct be_mcc_compl *compl = &mbox->compl;
        struct be_ctrl_info *ctrl = &phba->ctrl;
 
+       status = be_mbox_db_ready_wait(ctrl);
+       if (status)
+               return status;
+
        val |= MPU_MAILBOX_DB_HI_MASK;
        /* at bits 2 - 31 place mbox dma addr msb bits 34 - 63 */
        val |= (upper_32_bits(mbox_mem->dma) >> 2) << 2;
@@ -732,6 +749,16 @@ int beiscsi_cmd_eq_create(struct be_ctrl_info *ctrl,
        return status;
 }
 
+/**
+ * be_cmd_fw_initialize()- Initialize FW
+ * @ctrl: Pointer to function control structure
+ *
+ * Send FW initialize pattern for the function.
+ *
+ * return
+ * Success: 0
+ * Failure: Non-Zero value
+ **/
 int be_cmd_fw_initialize(struct be_ctrl_info *ctrl)
 {
        struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
@@ -762,6 +789,47 @@ int be_cmd_fw_initialize(struct be_ctrl_info *ctrl)
        return status;
 }
 
+/**
+ * be_cmd_fw_uninit()- Uinitialize FW
+ * @ctrl: Pointer to function control structure
+ *
+ * Send FW uninitialize pattern for the function
+ *
+ * return
+ * Success: 0
+ * Failure: Non-Zero value
+ **/
+int be_cmd_fw_uninit(struct be_ctrl_info *ctrl)
+{
+       struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
+       struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev);
+       int status;
+       u8 *endian_check;
+
+       spin_lock(&ctrl->mbox_lock);
+       memset(wrb, 0, sizeof(*wrb));
+
+       endian_check = (u8 *) wrb;
+       *endian_check++ = 0xFF;
+       *endian_check++ = 0xAA;
+       *endian_check++ = 0xBB;
+       *endian_check++ = 0xFF;
+       *endian_check++ = 0xFF;
+       *endian_check++ = 0xCC;
+       *endian_check++ = 0xDD;
+       *endian_check = 0xFF;
+
+       be_dws_cpu_to_le(wrb, sizeof(*wrb));
+
+       status = be_mbox_notify(ctrl);
+       if (status)
+               beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
+                           "BC_%d : be_cmd_fw_uninit Failed\n");
+
+       spin_unlock(&ctrl->mbox_lock);
+       return status;
+}
+
 int beiscsi_cmd_cq_create(struct be_ctrl_info *ctrl,
                          struct be_queue_info *cq, struct be_queue_info *eq,
                          bool sol_evts, bool no_delay, int coalesce_wm)
@@ -783,20 +851,7 @@ int beiscsi_cmd_cq_create(struct be_ctrl_info *ctrl,
                        OPCODE_COMMON_CQ_CREATE, sizeof(*req));
 
        req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
-       if (chip_skh_r(ctrl->pdev)) {
-               req->hdr.version = MBX_CMD_VER2;
-               req->page_size = 1;
-               AMAP_SET_BITS(struct amap_cq_context_v2, coalescwm,
-                             ctxt, coalesce_wm);
-               AMAP_SET_BITS(struct amap_cq_context_v2, nodelay,
-                             ctxt, no_delay);
-               AMAP_SET_BITS(struct amap_cq_context_v2, count, ctxt,
-                             __ilog2_u32(cq->len / 256));
-               AMAP_SET_BITS(struct amap_cq_context_v2, valid, ctxt, 1);
-               AMAP_SET_BITS(struct amap_cq_context_v2, eventable, ctxt, 1);
-               AMAP_SET_BITS(struct amap_cq_context_v2, eqid, ctxt, eq->id);
-               AMAP_SET_BITS(struct amap_cq_context_v2, armed, ctxt, 1);
-       } else {
+       if (is_chip_be2_be3r(phba)) {
                AMAP_SET_BITS(struct amap_cq_context, coalescwm,
                              ctxt, coalesce_wm);
                AMAP_SET_BITS(struct amap_cq_context, nodelay, ctxt, no_delay);
@@ -809,6 +864,19 @@ int beiscsi_cmd_cq_create(struct be_ctrl_info *ctrl,
                AMAP_SET_BITS(struct amap_cq_context, armed, ctxt, 1);
                AMAP_SET_BITS(struct amap_cq_context, func, ctxt,
                              PCI_FUNC(ctrl->pdev->devfn));
+       } else {
+               req->hdr.version = MBX_CMD_VER2;
+               req->page_size = 1;
+               AMAP_SET_BITS(struct amap_cq_context_v2, coalescwm,
+                             ctxt, coalesce_wm);
+               AMAP_SET_BITS(struct amap_cq_context_v2, nodelay,
+                             ctxt, no_delay);
+               AMAP_SET_BITS(struct amap_cq_context_v2, count, ctxt,
+                             __ilog2_u32(cq->len / 256));
+               AMAP_SET_BITS(struct amap_cq_context_v2, valid, ctxt, 1);
+               AMAP_SET_BITS(struct amap_cq_context_v2, eventable, ctxt, 1);
+               AMAP_SET_BITS(struct amap_cq_context_v2, eqid, ctxt, eq->id);
+               AMAP_SET_BITS(struct amap_cq_context_v2, armed, ctxt, 1);
        }
 
        be_dws_cpu_to_le(ctxt, sizeof(req->context));
@@ -949,6 +1017,7 @@ int be_cmd_create_default_pdu_queue(struct be_ctrl_info *ctrl,
        struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
        struct be_defq_create_req *req = embedded_payload(wrb);
        struct be_dma_mem *q_mem = &dq->dma_mem;
+       struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev);
        void *ctxt = &req->context;
        int status;
 
@@ -961,17 +1030,36 @@ int be_cmd_create_default_pdu_queue(struct be_ctrl_info *ctrl,
                           OPCODE_COMMON_ISCSI_DEFQ_CREATE, sizeof(*req));
 
        req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size);
-       AMAP_SET_BITS(struct amap_be_default_pdu_context, rx_pdid, ctxt, 0);
-       AMAP_SET_BITS(struct amap_be_default_pdu_context, rx_pdid_valid, ctxt,
-                     1);
-       AMAP_SET_BITS(struct amap_be_default_pdu_context, pci_func_id, ctxt,
-                     PCI_FUNC(ctrl->pdev->devfn));
-       AMAP_SET_BITS(struct amap_be_default_pdu_context, ring_size, ctxt,
-                     be_encoded_q_len(length / sizeof(struct phys_addr)));
-       AMAP_SET_BITS(struct amap_be_default_pdu_context, default_buffer_size,
-                     ctxt, entry_size);
-       AMAP_SET_BITS(struct amap_be_default_pdu_context, cq_id_recv, ctxt,
-                     cq->id);
+
+       if (is_chip_be2_be3r(phba)) {
+               AMAP_SET_BITS(struct amap_be_default_pdu_context,
+                             rx_pdid, ctxt, 0);
+               AMAP_SET_BITS(struct amap_be_default_pdu_context,
+                             rx_pdid_valid, ctxt, 1);
+               AMAP_SET_BITS(struct amap_be_default_pdu_context,
+                             pci_func_id, ctxt, PCI_FUNC(ctrl->pdev->devfn));
+               AMAP_SET_BITS(struct amap_be_default_pdu_context,
+                             ring_size, ctxt,
+                             be_encoded_q_len(length /
+                             sizeof(struct phys_addr)));
+               AMAP_SET_BITS(struct amap_be_default_pdu_context,
+                             default_buffer_size, ctxt, entry_size);
+               AMAP_SET_BITS(struct amap_be_default_pdu_context,
+                             cq_id_recv, ctxt, cq->id);
+       } else {
+               AMAP_SET_BITS(struct amap_default_pdu_context_ext,
+                             rx_pdid, ctxt, 0);
+               AMAP_SET_BITS(struct amap_default_pdu_context_ext,
+                             rx_pdid_valid, ctxt, 1);
+               AMAP_SET_BITS(struct amap_default_pdu_context_ext,
+                             ring_size, ctxt,
+                             be_encoded_q_len(length /
+                             sizeof(struct phys_addr)));
+               AMAP_SET_BITS(struct amap_default_pdu_context_ext,
+                             default_buffer_size, ctxt, entry_size);
+               AMAP_SET_BITS(struct amap_default_pdu_context_ext,
+                             cq_id_recv, ctxt, cq->id);
+       }
 
        be_dws_cpu_to_le(ctxt, sizeof(req->context));
 
index 23397d5..9907308 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2005 - 2012 Emulex
+ * Copyright (C) 2005 - 2013 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -52,6 +52,10 @@ struct be_mcc_wrb {
 
 /* Completion Status */
 #define MCC_STATUS_SUCCESS 0x0
+#define MCC_STATUS_FAILED 0x1
+#define MCC_STATUS_ILLEGAL_REQUEST 0x2
+#define MCC_STATUS_ILLEGAL_FIELD 0x3
+#define MCC_STATUS_INSUFFICIENT_BUFFER 0x4
 
 #define CQE_STATUS_COMPL_MASK 0xFFFF
 #define CQE_STATUS_COMPL_SHIFT 0       /* bits 0 - 15 */
@@ -118,7 +122,8 @@ struct be_async_event_trailer {
 
 enum {
        ASYNC_EVENT_LINK_DOWN = 0x0,
-       ASYNC_EVENT_LINK_UP = 0x1
+       ASYNC_EVENT_LINK_UP = 0x1,
+       ASYNC_EVENT_LOGICAL = 0x2
 };
 
 /**
@@ -130,6 +135,9 @@ struct be_async_event_link_state {
        u8 port_link_status;
        u8 port_duplex;
        u8 port_speed;
+#define BEISCSI_PHY_LINK_FAULT_NONE    0x00
+#define BEISCSI_PHY_LINK_FAULT_LOCAL   0x01
+#define BEISCSI_PHY_LINK_FAULT_REMOTE  0x02
        u8 port_fault;
        u8 rsvd0[7];
        struct be_async_event_trailer trailer;
@@ -697,6 +705,7 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba,
                        uint32_t tag, struct be_mcc_wrb **wrb, void *cmd_va);
 /*ISCSI Functuions */
 int be_cmd_fw_initialize(struct be_ctrl_info *ctrl);
+int be_cmd_fw_uninit(struct be_ctrl_info *ctrl);
 
 struct be_mcc_wrb *wrb_from_mbox(struct be_dma_mem *mbox_mem);
 struct be_mcc_wrb *wrb_from_mccq(struct beiscsi_hba *phba);
@@ -751,6 +760,18 @@ struct amap_be_default_pdu_context {
        u8 rsvd4[32];           /* dword 3 */
 } __packed;
 
+struct amap_default_pdu_context_ext {
+       u8 rsvd0[16];   /* dword 0 */
+       u8 ring_size[4];    /* dword 0 */
+       u8 rsvd1[12];   /* dword 0 */
+       u8 rsvd2[22];   /* dword 1 */
+       u8 rx_pdid[9];  /* dword 1 */
+       u8 rx_pdid_valid;   /* dword 1 */
+       u8 default_buffer_size[16]; /* dword 2 */
+       u8 cq_id_recv[16];  /* dword 2 */
+       u8 rsvd3[32];   /* dword 3 */
+} __packed;
+
 struct be_defq_create_req {
        struct be_cmd_req_hdr hdr;
        u16 num_pages;
@@ -896,7 +917,7 @@ struct amap_it_dmsg_cqe_v2 {
  * stack to notify the
  * controller of a posted Work Request Block
  */
-#define DB_WRB_POST_CID_MASK           0x3FF   /* bits 0 - 9 */
+#define DB_WRB_POST_CID_MASK           0xFFFF  /* bits 0 - 16 */
 #define DB_DEF_PDU_WRB_INDEX_MASK      0xFF    /* bits 0 - 9 */
 
 #define DB_DEF_PDU_WRB_INDEX_SHIFT     16
index 9014690..ef36be0 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2005 - 2012 Emulex
+ * Copyright (C) 2005 - 2013 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -161,7 +161,9 @@ static int beiscsi_bindconn_cid(struct beiscsi_hba *phba,
                                struct beiscsi_conn *beiscsi_conn,
                                unsigned int cid)
 {
-       if (phba->conn_table[cid]) {
+       uint16_t cri_index = BE_GET_CRI_FROM_CID(cid);
+
+       if (phba->conn_table[cri_index]) {
                beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
                            "BS_%d : Connection table already occupied. Detected clash\n");
 
@@ -169,9 +171,9 @@ static int beiscsi_bindconn_cid(struct beiscsi_hba *phba,
        } else {
                beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
                            "BS_%d : phba->conn_table[%d]=%p(beiscsi_conn)\n",
-                           cid, beiscsi_conn);
+                           cri_index, beiscsi_conn);
 
-               phba->conn_table[cid] = beiscsi_conn;
+               phba->conn_table[cri_index] = beiscsi_conn;
        }
        return 0;
 }
@@ -990,9 +992,27 @@ static void beiscsi_put_cid(struct beiscsi_hba *phba, unsigned short cid)
 static void beiscsi_free_ep(struct beiscsi_endpoint *beiscsi_ep)
 {
        struct beiscsi_hba *phba = beiscsi_ep->phba;
+       struct beiscsi_conn *beiscsi_conn;
 
        beiscsi_put_cid(phba, beiscsi_ep->ep_cid);
        beiscsi_ep->phba = NULL;
+       phba->ep_array[BE_GET_CRI_FROM_CID
+                      (beiscsi_ep->ep_cid)] = NULL;
+
+       /**
+        * Check if any connection resource allocated by driver
+        * is to be freed.This case occurs when target redirection
+        * or connection retry is done.
+        **/
+       if (!beiscsi_ep->conn)
+               return;
+
+       beiscsi_conn = beiscsi_ep->conn;
+       if (beiscsi_conn->login_in_progress) {
+               beiscsi_free_mgmt_task_handles(beiscsi_conn,
+                                              beiscsi_conn->task);
+               beiscsi_conn->login_in_progress = 0;
+       }
 }
 
 /**
@@ -1009,7 +1029,6 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep,
 {
        struct beiscsi_endpoint *beiscsi_ep = ep->dd_data;
        struct beiscsi_hba *phba = beiscsi_ep->phba;
-       struct be_mcc_wrb *wrb;
        struct tcp_connect_and_offload_out *ptcpcnct_out;
        struct be_dma_mem nonemb_cmd;
        unsigned int tag;
@@ -1029,15 +1048,8 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep,
                    "BS_%d : In beiscsi_open_conn, ep_cid=%d\n",
                    beiscsi_ep->ep_cid);
 
-       phba->ep_array[beiscsi_ep->ep_cid -
-                      phba->fw_config.iscsi_cid_start] = ep;
-       if (beiscsi_ep->ep_cid > (phba->fw_config.iscsi_cid_start +
-                                 phba->params.cxns_per_ctrl * 2)) {
-
-               beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
-                           "BS_%d : Failed in allocate iscsi cid\n");
-               goto free_ep;
-       }
+       phba->ep_array[BE_GET_CRI_FROM_CID
+                      (beiscsi_ep->ep_cid)] = ep;
 
        beiscsi_ep->cid_vld = 0;
        nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev,
@@ -1049,24 +1061,24 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep,
                            "BS_%d : Failed to allocate memory for"
                            " mgmt_open_connection\n");
 
-               beiscsi_put_cid(phba, beiscsi_ep->ep_cid);
+               beiscsi_free_ep(beiscsi_ep);
                return -ENOMEM;
        }
        nonemb_cmd.size = sizeof(struct tcp_connect_and_offload_in);
        memset(nonemb_cmd.va, 0, nonemb_cmd.size);
        tag = mgmt_open_connection(phba, dst_addr, beiscsi_ep, &nonemb_cmd);
-       if (!tag) {
+       if (tag <= 0) {
                beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
                            "BS_%d : mgmt_open_connection Failed for cid=%d\n",
                            beiscsi_ep->ep_cid);
 
-               beiscsi_put_cid(phba, beiscsi_ep->ep_cid);
                pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
                                    nonemb_cmd.va, nonemb_cmd.dma);
+               beiscsi_free_ep(beiscsi_ep);
                return -EAGAIN;
        }
 
-       ret = beiscsi_mccq_compl(phba, tag, &wrb, NULL);
+       ret = beiscsi_mccq_compl(phba, tag, NULL, nonemb_cmd.va);
        if (ret) {
                beiscsi_log(phba, KERN_ERR,
                            BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
@@ -1074,10 +1086,11 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep,
 
                pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
                            nonemb_cmd.va, nonemb_cmd.dma);
-               goto free_ep;
+               beiscsi_free_ep(beiscsi_ep);
+               return -EBUSY;
        }
 
-       ptcpcnct_out = embedded_payload(wrb);
+       ptcpcnct_out = (struct tcp_connect_and_offload_out *)nonemb_cmd.va;
        beiscsi_ep = ep->dd_data;
        beiscsi_ep->fw_handle = ptcpcnct_out->connection_handle;
        beiscsi_ep->cid_vld = 1;
@@ -1087,10 +1100,6 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep,
        pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
                            nonemb_cmd.va, nonemb_cmd.dma);
        return 0;
-
-free_ep:
-       beiscsi_free_ep(beiscsi_ep);
-       return -EBUSY;
 }
 
 /**
@@ -1119,6 +1128,13 @@ beiscsi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr,
                return ERR_PTR(ret);
        }
 
+       if (beiscsi_error(phba)) {
+               ret = -EIO;
+               beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,
+                           "BS_%d : The FW state Not Stable!!!\n");
+               return ERR_PTR(ret);
+       }
+
        if (phba->state != BE_ADAPTER_UP) {
                ret = -EBUSY;
                beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,
@@ -1201,8 +1217,10 @@ static int beiscsi_close_conn(struct  beiscsi_endpoint *beiscsi_ep, int flag)
 static int beiscsi_unbind_conn_to_cid(struct beiscsi_hba *phba,
                                      unsigned int cid)
 {
-       if (phba->conn_table[cid])
-               phba->conn_table[cid] = NULL;
+       uint16_t cri_index = BE_GET_CRI_FROM_CID(cid);
+
+       if (phba->conn_table[cri_index])
+               phba->conn_table[cri_index] = NULL;
        else {
                beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
                            "BS_%d : Connection table Not occupied.\n");
index 38eab72..31ddc84 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2005 - 2012 Emulex
+ * Copyright (C) 2005 - 2013 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
index 4e2733d..d24a286 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2005 - 2012 Emulex
+ * Copyright (C) 2005 - 2013 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -153,10 +153,14 @@ BEISCSI_RW_ATTR(log_enable, 0x00,
 
 DEVICE_ATTR(beiscsi_drvr_ver, S_IRUGO, beiscsi_drvr_ver_disp, NULL);
 DEVICE_ATTR(beiscsi_adapter_family, S_IRUGO, beiscsi_adap_family_disp, NULL);
+DEVICE_ATTR(beiscsi_fw_ver, S_IRUGO, beiscsi_fw_ver_disp, NULL);
+DEVICE_ATTR(beiscsi_active_cid_count, S_IRUGO, beiscsi_active_cid_disp, NULL);
 struct device_attribute *beiscsi_attrs[] = {
        &dev_attr_beiscsi_log_enable,
        &dev_attr_beiscsi_drvr_ver,
        &dev_attr_beiscsi_adapter_family,
+       &dev_attr_beiscsi_fw_ver,
+       &dev_attr_beiscsi_active_cid_count,
        NULL,
 };
 
@@ -702,7 +706,7 @@ static void beiscsi_get_params(struct beiscsi_hba *phba)
                                    + BE2_TMFS
                                    + BE2_NOPOUT_REQ));
        phba->params.cxns_per_ctrl = phba->fw_config.iscsi_cid_count;
-       phba->params.asyncpdus_per_ctrl = phba->fw_config.iscsi_cid_count * 2;
+       phba->params.asyncpdus_per_ctrl = phba->fw_config.iscsi_cid_count;
        phba->params.icds_per_ctrl = phba->fw_config.iscsi_icd_count;
        phba->params.num_sge_per_io = BE2_SGE;
        phba->params.defpdu_hdr_sz = BE2_DEFPDU_HDR_SZ;
@@ -1032,7 +1036,6 @@ static void hwi_ring_cq_db(struct beiscsi_hba *phba,
 static unsigned int
 beiscsi_process_async_pdu(struct beiscsi_conn *beiscsi_conn,
                          struct beiscsi_hba *phba,
-                         unsigned short cid,
                          struct pdu_base *ppdu,
                          unsigned long pdu_len,
                          void *pbuffer, unsigned long buf_len)
@@ -1144,9 +1147,10 @@ struct wrb_handle *alloc_wrb_handle(struct beiscsi_hba *phba, unsigned int cid)
        struct hwi_wrb_context *pwrb_context;
        struct hwi_controller *phwi_ctrlr;
        struct wrb_handle *pwrb_handle, *pwrb_handle_tmp;
+       uint16_t cri_index = BE_GET_CRI_FROM_CID(cid);
 
        phwi_ctrlr = phba->phwi_ctrlr;
-       pwrb_context = &phwi_ctrlr->wrb_context[cid];
+       pwrb_context = &phwi_ctrlr->wrb_context[cri_index];
        if (pwrb_context->wrb_handles_available >= 2) {
                pwrb_handle = pwrb_context->pwrb_handle_base[
                                            pwrb_context->alloc_index];
@@ -1322,8 +1326,9 @@ be_complete_logout(struct beiscsi_conn *beiscsi_conn,
        hdr->t2retain = 0;
        hdr->flags = csol_cqe->i_flags;
        hdr->response = csol_cqe->i_resp;
-       hdr->exp_cmdsn = csol_cqe->exp_cmdsn;
-       hdr->max_cmdsn = (csol_cqe->exp_cmdsn + csol_cqe->cmd_wnd - 1);
+       hdr->exp_cmdsn = cpu_to_be32(csol_cqe->exp_cmdsn);
+       hdr->max_cmdsn = cpu_to_be32(csol_cqe->exp_cmdsn +
+                                    csol_cqe->cmd_wnd - 1);
 
        hdr->dlength[0] = 0;
        hdr->dlength[1] = 0;
@@ -1346,9 +1351,9 @@ be_complete_tmf(struct beiscsi_conn *beiscsi_conn,
        hdr->opcode = ISCSI_OP_SCSI_TMFUNC_RSP;
        hdr->flags = csol_cqe->i_flags;
        hdr->response = csol_cqe->i_resp;
-       hdr->exp_cmdsn = csol_cqe->exp_cmdsn;
-       hdr->max_cmdsn = (csol_cqe->exp_cmdsn +
-                         csol_cqe->cmd_wnd - 1);
+       hdr->exp_cmdsn = cpu_to_be32(csol_cqe->exp_cmdsn);
+       hdr->max_cmdsn = cpu_to_be32(csol_cqe->exp_cmdsn +
+                                    csol_cqe->cmd_wnd - 1);
 
        hdr->itt = io_task->libiscsi_itt;
        __iscsi_complete_pdu(conn, (struct iscsi_hdr *)hdr, NULL, 0);
@@ -1363,35 +1368,29 @@ hwi_complete_drvr_msgs(struct beiscsi_conn *beiscsi_conn,
        struct hwi_controller *phwi_ctrlr;
        struct iscsi_task *task;
        struct beiscsi_io_task *io_task;
-       struct iscsi_conn *conn = beiscsi_conn->conn;
-       struct iscsi_session *session = conn->session;
-       uint16_t wrb_index, cid;
+       uint16_t wrb_index, cid, cri_index;
 
        phwi_ctrlr = phba->phwi_ctrlr;
-       if (chip_skh_r(phba->pcidev)) {
-               wrb_index = AMAP_GET_BITS(struct amap_it_dmsg_cqe_v2,
+       if (is_chip_be2_be3r(phba)) {
+               wrb_index = AMAP_GET_BITS(struct amap_it_dmsg_cqe,
                                          wrb_idx, psol);
-               cid = AMAP_GET_BITS(struct amap_it_dmsg_cqe_v2,
+               cid = AMAP_GET_BITS(struct amap_it_dmsg_cqe,
                                    cid, psol);
        } else {
-               wrb_index = AMAP_GET_BITS(struct amap_it_dmsg_cqe,
+               wrb_index = AMAP_GET_BITS(struct amap_it_dmsg_cqe_v2,
                                          wrb_idx, psol);
-               cid = AMAP_GET_BITS(struct amap_it_dmsg_cqe,
+               cid = AMAP_GET_BITS(struct amap_it_dmsg_cqe_v2,
                                    cid, psol);
        }
 
-       pwrb_context = &phwi_ctrlr->wrb_context[
-                       cid - phba->fw_config.iscsi_cid_start];
+       cri_index = BE_GET_CRI_FROM_CID(cid);
+       pwrb_context = &phwi_ctrlr->wrb_context[cri_index];
        pwrb_handle = pwrb_context->pwrb_handle_basestd[wrb_index];
        task = pwrb_handle->pio_handle;
 
        io_task = task->dd_data;
-       spin_lock_bh(&phba->mgmt_sgl_lock);
-       free_mgmt_sgl_handle(phba, io_task->psgl_handle);
-       spin_unlock_bh(&phba->mgmt_sgl_lock);
-       spin_lock_bh(&session->lock);
-       free_wrb_handle(phba, pwrb_context, pwrb_handle);
-       spin_unlock_bh(&session->lock);
+       memset(io_task->pwrb_handle->pwrb, 0, sizeof(struct iscsi_wrb));
+       iscsi_put_task(task);
 }
 
 static void
@@ -1406,8 +1405,8 @@ be_complete_nopin_resp(struct beiscsi_conn *beiscsi_conn,
        hdr = (struct iscsi_nopin *)task->hdr;
        hdr->flags = csol_cqe->i_flags;
        hdr->exp_cmdsn = cpu_to_be32(csol_cqe->exp_cmdsn);
-       hdr->max_cmdsn = be32_to_cpu(hdr->exp_cmdsn +
-                        csol_cqe->cmd_wnd - 1);
+       hdr->max_cmdsn = cpu_to_be32(csol_cqe->exp_cmdsn +
+                                    csol_cqe->cmd_wnd - 1);
 
        hdr->opcode = ISCSI_OP_NOOP_IN;
        hdr->itt = io_task->libiscsi_itt;
@@ -1418,7 +1417,26 @@ static void adapter_get_sol_cqe(struct beiscsi_hba *phba,
                struct sol_cqe *psol,
                struct common_sol_cqe *csol_cqe)
 {
-       if (chip_skh_r(phba->pcidev)) {
+       if (is_chip_be2_be3r(phba)) {
+               csol_cqe->exp_cmdsn = AMAP_GET_BITS(struct amap_sol_cqe,
+                                                   i_exp_cmd_sn, psol);
+               csol_cqe->res_cnt = AMAP_GET_BITS(struct amap_sol_cqe,
+                                                 i_res_cnt, psol);
+               csol_cqe->cmd_wnd = AMAP_GET_BITS(struct amap_sol_cqe,
+                                                 i_cmd_wnd, psol);
+               csol_cqe->wrb_index = AMAP_GET_BITS(struct amap_sol_cqe,
+                                                   wrb_index, psol);
+               csol_cqe->cid = AMAP_GET_BITS(struct amap_sol_cqe,
+                                             cid, psol);
+               csol_cqe->hw_sts = AMAP_GET_BITS(struct amap_sol_cqe,
+                                                hw_sts, psol);
+               csol_cqe->i_resp = AMAP_GET_BITS(struct amap_sol_cqe,
+                                                i_resp, psol);
+               csol_cqe->i_sts = AMAP_GET_BITS(struct amap_sol_cqe,
+                                               i_sts, psol);
+               csol_cqe->i_flags = AMAP_GET_BITS(struct amap_sol_cqe,
+                                                 i_flags, psol);
+       } else {
                csol_cqe->exp_cmdsn = AMAP_GET_BITS(struct amap_sol_cqe_v2,
                                                    i_exp_cmd_sn, psol);
                csol_cqe->res_cnt = AMAP_GET_BITS(struct amap_sol_cqe_v2,
@@ -1429,7 +1447,7 @@ static void adapter_get_sol_cqe(struct beiscsi_hba *phba,
                                              cid, psol);
                csol_cqe->hw_sts = AMAP_GET_BITS(struct amap_sol_cqe_v2,
                                                 hw_sts, psol);
-               csol_cqe->cmd_wnd = AMAP_GET_BITS(struct amap_sol_cqe,
+               csol_cqe->cmd_wnd = AMAP_GET_BITS(struct amap_sol_cqe_v2,
                                                  i_cmd_wnd, psol);
                if (AMAP_GET_BITS(struct amap_sol_cqe_v2,
                                  cmd_cmpl, psol))
@@ -1445,25 +1463,6 @@ static void adapter_get_sol_cqe(struct beiscsi_hba *phba,
                if (AMAP_GET_BITS(struct amap_sol_cqe_v2,
                                  o, psol))
                        csol_cqe->i_flags |= ISCSI_FLAG_CMD_OVERFLOW;
-       } else {
-               csol_cqe->exp_cmdsn = AMAP_GET_BITS(struct amap_sol_cqe,
-                                                   i_exp_cmd_sn, psol);
-               csol_cqe->res_cnt = AMAP_GET_BITS(struct amap_sol_cqe,
-                                                 i_res_cnt, psol);
-               csol_cqe->cmd_wnd = AMAP_GET_BITS(struct amap_sol_cqe,
-                                                 i_cmd_wnd, psol);
-               csol_cqe->wrb_index = AMAP_GET_BITS(struct amap_sol_cqe,
-                                                   wrb_index, psol);
-               csol_cqe->cid = AMAP_GET_BITS(struct amap_sol_cqe,
-                                             cid, psol);
-               csol_cqe->hw_sts = AMAP_GET_BITS(struct amap_sol_cqe,
-                                                hw_sts, psol);
-               csol_cqe->i_resp = AMAP_GET_BITS(struct amap_sol_cqe,
-                                                i_resp, psol);
-               csol_cqe->i_sts = AMAP_GET_BITS(struct amap_sol_cqe,
-                                               i_sts, psol);
-               csol_cqe->i_flags = AMAP_GET_BITS(struct amap_sol_cqe,
-                                                 i_flags, psol);
        }
 }
 
@@ -1480,14 +1479,15 @@ static void hwi_complete_cmd(struct beiscsi_conn *beiscsi_conn,
        struct iscsi_conn *conn = beiscsi_conn->conn;
        struct iscsi_session *session = conn->session;
        struct common_sol_cqe csol_cqe = {0};
+       uint16_t cri_index = 0;
 
        phwi_ctrlr = phba->phwi_ctrlr;
 
        /* Copy the elements to a common structure */
        adapter_get_sol_cqe(phba, psol, &csol_cqe);
 
-       pwrb_context = &phwi_ctrlr->wrb_context[
-                       csol_cqe.cid - phba->fw_config.iscsi_cid_start];
+       cri_index = BE_GET_CRI_FROM_CID(csol_cqe.cid);
+       pwrb_context = &phwi_ctrlr->wrb_context[cri_index];
 
        pwrb_handle = pwrb_context->pwrb_handle_basestd[
                      csol_cqe.wrb_index];
@@ -1561,15 +1561,15 @@ hwi_get_async_handle(struct beiscsi_hba *phba,
        unsigned char is_header = 0;
        unsigned int index, dpl;
 
-       if (chip_skh_r(phba->pcidev)) {
-               dpl = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe_v2,
+       if (is_chip_be2_be3r(phba)) {
+               dpl = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe,
                                    dpl, pdpdu_cqe);
-               index = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe_v2,
+               index = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe,
                                      index, pdpdu_cqe);
        } else {
-               dpl = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe,
+               dpl = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe_v2,
                                    dpl, pdpdu_cqe);
-               index = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe,
+               index = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe_v2,
                                      index, pdpdu_cqe);
        }
 
@@ -1613,8 +1613,8 @@ hwi_get_async_handle(struct beiscsi_hba *phba,
 
        WARN_ON(!pasync_handle);
 
-       pasync_handle->cri = (unsigned short)beiscsi_conn->beiscsi_conn_cid -
-                                            phba->fw_config.iscsi_cid_start;
+       pasync_handle->cri =
+                       BE_GET_CRI_FROM_CID(beiscsi_conn->beiscsi_conn_cid);
        pasync_handle->is_header = is_header;
        pasync_handle->buffer_len = dpl;
        *pcq_index = index;
@@ -1856,8 +1856,6 @@ hwi_fwd_async_msg(struct beiscsi_conn *beiscsi_conn,
        }
 
        status = beiscsi_process_async_pdu(beiscsi_conn, phba,
-                                          (beiscsi_conn->beiscsi_conn_cid -
-                                           phba->fw_config.iscsi_cid_start),
                                            phdr, hdr_len, pfirst_buffer,
                                            offset);
 
@@ -2011,6 +2009,7 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
        unsigned int num_processed = 0;
        unsigned int tot_nump = 0;
        unsigned short code = 0, cid = 0;
+       uint16_t cri_index = 0;
        struct beiscsi_conn *beiscsi_conn;
        struct beiscsi_endpoint *beiscsi_ep;
        struct iscsi_endpoint *ep;
@@ -2028,7 +2027,9 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
                         32] & CQE_CODE_MASK);
 
                 /* Get the CID */
-               if (chip_skh_r(phba->pcidev)) {
+               if (is_chip_be2_be3r(phba)) {
+                       cid = AMAP_GET_BITS(struct amap_sol_cqe, cid, sol);
+               } else {
                        if ((code == DRIVERMSG_NOTIFY) ||
                            (code == UNSOL_HDR_NOTIFY) ||
                            (code == UNSOL_DATA_NOTIFY))
@@ -2038,10 +2039,10 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
                         else
                                 cid = AMAP_GET_BITS(struct amap_sol_cqe_v2,
                                                     cid, sol);
-                  } else
-                        cid = AMAP_GET_BITS(struct amap_sol_cqe, cid, sol);
+               }
 
-               ep = phba->ep_array[cid - phba->fw_config.iscsi_cid_start];
+               cri_index = BE_GET_CRI_FROM_CID(cid);
+               ep = phba->ep_array[cri_index];
                beiscsi_ep = ep->dd_data;
                beiscsi_conn = beiscsi_ep->conn;
 
@@ -2191,7 +2192,7 @@ void beiscsi_process_all_cqs(struct work_struct *work)
 
 static int be_iopoll(struct blk_iopoll *iop, int budget)
 {
-       static unsigned int ret;
+       unsigned int ret;
        struct beiscsi_hba *phba;
        struct be_eq_obj *pbe_eq;
 
@@ -2416,11 +2417,11 @@ static void hwi_write_buffer(struct iscsi_wrb *pwrb, struct iscsi_task *task)
                /* Check for the data_count */
                dsp_value = (task->data_count) ? 1 : 0;
 
-               if (chip_skh_r(phba->pcidev))
-                       AMAP_SET_BITS(struct amap_iscsi_wrb_v2, dsp,
+               if (is_chip_be2_be3r(phba))
+                       AMAP_SET_BITS(struct amap_iscsi_wrb, dsp,
                                      pwrb, dsp_value);
                else
-                       AMAP_SET_BITS(struct amap_iscsi_wrb, dsp,
+                       AMAP_SET_BITS(struct amap_iscsi_wrb_v2, dsp,
                                      pwrb, dsp_value);
 
                /* Map addr only if there is data_count */
@@ -2538,8 +2539,9 @@ static void beiscsi_find_mem_req(struct beiscsi_hba *phba)
 
 static int beiscsi_alloc_mem(struct beiscsi_hba *phba)
 {
-       struct be_mem_descriptor *mem_descr;
        dma_addr_t bus_add;
+       struct hwi_controller *phwi_ctrlr;
+       struct be_mem_descriptor *mem_descr;
        struct mem_array *mem_arr, *mem_arr_orig;
        unsigned int i, j, alloc_size, curr_alloc_size;
 
@@ -2547,9 +2549,18 @@ static int beiscsi_alloc_mem(struct beiscsi_hba *phba)
        if (!phba->phwi_ctrlr)
                return -ENOMEM;
 
+       /* Allocate memory for wrb_context */
+       phwi_ctrlr = phba->phwi_ctrlr;
+       phwi_ctrlr->wrb_context = kzalloc(sizeof(struct hwi_wrb_context) *
+                                         phba->params.cxns_per_ctrl,
+                                         GFP_KERNEL);
+       if (!phwi_ctrlr->wrb_context)
+               return -ENOMEM;
+
        phba->init_mem = kcalloc(SE_MEM_MAX, sizeof(*mem_descr),
                                 GFP_KERNEL);
        if (!phba->init_mem) {
+               kfree(phwi_ctrlr->wrb_context);
                kfree(phba->phwi_ctrlr);
                return -ENOMEM;
        }
@@ -2558,6 +2569,7 @@ static int beiscsi_alloc_mem(struct beiscsi_hba *phba)
                               GFP_KERNEL);
        if (!mem_arr_orig) {
                kfree(phba->init_mem);
+               kfree(phwi_ctrlr->wrb_context);
                kfree(phba->phwi_ctrlr);
                return -ENOMEM;
        }
@@ -2628,6 +2640,7 @@ free_mem:
        }
        kfree(mem_arr_orig);
        kfree(phba->init_mem);
+       kfree(phba->phwi_ctrlr->wrb_context);
        kfree(phba->phwi_ctrlr);
        return -ENOMEM;
 }
@@ -2666,6 +2679,7 @@ static void iscsi_init_global_templates(struct beiscsi_hba *phba)
 static int beiscsi_init_wrb_handle(struct beiscsi_hba *phba)
 {
        struct be_mem_descriptor *mem_descr_wrbh, *mem_descr_wrb;
+       struct hwi_context_memory *phwi_ctxt;
        struct wrb_handle *pwrb_handle = NULL;
        struct hwi_controller *phwi_ctrlr;
        struct hwi_wrb_context *pwrb_context;
@@ -2680,7 +2694,18 @@ static int beiscsi_init_wrb_handle(struct beiscsi_hba *phba)
        mem_descr_wrb += HWI_MEM_WRB;
        phwi_ctrlr = phba->phwi_ctrlr;
 
-       for (index = 0; index < phba->params.cxns_per_ctrl * 2; index += 2) {
+       /* Allocate memory for WRBQ */
+       phwi_ctxt = phwi_ctrlr->phwi_ctxt;
+       phwi_ctxt->be_wrbq = kzalloc(sizeof(struct be_queue_info) *
+                                    phba->fw_config.iscsi_cid_count,
+                                    GFP_KERNEL);
+       if (!phwi_ctxt->be_wrbq) {
+               beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
+                           "BM_%d : WRBQ Mem Alloc Failed\n");
+               return -ENOMEM;
+       }
+
+       for (index = 0; index < phba->params.cxns_per_ctrl; index++) {
                pwrb_context = &phwi_ctrlr->wrb_context[index];
                pwrb_context->pwrb_handle_base =
                                kzalloc(sizeof(struct wrb_handle *) *
@@ -2723,7 +2748,7 @@ static int beiscsi_init_wrb_handle(struct beiscsi_hba *phba)
                }
        }
        idx = 0;
-       for (index = 0; index < phba->params.cxns_per_ctrl * 2; index += 2) {
+       for (index = 0; index < phba->params.cxns_per_ctrl; index++) {
                pwrb_context = &phwi_ctrlr->wrb_context[index];
                if (!num_cxn_wrb) {
                        pwrb = mem_descr_wrb->mem_array[idx].virtual_address;
@@ -2752,7 +2777,7 @@ init_wrb_hndl_failed:
        return -ENOMEM;
 }
 
-static void hwi_init_async_pdu_ctx(struct beiscsi_hba *phba)
+static int hwi_init_async_pdu_ctx(struct beiscsi_hba *phba)
 {
        struct hwi_controller *phwi_ctrlr;
        struct hba_parameters *p = &phba->params;
@@ -2770,6 +2795,15 @@ static void hwi_init_async_pdu_ctx(struct beiscsi_hba *phba)
        pasync_ctx = phwi_ctrlr->phwi_ctxt->pasync_ctx;
        memset(pasync_ctx, 0, sizeof(*pasync_ctx));
 
+       pasync_ctx->async_entry = kzalloc(sizeof(struct hwi_async_entry) *
+                                         phba->fw_config.iscsi_cid_count,
+                                         GFP_KERNEL);
+       if (!pasync_ctx->async_entry) {
+               beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
+                           "BM_%d : hwi_init_async_pdu_ctx Mem Alloc Failed\n");
+               return -ENOMEM;
+       }
+
        pasync_ctx->num_entries = p->asyncpdus_per_ctrl;
        pasync_ctx->buffer_size = p->defpdu_hdr_sz;
 
@@ -2934,6 +2968,8 @@ static void hwi_init_async_pdu_ctx(struct beiscsi_hba *phba)
        pasync_ctx->async_header.ep_read_ptr = -1;
        pasync_ctx->async_data.host_write_ptr = 0;
        pasync_ctx->async_data.ep_read_ptr = -1;
+
+       return 0;
 }
 
 static int
@@ -3293,6 +3329,7 @@ beiscsi_create_wrb_rings(struct beiscsi_hba *phba,
        void *wrb_vaddr;
        struct be_dma_mem sgl;
        struct be_mem_descriptor *mem_descr;
+       struct hwi_wrb_context *pwrb_context;
        int status;
 
        idx = 0;
@@ -3351,8 +3388,9 @@ beiscsi_create_wrb_rings(struct beiscsi_hba *phba,
                        kfree(pwrb_arr);
                        return status;
                }
-               phwi_ctrlr->wrb_context[i * 2].cid = phwi_context->be_wrbq[i].
-                                                                  id;
+               pwrb_context = &phwi_ctrlr->wrb_context[i];
+               pwrb_context->cid = phwi_context->be_wrbq[i].id;
+               BE_SET_CID_TO_CRI(i, pwrb_context->cid);
        }
        kfree(pwrb_arr);
        return 0;
@@ -3365,7 +3403,7 @@ static void free_wrb_handles(struct beiscsi_hba *phba)
        struct hwi_wrb_context *pwrb_context;
 
        phwi_ctrlr = phba->phwi_ctrlr;
-       for (index = 0; index < phba->params.cxns_per_ctrl * 2; index += 2) {
+       for (index = 0; index < phba->params.cxns_per_ctrl; index++) {
                pwrb_context = &phwi_ctrlr->wrb_context[index];
                kfree(pwrb_context->pwrb_handle_base);
                kfree(pwrb_context->pwrb_handle_basestd);
@@ -3394,6 +3432,7 @@ static void hwi_cleanup(struct beiscsi_hba *phba)
        struct be_ctrl_info *ctrl = &phba->ctrl;
        struct hwi_controller *phwi_ctrlr;
        struct hwi_context_memory *phwi_context;
+       struct hwi_async_pdu_context *pasync_ctx;
        int i, eq_num;
 
        phwi_ctrlr = phba->phwi_ctrlr;
@@ -3403,6 +3442,7 @@ static void hwi_cleanup(struct beiscsi_hba *phba)
                if (q->created)
                        beiscsi_cmd_q_destroy(ctrl, q, QTYPE_WRBQ);
        }
+       kfree(phwi_context->be_wrbq);
        free_wrb_handles(phba);
 
        q = &phwi_context->be_def_hdrq;
@@ -3430,6 +3470,10 @@ static void hwi_cleanup(struct beiscsi_hba *phba)
                        beiscsi_cmd_q_destroy(ctrl, q, QTYPE_EQ);
        }
        be_mcc_queues_destroy(phba);
+
+       pasync_ctx = phwi_ctrlr->phwi_ctxt->pasync_ctx;
+       kfree(pasync_ctx->async_entry);
+       be_cmd_fw_uninit(ctrl);
 }
 
 static int be_mcc_queues_create(struct beiscsi_hba *phba,
@@ -3607,7 +3651,12 @@ static int hwi_init_controller(struct beiscsi_hba *phba)
        if (beiscsi_init_wrb_handle(phba))
                return -ENOMEM;
 
-       hwi_init_async_pdu_ctx(phba);
+       if (hwi_init_async_pdu_ctx(phba)) {
+               beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
+                           "BM_%d : hwi_init_async_pdu_ctx failed\n");
+               return -ENOMEM;
+       }
+
        if (hwi_init_port(phba) != 0) {
                beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
                            "BM_%d : hwi_init_controller failed\n");
@@ -3637,6 +3686,7 @@ static void beiscsi_free_mem(struct beiscsi_hba *phba)
                mem_descr++;
        }
        kfree(phba->init_mem);
+       kfree(phba->phwi_ctrlr->wrb_context);
        kfree(phba->phwi_ctrlr);
 }
 
@@ -3769,7 +3819,7 @@ static int beiscsi_init_sgl_handle(struct beiscsi_hba *phba)
 
 static int hba_setup_cid_tbls(struct beiscsi_hba *phba)
 {
-       int i, new_cid;
+       int i;
 
        phba->cid_array = kzalloc(sizeof(void *) * phba->params.cxns_per_ctrl,
                                  GFP_KERNEL);
@@ -3780,19 +3830,33 @@ static int hba_setup_cid_tbls(struct beiscsi_hba *phba)
                return -ENOMEM;
        }
        phba->ep_array = kzalloc(sizeof(struct iscsi_endpoint *) *
-                                phba->params.cxns_per_ctrl * 2, GFP_KERNEL);
+                                phba->params.cxns_per_ctrl, GFP_KERNEL);
        if (!phba->ep_array) {
                beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
                            "BM_%d : Failed to allocate memory in "
                            "hba_setup_cid_tbls\n");
                kfree(phba->cid_array);
+               phba->cid_array = NULL;
                return -ENOMEM;
        }
-       new_cid = phba->fw_config.iscsi_cid_start;
-       for (i = 0; i < phba->params.cxns_per_ctrl; i++) {
-               phba->cid_array[i] = new_cid;
-               new_cid += 2;
+
+       phba->conn_table = kzalloc(sizeof(struct beiscsi_conn *) *
+                                  phba->params.cxns_per_ctrl, GFP_KERNEL);
+       if (!phba->conn_table) {
+               beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
+                           "BM_%d : Failed to allocate memory in"
+                           "hba_setup_cid_tbls\n");
+
+               kfree(phba->cid_array);
+               kfree(phba->ep_array);
+               phba->cid_array = NULL;
+               phba->ep_array = NULL;
+               return -ENOMEM;
        }
+
+       for (i = 0; i < phba->params.cxns_per_ctrl; i++)
+               phba->cid_array[i] = phba->phwi_ctrlr->wrb_context[i].cid;
+
        phba->avlbl_cids = phba->params.cxns_per_ctrl;
        return 0;
 }
@@ -4062,6 +4126,53 @@ static void beiscsi_clean_port(struct beiscsi_hba *phba)
        kfree(phba->eh_sgl_hndl_base);
        kfree(phba->cid_array);
        kfree(phba->ep_array);
+       kfree(phba->conn_table);
+}
+
+/**
+ * beiscsi_free_mgmt_task_handles()- Free driver CXN resources
+ * @beiscsi_conn: ptr to the conn to be cleaned up
+ * @task: ptr to iscsi_task resource to be freed.
+ *
+ * Free driver mgmt resources binded to CXN.
+ **/
+void
+beiscsi_free_mgmt_task_handles(struct beiscsi_conn *beiscsi_conn,
+                               struct iscsi_task *task)
+{
+       struct beiscsi_io_task *io_task;
+       struct beiscsi_hba *phba = beiscsi_conn->phba;
+       struct hwi_wrb_context *pwrb_context;
+       struct hwi_controller *phwi_ctrlr;
+       uint16_t cri_index = BE_GET_CRI_FROM_CID(
+                               beiscsi_conn->beiscsi_conn_cid);
+
+       phwi_ctrlr = phba->phwi_ctrlr;
+       pwrb_context = &phwi_ctrlr->wrb_context[cri_index];
+
+       io_task = task->dd_data;
+
+       if (io_task->pwrb_handle) {
+               memset(io_task->pwrb_handle->pwrb, 0,
+                      sizeof(struct iscsi_wrb));
+               free_wrb_handle(phba, pwrb_context,
+                               io_task->pwrb_handle);
+               io_task->pwrb_handle = NULL;
+       }
+
+       if (io_task->psgl_handle) {
+               spin_lock_bh(&phba->mgmt_sgl_lock);
+               free_mgmt_sgl_handle(phba,
+                                    io_task->psgl_handle);
+               io_task->psgl_handle = NULL;
+               spin_unlock_bh(&phba->mgmt_sgl_lock);
+       }
+
+       if (io_task->mtask_addr)
+               pci_unmap_single(phba->pcidev,
+                                io_task->mtask_addr,
+                                io_task->mtask_data_count,
+                                PCI_DMA_TODEVICE);
 }
 
 /**
@@ -4078,10 +4189,11 @@ static void beiscsi_cleanup_task(struct iscsi_task *task)
        struct beiscsi_session *beiscsi_sess = beiscsi_conn->beiscsi_sess;
        struct hwi_wrb_context *pwrb_context;
        struct hwi_controller *phwi_ctrlr;
+       uint16_t cri_index = BE_GET_CRI_FROM_CID(
+                            beiscsi_conn->beiscsi_conn_cid);
 
        phwi_ctrlr = phba->phwi_ctrlr;
-       pwrb_context = &phwi_ctrlr->wrb_context[beiscsi_conn->beiscsi_conn_cid
-                       - phba->fw_config.iscsi_cid_start];
+       pwrb_context = &phwi_ctrlr->wrb_context[cri_index];
 
        if (io_task->cmd_bhs) {
                pci_pool_free(beiscsi_sess->bhs_pool, io_task->cmd_bhs,
@@ -4103,27 +4215,8 @@ static void beiscsi_cleanup_task(struct iscsi_task *task)
                        io_task->psgl_handle = NULL;
                }
        } else {
-               if (!beiscsi_conn->login_in_progress) {
-                       if (io_task->pwrb_handle) {
-                               free_wrb_handle(phba, pwrb_context,
-                                               io_task->pwrb_handle);
-                               io_task->pwrb_handle = NULL;
-                       }
-                       if (io_task->psgl_handle) {
-                               spin_lock(&phba->mgmt_sgl_lock);
-                               free_mgmt_sgl_handle(phba,
-                                                    io_task->psgl_handle);
-                               spin_unlock(&phba->mgmt_sgl_lock);
-                               io_task->psgl_handle = NULL;
-                       }
-                       if (io_task->mtask_addr) {
-                               pci_unmap_single(phba->pcidev,
-                                                io_task->mtask_addr,
-                                                io_task->mtask_data_count,
-                                                PCI_DMA_TODEVICE);
-                               io_task->mtask_addr = 0;
-                       }
-               }
+               if (!beiscsi_conn->login_in_progress)
+                       beiscsi_free_mgmt_task_handles(beiscsi_conn, task);
        }
 }
 
@@ -4146,15 +4239,14 @@ beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn,
        beiscsi_cleanup_task(task);
        spin_unlock_bh(&session->lock);
 
-       pwrb_handle = alloc_wrb_handle(phba, (beiscsi_conn->beiscsi_conn_cid -
-                                      phba->fw_config.iscsi_cid_start));
+       pwrb_handle = alloc_wrb_handle(phba, beiscsi_conn->beiscsi_conn_cid);
 
        /* Check for the adapter family */
-       if (chip_skh_r(phba->pcidev))
-               beiscsi_offload_cxn_v2(params, pwrb_handle);
-       else
+       if (is_chip_be2_be3r(phba))
                beiscsi_offload_cxn_v0(params, pwrb_handle,
                                       phba->init_mem);
+       else
+               beiscsi_offload_cxn_v2(params, pwrb_handle);
 
        be_dws_le_to_cpu(pwrb_handle->pwrb,
                         sizeof(struct iscsi_target_context_update_wrb));
@@ -4194,6 +4286,7 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
        struct hwi_wrb_context *pwrb_context;
        struct hwi_controller *phwi_ctrlr;
        itt_t itt;
+       uint16_t cri_index = 0;
        struct beiscsi_session *beiscsi_sess = beiscsi_conn->beiscsi_sess;
        dma_addr_t paddr;
 
@@ -4223,8 +4316,7 @@ 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 -
-                                       phba->fw_config.iscsi_cid_start);
+                                       beiscsi_conn->beiscsi_conn_cid);
                if (!io_task->pwrb_handle) {
                        beiscsi_log(phba, KERN_ERR,
                                    BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
@@ -4236,6 +4328,7 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
        } else {
                io_task->scsi_cmnd = NULL;
                if ((opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGIN) {
+                       beiscsi_conn->task = task;
                        if (!beiscsi_conn->login_in_progress) {
                                spin_lock(&phba->mgmt_sgl_lock);
                                io_task->psgl_handle = (struct sgl_handle *)
@@ -4257,8 +4350,7 @@ 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 -
-                                       phba->fw_config.iscsi_cid_start);
+                                       beiscsi_conn->beiscsi_conn_cid);
                                if (!io_task->pwrb_handle) {
                                        beiscsi_log(phba, KERN_ERR,
                                                    BEISCSI_LOG_IO |
@@ -4278,7 +4370,6 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
                                io_task->pwrb_handle =
                                                beiscsi_conn->plogin_wrb_handle;
                        }
-                       beiscsi_conn->task = task;
                } else {
                        spin_lock(&phba->mgmt_sgl_lock);
                        io_task->psgl_handle = alloc_mgmt_sgl_handle(phba);
@@ -4295,8 +4386,7 @@ 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 -
-                                       phba->fw_config.iscsi_cid_start);
+                                       beiscsi_conn->beiscsi_conn_cid);
                        if (!io_task->pwrb_handle) {
                                beiscsi_log(phba, KERN_ERR,
                                            BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
@@ -4324,12 +4414,13 @@ free_io_hndls:
 free_mgmt_hndls:
        spin_lock(&phba->mgmt_sgl_lock);
        free_mgmt_sgl_handle(phba, io_task->psgl_handle);
+       io_task->psgl_handle = NULL;
        spin_unlock(&phba->mgmt_sgl_lock);
 free_hndls:
        phwi_ctrlr = phba->phwi_ctrlr;
-       pwrb_context = &phwi_ctrlr->wrb_context[
-                       beiscsi_conn->beiscsi_conn_cid -
-                       phba->fw_config.iscsi_cid_start];
+       cri_index = BE_GET_CRI_FROM_CID(
+       beiscsi_conn->beiscsi_conn_cid);
+       pwrb_context = &phwi_ctrlr->wrb_context[cri_index];
        if (io_task->pwrb_handle)
                free_wrb_handle(phba, pwrb_context, io_task->pwrb_handle);
        io_task->pwrb_handle = NULL;
@@ -4351,7 +4442,6 @@ int beiscsi_iotask_v2(struct iscsi_task *task, struct scatterlist *sg,
        unsigned int doorbell = 0;
 
        pwrb = io_task->pwrb_handle->pwrb;
-       memset(pwrb, 0, sizeof(*pwrb));
 
        io_task->cmd_bhs->iscsi_hdr.exp_statsn = 0;
        io_task->bhs_len = sizeof(struct be_cmd_bhs);
@@ -4465,19 +4555,7 @@ static int beiscsi_mtask(struct iscsi_task *task)
        pwrb = io_task->pwrb_handle->pwrb;
        memset(pwrb, 0, sizeof(*pwrb));
 
-       if (chip_skh_r(phba->pcidev)) {
-               AMAP_SET_BITS(struct amap_iscsi_wrb_v2, cmdsn_itt, pwrb,
-                             be32_to_cpu(task->cmdsn));
-               AMAP_SET_BITS(struct amap_iscsi_wrb_v2, wrb_idx, pwrb,
-                             io_task->pwrb_handle->wrb_index);
-               AMAP_SET_BITS(struct amap_iscsi_wrb_v2, sgl_idx, pwrb,
-                             io_task->psgl_handle->sgl_index);
-               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);
-               pwrb_typeoffset = SKH_WRB_TYPE_OFFSET;
-       } else {
+       if (is_chip_be2_be3r(phba)) {
                AMAP_SET_BITS(struct amap_iscsi_wrb, cmdsn_itt, pwrb,
                              be32_to_cpu(task->cmdsn));
                AMAP_SET_BITS(struct amap_iscsi_wrb, wrb_idx, pwrb,
@@ -4489,6 +4567,18 @@ static int beiscsi_mtask(struct iscsi_task *task)
                AMAP_SET_BITS(struct amap_iscsi_wrb, ptr2nextwrb, pwrb,
                              io_task->pwrb_handle->nxt_wrb_index);
                pwrb_typeoffset = BE_WRB_TYPE_OFFSET;
+       } else {
+               AMAP_SET_BITS(struct amap_iscsi_wrb_v2, cmdsn_itt, pwrb,
+                             be32_to_cpu(task->cmdsn));
+               AMAP_SET_BITS(struct amap_iscsi_wrb_v2, wrb_idx, pwrb,
+                             io_task->pwrb_handle->wrb_index);
+               AMAP_SET_BITS(struct amap_iscsi_wrb_v2, sgl_idx, pwrb,
+                             io_task->psgl_handle->sgl_index);
+               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);
+               pwrb_typeoffset = SKH_WRB_TYPE_OFFSET;
        }
 
 
@@ -4501,19 +4591,19 @@ static int beiscsi_mtask(struct iscsi_task *task)
        case ISCSI_OP_NOOP_OUT:
                if (task->hdr->ttt != ISCSI_RESERVED_TAG) {
                        ADAPTER_SET_WRB_TYPE(pwrb, TGT_DM_CMD, pwrb_typeoffset);
-                       if (chip_skh_r(phba->pcidev))
-                               AMAP_SET_BITS(struct amap_iscsi_wrb_v2,
+                       if (is_chip_be2_be3r(phba))
+                               AMAP_SET_BITS(struct amap_iscsi_wrb,
                                              dmsg, pwrb, 1);
                        else
-                               AMAP_SET_BITS(struct amap_iscsi_wrb,
+                               AMAP_SET_BITS(struct amap_iscsi_wrb_v2,
                                              dmsg, pwrb, 1);
                } else {
                        ADAPTER_SET_WRB_TYPE(pwrb, INI_RD_CMD, pwrb_typeoffset);
-                       if (chip_skh_r(phba->pcidev))
-                               AMAP_SET_BITS(struct amap_iscsi_wrb_v2,
+                       if (is_chip_be2_be3r(phba))
+                               AMAP_SET_BITS(struct amap_iscsi_wrb,
                                              dmsg, pwrb, 0);
                        else
-                               AMAP_SET_BITS(struct amap_iscsi_wrb,
+                               AMAP_SET_BITS(struct amap_iscsi_wrb_v2,
                                              dmsg, pwrb, 0);
                }
                hwi_write_buffer(pwrb, task);
@@ -4540,9 +4630,9 @@ static int beiscsi_mtask(struct iscsi_task *task)
        }
 
        /* Set the task type */
-       io_task->wrb_type = (chip_skh_r(phba->pcidev)) ?
-               AMAP_GET_BITS(struct amap_iscsi_wrb_v2, type, pwrb) :
-               AMAP_GET_BITS(struct amap_iscsi_wrb, type, pwrb);
+       io_task->wrb_type = (is_chip_be2_be3r(phba)) ?
+               AMAP_GET_BITS(struct amap_iscsi_wrb, type, pwrb) :
+               AMAP_GET_BITS(struct amap_iscsi_wrb_v2, type, pwrb);
 
        doorbell |= cid & DB_WRB_POST_CID_MASK;
        doorbell |= (io_task->pwrb_handle->wrb_index &
@@ -4834,6 +4924,7 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev,
        case OC_SKH_ID1:
                phba->generation = BE_GEN4;
                phba->iotask_fn = beiscsi_iotask_v2;
+               break;
        default:
                phba->generation = 0;
        }
index 5946577..2c06ef3 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2005 - 2012 Emulex
+ * Copyright (C) 2005 - 2013 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -36,7 +36,7 @@
 
 #include "be.h"
 #define DRV_NAME               "be2iscsi"
-#define BUILD_STR              "10.0.272.0"
+#define BUILD_STR              "10.0.467.0"
 #define BE_NAME                        "Emulex OneConnect" \
                                "Open-iSCSI Driver version" BUILD_STR
 #define DRV_DESC               BE_NAME " " "Driver"
@@ -66,8 +66,9 @@
 
 #define MAX_CPUS               64
 #define BEISCSI_MAX_NUM_CPUS   7
-#define OC_SKH_MAX_NUM_CPUS    63
+#define OC_SKH_MAX_NUM_CPUS    31
 
+#define BEISCSI_VER_STRLEN 32
 
 #define BEISCSI_SGLIST_ELEMENTS        30
 
@@ -265,7 +266,9 @@ struct invalidate_command_table {
        unsigned short cid;
 } __packed;
 
-#define chip_skh_r(pdev)       (pdev->device == OC_SKH_ID1)
+#define chip_be2(phba)      (phba->generation == BE_GEN2)
+#define chip_be3_r(phba)    (phba->generation == BE_GEN3)
+#define is_chip_be2_be3r(phba) (chip_be3_r(phba) || (chip_be2(phba)))
 struct beiscsi_hba {
        struct hba_parameters params;
        struct hwi_controller *phwi_ctrlr;
@@ -304,10 +307,15 @@ struct beiscsi_hba {
        unsigned short avlbl_cids;
        unsigned short cid_alloc;
        unsigned short cid_free;
-       struct beiscsi_conn *conn_table[BE2_MAX_SESSIONS * 2];
        struct list_head hba_queue;
+#define BE_MAX_SESSION 2048
+#define BE_SET_CID_TO_CRI(cri_index, cid) \
+                         (phba->cid_to_cri_map[cid] = cri_index)
+#define BE_GET_CRI_FROM_CID(cid) (phba->cid_to_cri_map[cid])
+       unsigned short cid_to_cri_map[BE_MAX_SESSION];
        unsigned short *cid_array;
        struct iscsi_endpoint **ep_array;
+       struct beiscsi_conn **conn_table;
        struct iscsi_boot_kset *boot_kset;
        struct Scsi_Host *shost;
        struct iscsi_iface *ipv4_iface;
@@ -339,6 +347,7 @@ struct beiscsi_hba {
        struct delayed_work beiscsi_hw_check_task;
 
        u8 mac_address[ETH_ALEN];
+       char fw_ver_str[BEISCSI_VER_STRLEN];
        char wq_name[20];
        struct workqueue_struct *wq;    /* The actuak work queue */
        struct be_ctrl_info ctrl;
@@ -563,7 +572,7 @@ struct hwi_async_pdu_context {
         * This is a varying size list! Do not add anything
         * after this entry!!
         */
-       struct hwi_async_entry async_entry[BE2_MAX_SESSIONS * 2];
+       struct hwi_async_entry *async_entry;
 };
 
 #define PDUCQE_CODE_MASK       0x0000003F
@@ -749,6 +758,8 @@ void
 free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle);
 
 void beiscsi_process_all_cqs(struct work_struct *work);
+void beiscsi_free_mgmt_task_handles(struct beiscsi_conn *beiscsi_conn,
+                                    struct iscsi_task *task);
 
 static inline bool beiscsi_error(struct beiscsi_hba *phba)
 {
@@ -933,7 +944,7 @@ struct hwi_controller {
        struct sgl_handle *psgl_handle_base;
        unsigned int wrb_mem_index;
 
-       struct hwi_wrb_context wrb_context[BE2_MAX_SESSIONS * 2];
+       struct hwi_wrb_context *wrb_context;
        struct mcc_wrb *pmcc_wrb_base;
        struct be_ring default_pdu_hdr;
        struct be_ring default_pdu_data;
@@ -970,9 +981,7 @@ struct hwi_context_memory {
        struct be_queue_info be_def_hdrq;
        struct be_queue_info be_def_dataq;
 
-       struct be_queue_info be_wrbq[BE2_MAX_SESSIONS];
-       struct be_mcc_wrb_context *pbe_mcc_context;
-
+       struct be_queue_info *be_wrbq;
        struct hwi_async_pdu_context *pasync_ctx;
 };
 
index 55cc990..245a959 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2005 - 2012 Emulex
+ * Copyright (C) 2005 - 2013 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -368,6 +368,8 @@ int mgmt_check_supported_fw(struct be_ctrl_info *ctrl,
                beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
                            "BM_%d : phba->fw_config.iscsi_features = %d\n",
                            phba->fw_config.iscsi_features);
+               memcpy(phba->fw_ver_str, resp->params.hba_attribs.
+                      firmware_version_string, BEISCSI_VER_STRLEN);
        } else
                beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
                            "BG_%d :  Failed in mgmt_check_supported_fw\n");
@@ -1259,6 +1261,45 @@ beiscsi_drvr_ver_disp(struct device *dev, struct device_attribute *attr,
        return snprintf(buf, PAGE_SIZE, BE_NAME "\n");
 }
 
+/**
+ * beiscsi_fw_ver_disp()- Display Firmware Version
+ * @dev: ptr to device not used.
+ * @attr: device attribute, not used.
+ * @buf: contains formatted text Firmware version
+ *
+ * return
+ * size of the formatted string
+ **/
+ssize_t
+beiscsi_fw_ver_disp(struct device *dev, struct device_attribute *attr,
+                    char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(dev);
+       struct beiscsi_hba *phba = iscsi_host_priv(shost);
+
+       return snprintf(buf, PAGE_SIZE, "%s\n", phba->fw_ver_str);
+}
+
+/**
+ * beiscsi_active_cid_disp()- Display Sessions Active
+ * @dev: ptr to device not used.
+ * @attr: device attribute, not used.
+ * @buf: contains formatted text Session Count
+ *
+ * return
+ * size of the formatted string
+ **/
+ssize_t
+beiscsi_active_cid_disp(struct device *dev, struct device_attribute *attr,
+                        char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(dev);
+       struct beiscsi_hba *phba = iscsi_host_priv(shost);
+
+       return snprintf(buf, PAGE_SIZE, "%d\n",
+                      (phba->params.cxns_per_ctrl - phba->avlbl_cids));
+}
+
 /**
  * beiscsi_adap_family_disp()- Display adapter family.
  * @dev: ptr to device to get priv structure
index 2e4968a..04af7e7 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2005 - 2012 Emulex
+ * Copyright (C) 2005 - 2013 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -156,25 +156,25 @@ union invalidate_commands_params {
 } __packed;
 
 struct mgmt_hba_attributes {
-       u8 flashrom_version_string[32];
-       u8 manufacturer_name[32];
+       u8 flashrom_version_string[BEISCSI_VER_STRLEN];
+       u8 manufacturer_name[BEISCSI_VER_STRLEN];
        u32 supported_modes;
        u8 seeprom_version_lo;
        u8 seeprom_version_hi;
        u8 rsvd0[2];
        u32 fw_cmd_data_struct_version;
        u32 ep_fw_data_struct_version;
-       u32 future_reserved[12];
+       u8 ncsi_version_string[12];
        u32 default_extended_timeout;
-       u8 controller_model_number[32];
+       u8 controller_model_number[BEISCSI_VER_STRLEN];
        u8 controller_description[64];
-       u8 controller_serial_number[32];
-       u8 ip_version_string[32];
-       u8 firmware_version_string[32];
-       u8 bios_version_string[32];
-       u8 redboot_version_string[32];
-       u8 driver_version_string[32];
-       u8 fw_on_flash_version_string[32];
+       u8 controller_serial_number[BEISCSI_VER_STRLEN];
+       u8 ip_version_string[BEISCSI_VER_STRLEN];
+       u8 firmware_version_string[BEISCSI_VER_STRLEN];
+       u8 bios_version_string[BEISCSI_VER_STRLEN];
+       u8 redboot_version_string[BEISCSI_VER_STRLEN];
+       u8 driver_version_string[BEISCSI_VER_STRLEN];
+       u8 fw_on_flash_version_string[BEISCSI_VER_STRLEN];
        u32 functionalities_supported;
        u16 max_cdblength;
        u8 asic_revision;
@@ -190,7 +190,8 @@ struct mgmt_hba_attributes {
        u32 firmware_post_status;
        u32 hba_mtu[8];
        u8 iscsi_features;
-       u8 future_u8[3];
+       u8 asic_generation;
+       u8 future_u8[2];
        u32 future_u32[3];
 } __packed;
 
@@ -207,7 +208,7 @@ struct mgmt_controller_attributes {
        u64 unique_identifier;
        u8 netfilters;
        u8 rsvd0[3];
-       u8 future_u32[4];
+       u32 future_u32[4];
 } __packed;
 
 struct be_mgmt_controller_attributes {
@@ -311,6 +312,12 @@ int mgmt_set_vlan(struct beiscsi_hba *phba, uint16_t vlan_tag);
 ssize_t beiscsi_drvr_ver_disp(struct device *dev,
                               struct device_attribute *attr, char *buf);
 
+ssize_t beiscsi_fw_ver_disp(struct device *dev,
+                            struct device_attribute *attr, char *buf);
+
+ssize_t beiscsi_active_cid_disp(struct device *dev,
+                                struct device_attribute *attr, char *buf);
+
 ssize_t beiscsi_adap_family_disp(struct device *dev,
                                  struct device_attribute *attr, char *buf);
 
index 11596b2..08b22a9 100644 (file)
@@ -2,7 +2,7 @@
 #define _BNX2FC_H_
 /* bnx2fc.h: Broadcom NetXtreme II Linux FCoE offload driver.
  *
- * Copyright (c) 2008 - 2011 Broadcom Corporation
+ * Copyright (c) 2008 - 2013 Broadcom 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
 #include "bnx2fc_constants.h"
 
 #define BNX2FC_NAME            "bnx2fc"
-#define BNX2FC_VERSION         "1.0.13"
+#define BNX2FC_VERSION         "1.0.14"
 
 #define PFX                    "bnx2fc: "
 
+#define BCM_CHIP_LEN           16
+
 #define BNX2X_DOORBELL_PCI_BAR         2
 
 #define BNX2FC_MAX_BD_LEN              0xffff
@@ -241,6 +243,8 @@ struct bnx2fc_hba {
        int wait_for_link_down;
        int num_ofld_sess;
        struct list_head vports;
+
+       char chip_num[BCM_CHIP_LEN];
 };
 
 struct bnx2fc_interface {
index bdbbb13..b1c9a4f 100644 (file)
@@ -3,7 +3,7 @@
  * This file contains helper routines that handle ELS requests
  * and responses.
  *
- * Copyright (c) 2008 - 2011 Broadcom Corporation
+ * Copyright (c) 2008 - 2013 Broadcom 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 7dffec1..69ac554 100644 (file)
@@ -3,7 +3,7 @@
  * cnic modules to create FCoE instances, send/receive non-offloaded
  * FIP/FCoE packets, listen to link events etc.
  *
- * Copyright (c) 2008 - 2011 Broadcom Corporation
+ * Copyright (c) 2008 - 2013 Broadcom 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
@@ -22,7 +22,7 @@ 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 21, 2012"
+#define DRV_MODULE_RELDATE     "Mar 08, 2013"
 
 
 static char version[] =
@@ -679,6 +679,7 @@ static int bnx2fc_shost_config(struct fc_lport *lport, struct device *dev)
 {
        struct fcoe_port *port = lport_priv(lport);
        struct bnx2fc_interface *interface = port->priv;
+       struct bnx2fc_hba *hba = interface->hba;
        struct Scsi_Host *shost = lport->host;
        int rc = 0;
 
@@ -699,8 +700,9 @@ static int bnx2fc_shost_config(struct fc_lport *lport, struct device *dev)
        }
        if (!lport->vport)
                fc_host_max_npiv_vports(lport->host) = USHRT_MAX;
-       sprintf(fc_host_symbolic_name(lport->host), "%s v%s over %s",
-               BNX2FC_NAME, BNX2FC_VERSION,
+       snprintf(fc_host_symbolic_name(lport->host), 256,
+                "%s (Broadcom %s) v%s over %s",
+               BNX2FC_NAME, hba->chip_num, BNX2FC_VERSION,
                interface->netdev->name);
 
        return 0;
@@ -1656,23 +1658,60 @@ mem_err:
 static int bnx2fc_bind_pcidev(struct bnx2fc_hba *hba)
 {
        struct cnic_dev *cnic;
+       struct pci_dev *pdev;
 
        if (!hba->cnic) {
                printk(KERN_ERR PFX "cnic is NULL\n");
                return -ENODEV;
        }
        cnic = hba->cnic;
-       hba->pcidev = cnic->pcidev;
-       if (hba->pcidev)
-               pci_dev_get(hba->pcidev);
+       pdev = hba->pcidev = cnic->pcidev;
+       if (!hba->pcidev)
+               return -ENODEV;
 
+       switch (pdev->device) {
+       case PCI_DEVICE_ID_NX2_57710:
+               strncpy(hba->chip_num, "BCM57710", BCM_CHIP_LEN);
+               break;
+       case PCI_DEVICE_ID_NX2_57711:
+               strncpy(hba->chip_num, "BCM57711", BCM_CHIP_LEN);
+               break;
+       case PCI_DEVICE_ID_NX2_57712:
+       case PCI_DEVICE_ID_NX2_57712_MF:
+       case PCI_DEVICE_ID_NX2_57712_VF:
+               strncpy(hba->chip_num, "BCM57712", BCM_CHIP_LEN);
+               break;
+       case PCI_DEVICE_ID_NX2_57800:
+       case PCI_DEVICE_ID_NX2_57800_MF:
+       case PCI_DEVICE_ID_NX2_57800_VF:
+               strncpy(hba->chip_num, "BCM57800", BCM_CHIP_LEN);
+               break;
+       case PCI_DEVICE_ID_NX2_57810:
+       case PCI_DEVICE_ID_NX2_57810_MF:
+       case PCI_DEVICE_ID_NX2_57810_VF:
+               strncpy(hba->chip_num, "BCM57810", BCM_CHIP_LEN);
+               break;
+       case PCI_DEVICE_ID_NX2_57840:
+       case PCI_DEVICE_ID_NX2_57840_MF:
+       case PCI_DEVICE_ID_NX2_57840_VF:
+       case PCI_DEVICE_ID_NX2_57840_2_20:
+       case PCI_DEVICE_ID_NX2_57840_4_10:
+               strncpy(hba->chip_num, "BCM57840", BCM_CHIP_LEN);
+               break;
+       default:
+               pr_err(PFX "Unknown device id 0x%x\n", pdev->device);
+               break;
+       }
+       pci_dev_get(hba->pcidev);
        return 0;
 }
 
 static void bnx2fc_unbind_pcidev(struct bnx2fc_hba *hba)
 {
-       if (hba->pcidev)
+       if (hba->pcidev) {
+               hba->chip_num[0] = '\0';
                pci_dev_put(hba->pcidev);
+       }
        hba->pcidev = NULL;
 }
 
index 50510ff..c0d035a 100644 (file)
@@ -2,7 +2,7 @@
  * This file contains the code that low level functions that interact
  * with 57712 FCoE firmware.
  *
- * Copyright (c) 2008 - 2011 Broadcom Corporation
+ * Copyright (c) 2008 - 2013 Broadcom 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
@@ -126,7 +126,11 @@ int bnx2fc_send_fw_fcoe_init_msg(struct bnx2fc_hba *hba)
        fcoe_init3.error_bit_map_lo = 0xffffffff;
        fcoe_init3.error_bit_map_hi = 0xffffffff;
 
-       fcoe_init3.perf_config = 1;
+       /*
+        * enable both cached connection and cached tasks
+        * 0 = none, 1 = cached connection, 2 = cached tasks, 3 = both
+        */
+       fcoe_init3.perf_config = 3;
 
        kwqe_arr[0] = (struct kwqe *) &fcoe_init1;
        kwqe_arr[1] = (struct kwqe *) &fcoe_init2;
index 723a9a8..575142e 100644 (file)
@@ -1,7 +1,7 @@
 /* bnx2fc_io.c: Broadcom NetXtreme II Linux FCoE offload driver.
  * IO manager and SCSI IO processing.
  *
- * Copyright (c) 2008 - 2011 Broadcom Corporation
+ * Copyright (c) 2008 - 2013 Broadcom 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
@@ -1270,8 +1270,11 @@ int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd)
 
        spin_lock_bh(&tgt->tgt_lock);
        io_req->wait_for_comp = 0;
-       if (!(test_and_set_bit(BNX2FC_FLAG_ABTS_DONE,
-                                   &io_req->req_flags))) {
+       if (test_bit(BNX2FC_FLAG_IO_COMPL, &io_req->req_flags)) {
+               BNX2FC_IO_DBG(io_req, "IO completed in a different context\n");
+               rc = SUCCESS;
+       } else if (!(test_and_set_bit(BNX2FC_FLAG_ABTS_DONE,
+                                     &io_req->req_flags))) {
                /* Let the scsi-ml try to recover this command */
                printk(KERN_ERR PFX "abort failed, xid = 0x%x\n",
                       io_req->xid);
index c57a3bb..4d93177 100644 (file)
@@ -2,7 +2,7 @@
  * Handles operations such as session offload/upload etc, and manages
  * session resources such as connection id and qp resources.
  *
- * Copyright (c) 2008 - 2011 Broadcom Corporation
+ * Copyright (c) 2008 - 2013 Broadcom 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 0f9c041..372a67d 100644 (file)
@@ -114,7 +114,7 @@ struct csio_lnode_stats {
        uint32_t        n_rnode_match;  /* matched rnode */
        uint32_t        n_dev_loss_tmo; /* Device loss timeout */
        uint32_t        n_fdmi_err;     /* fdmi err */
-       uint32_t        n_evt_fw[PROTO_ERR_IMPL_LOGO];  /* fw events */
+       uint32_t        n_evt_fw[PROTO_ERR_IMPL_LOGO + 1];      /* fw events */
        enum csio_ln_ev n_evt_sm[CSIO_LNE_MAX_EVENT];   /* State m/c events */
        uint32_t        n_rnode_alloc;  /* rnode allocated */
        uint32_t        n_rnode_free;   /* rnode freed */
index 6594009..4334342 100644 (file)
@@ -63,7 +63,7 @@ struct csio_rnode_stats {
        uint32_t        n_err_nomem;    /* error nomem */
        uint32_t        n_evt_unexp;    /* unexpected event */
        uint32_t        n_evt_drop;     /* unexpected event */
-       uint32_t        n_evt_fw[PROTO_ERR_IMPL_LOGO];  /* fw events */
+       uint32_t        n_evt_fw[PROTO_ERR_IMPL_LOGO + 1];      /* fw events */
        enum csio_rn_ev n_evt_sm[CSIO_RNFE_MAX_EVENT];  /* State m/c events */
        uint32_t        n_lun_rst;      /* Number of resets of
                                         * of LUNs under this
index 98436c3..b6d1f92 100644 (file)
@@ -38,7 +38,7 @@
 
 #define DRV_NAME               "fnic"
 #define DRV_DESCRIPTION                "Cisco FCoE HBA Driver"
-#define DRV_VERSION            "1.5.0.2"
+#define DRV_VERSION            "1.5.0.22"
 #define PFX                    DRV_NAME ": "
 #define DFX                     DRV_NAME "%d: "
 
@@ -192,6 +192,18 @@ enum fnic_state {
 
 struct mempool;
 
+enum fnic_evt {
+       FNIC_EVT_START_VLAN_DISC = 1,
+       FNIC_EVT_START_FCF_DISC = 2,
+       FNIC_EVT_MAX,
+};
+
+struct fnic_event {
+       struct list_head list;
+       struct fnic *fnic;
+       enum fnic_evt event;
+};
+
 /* Per-instance private data structure */
 struct fnic {
        struct fc_lport *lport;
@@ -254,6 +266,18 @@ struct fnic {
        struct sk_buff_head frame_queue;
        struct sk_buff_head tx_queue;
 
+       /*** FIP related data members  -- start ***/
+       void (*set_vlan)(struct fnic *, u16 vlan);
+       struct work_struct      fip_frame_work;
+       struct sk_buff_head     fip_frame_queue;
+       struct timer_list       fip_timer;
+       struct list_head        vlans;
+       spinlock_t              vlans_lock;
+
+       struct work_struct      event_work;
+       struct list_head        evlist;
+       /*** FIP related data members  -- end ***/
+
        /* copy work queue cache line section */
        ____cacheline_aligned struct vnic_wq_copy wq_copy[FNIC_WQ_COPY_MAX];
        /* completion queue cache line section */
@@ -278,6 +302,7 @@ static inline struct fnic *fnic_from_ctlr(struct fcoe_ctlr *fip)
 }
 
 extern struct workqueue_struct *fnic_event_queue;
+extern struct workqueue_struct *fnic_fip_queue;
 extern struct device_attribute *fnic_attrs[];
 
 void fnic_clear_intr_mode(struct fnic *fnic);
@@ -289,6 +314,7 @@ int fnic_send(struct fc_lport *, struct fc_frame *);
 void fnic_free_wq_buf(struct vnic_wq *wq, struct vnic_wq_buf *buf);
 void fnic_handle_frame(struct work_struct *work);
 void fnic_handle_link(struct work_struct *work);
+void fnic_handle_event(struct work_struct *work);
 int fnic_rq_cmpl_handler(struct fnic *fnic, int);
 int fnic_alloc_rq_frame(struct vnic_rq *rq);
 void fnic_free_rq_buf(struct vnic_rq *rq, struct vnic_rq_buf *buf);
@@ -321,6 +347,12 @@ void fnic_handle_link_event(struct fnic *fnic);
 
 int fnic_is_abts_pending(struct fnic *, struct scsi_cmnd *);
 
+void fnic_handle_fip_frame(struct work_struct *work);
+void fnic_handle_fip_event(struct fnic *fnic);
+void fnic_fcoe_reset_vlans(struct fnic *fnic);
+void fnic_fcoe_evlist_free(struct fnic *fnic);
+extern void fnic_handle_fip_timer(struct fnic *fnic);
+
 static inline int
 fnic_chk_state_flags_locked(struct fnic *fnic, unsigned long st_flags)
 {
index 483eb9d..006fa92 100644 (file)
 #include <scsi/libfc.h>
 #include "fnic_io.h"
 #include "fnic.h"
+#include "fnic_fip.h"
 #include "cq_enet_desc.h"
 #include "cq_exch_desc.h"
 
+static u8 fcoe_all_fcfs[ETH_ALEN];
+struct workqueue_struct *fnic_fip_queue;
 struct workqueue_struct *fnic_event_queue;
 
 static void fnic_set_eth_mode(struct fnic *);
+static void fnic_fcoe_send_vlan_req(struct fnic *fnic);
+static void fnic_fcoe_start_fcf_disc(struct fnic *fnic);
+static void fnic_fcoe_process_vlan_resp(struct fnic *fnic, struct sk_buff *);
+static int fnic_fcoe_vlan_check(struct fnic *fnic, u16 flag);
+static int fnic_fcoe_handle_fip_frame(struct fnic *fnic, struct sk_buff *skb);
 
 void fnic_handle_link(struct work_struct *work)
 {
@@ -69,6 +77,11 @@ void fnic_handle_link(struct work_struct *work)
                                FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host,
                                             "link down\n");
                                fcoe_ctlr_link_down(&fnic->ctlr);
+                               if (fnic->config.flags & VFCF_FIP_CAPABLE) {
+                                       /* start FCoE VLAN discovery */
+                                       fnic_fcoe_send_vlan_req(fnic);
+                                       return;
+                               }
                                FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host,
                                             "link up\n");
                                fcoe_ctlr_link_up(&fnic->ctlr);
@@ -79,6 +92,11 @@ void fnic_handle_link(struct work_struct *work)
        } else if (fnic->link_status) {
                /* DOWN -> UP */
                spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+               if (fnic->config.flags & VFCF_FIP_CAPABLE) {
+                       /* start FCoE VLAN discovery */
+                       fnic_fcoe_send_vlan_req(fnic);
+                       return;
+               }
                FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, "link up\n");
                fcoe_ctlr_link_up(&fnic->ctlr);
        } else {
@@ -128,6 +146,441 @@ void fnic_handle_frame(struct work_struct *work)
        }
 }
 
+void fnic_fcoe_evlist_free(struct fnic *fnic)
+{
+       struct fnic_event *fevt = NULL;
+       struct fnic_event *next = NULL;
+       unsigned long flags;
+
+       spin_lock_irqsave(&fnic->fnic_lock, flags);
+       if (list_empty(&fnic->evlist)) {
+               spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+               return;
+       }
+
+       list_for_each_entry_safe(fevt, next, &fnic->evlist, list) {
+               list_del(&fevt->list);
+               kfree(fevt);
+       }
+       spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+}
+
+void fnic_handle_event(struct work_struct *work)
+{
+       struct fnic *fnic = container_of(work, struct fnic, event_work);
+       struct fnic_event *fevt = NULL;
+       struct fnic_event *next = NULL;
+       unsigned long flags;
+
+       spin_lock_irqsave(&fnic->fnic_lock, flags);
+       if (list_empty(&fnic->evlist)) {
+               spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+               return;
+       }
+
+       list_for_each_entry_safe(fevt, next, &fnic->evlist, list) {
+               if (fnic->stop_rx_link_events) {
+                       list_del(&fevt->list);
+                       kfree(fevt);
+                       spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+                       return;
+               }
+               /*
+                * If we're in a transitional state, just re-queue and return.
+                * The queue will be serviced when we get to a stable state.
+                */
+               if (fnic->state != FNIC_IN_FC_MODE &&
+                   fnic->state != FNIC_IN_ETH_MODE) {
+                       spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+                       return;
+               }
+
+               list_del(&fevt->list);
+               switch (fevt->event) {
+               case FNIC_EVT_START_VLAN_DISC:
+                       spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+                       fnic_fcoe_send_vlan_req(fnic);
+                       spin_lock_irqsave(&fnic->fnic_lock, flags);
+                       break;
+               case FNIC_EVT_START_FCF_DISC:
+                       FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host,
+                                 "Start FCF Discovery\n");
+                       fnic_fcoe_start_fcf_disc(fnic);
+                       break;
+               default:
+                       FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host,
+                                 "Unknown event 0x%x\n", fevt->event);
+                       break;
+               }
+               kfree(fevt);
+       }
+       spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+}
+
+/**
+ * Check if the Received FIP FLOGI frame is rejected
+ * @fip: The FCoE controller that received the frame
+ * @skb: The received FIP frame
+ *
+ * Returns non-zero if the frame is rejected with unsupported cmd with
+ * insufficient resource els explanation.
+ */
+static inline int is_fnic_fip_flogi_reject(struct fcoe_ctlr *fip,
+                                        struct sk_buff *skb)
+{
+       struct fc_lport *lport = fip->lp;
+       struct fip_header *fiph;
+       struct fc_frame_header *fh = NULL;
+       struct fip_desc *desc;
+       struct fip_encaps *els;
+       enum fip_desc_type els_dtype = 0;
+       u16 op;
+       u8 els_op;
+       u8 sub;
+
+       size_t els_len = 0;
+       size_t rlen;
+       size_t dlen = 0;
+
+       if (skb_linearize(skb))
+               return 0;
+
+       if (skb->len < sizeof(*fiph))
+               return 0;
+
+       fiph = (struct fip_header *)skb->data;
+       op = ntohs(fiph->fip_op);
+       sub = fiph->fip_subcode;
+
+       if (op != FIP_OP_LS)
+               return 0;
+
+       if (sub != FIP_SC_REP)
+               return 0;
+
+       rlen = ntohs(fiph->fip_dl_len) * 4;
+       if (rlen + sizeof(*fiph) > skb->len)
+               return 0;
+
+       desc = (struct fip_desc *)(fiph + 1);
+       dlen = desc->fip_dlen * FIP_BPW;
+
+       if (desc->fip_dtype == FIP_DT_FLOGI) {
+
+               shost_printk(KERN_DEBUG, lport->host,
+                         " FIP TYPE FLOGI: fab name:%llx "
+                         "vfid:%d map:%x\n",
+                         fip->sel_fcf->fabric_name, fip->sel_fcf->vfid,
+                         fip->sel_fcf->fc_map);
+               if (dlen < sizeof(*els) + sizeof(*fh) + 1)
+                       return 0;
+
+               els_len = dlen - sizeof(*els);
+               els = (struct fip_encaps *)desc;
+               fh = (struct fc_frame_header *)(els + 1);
+               els_dtype = desc->fip_dtype;
+
+               if (!fh)
+                       return 0;
+
+               /*
+                * ELS command code, reason and explanation should be = Reject,
+                * unsupported command and insufficient resource
+                */
+               els_op = *(u8 *)(fh + 1);
+               if (els_op == ELS_LS_RJT) {
+                       shost_printk(KERN_INFO, lport->host,
+                                 "Flogi Request Rejected by Switch\n");
+                       return 1;
+               }
+               shost_printk(KERN_INFO, lport->host,
+                               "Flogi Request Accepted by Switch\n");
+       }
+       return 0;
+}
+
+static void fnic_fcoe_send_vlan_req(struct fnic *fnic)
+{
+       struct fcoe_ctlr *fip = &fnic->ctlr;
+       struct sk_buff *skb;
+       char *eth_fr;
+       int fr_len;
+       struct fip_vlan *vlan;
+       u64 vlan_tov;
+
+       fnic_fcoe_reset_vlans(fnic);
+       fnic->set_vlan(fnic, 0);
+       FNIC_FCS_DBG(KERN_INFO, fnic->lport->host,
+                 "Sending VLAN request...\n");
+       skb = dev_alloc_skb(sizeof(struct fip_vlan));
+       if (!skb)
+               return;
+
+       fr_len = sizeof(*vlan);
+       eth_fr = (char *)skb->data;
+       vlan = (struct fip_vlan *)eth_fr;
+
+       memset(vlan, 0, sizeof(*vlan));
+       memcpy(vlan->eth.h_source, fip->ctl_src_addr, ETH_ALEN);
+       memcpy(vlan->eth.h_dest, fcoe_all_fcfs, ETH_ALEN);
+       vlan->eth.h_proto = htons(ETH_P_FIP);
+
+       vlan->fip.fip_ver = FIP_VER_ENCAPS(FIP_VER);
+       vlan->fip.fip_op = htons(FIP_OP_VLAN);
+       vlan->fip.fip_subcode = FIP_SC_VL_REQ;
+       vlan->fip.fip_dl_len = htons(sizeof(vlan->desc) / FIP_BPW);
+
+       vlan->desc.mac.fd_desc.fip_dtype = FIP_DT_MAC;
+       vlan->desc.mac.fd_desc.fip_dlen = sizeof(vlan->desc.mac) / FIP_BPW;
+       memcpy(&vlan->desc.mac.fd_mac, fip->ctl_src_addr, ETH_ALEN);
+
+       vlan->desc.wwnn.fd_desc.fip_dtype = FIP_DT_NAME;
+       vlan->desc.wwnn.fd_desc.fip_dlen = sizeof(vlan->desc.wwnn) / FIP_BPW;
+       put_unaligned_be64(fip->lp->wwnn, &vlan->desc.wwnn.fd_wwn);
+
+       skb_put(skb, sizeof(*vlan));
+       skb->protocol = htons(ETH_P_FIP);
+       skb_reset_mac_header(skb);
+       skb_reset_network_header(skb);
+       fip->send(fip, skb);
+
+       /* set a timer so that we can retry if there no response */
+       vlan_tov = jiffies + msecs_to_jiffies(FCOE_CTLR_FIPVLAN_TOV);
+       mod_timer(&fnic->fip_timer, round_jiffies(vlan_tov));
+}
+
+static void fnic_fcoe_process_vlan_resp(struct fnic *fnic, struct sk_buff *skb)
+{
+       struct fcoe_ctlr *fip = &fnic->ctlr;
+       struct fip_header *fiph;
+       struct fip_desc *desc;
+       u16 vid;
+       size_t rlen;
+       size_t dlen;
+       struct fcoe_vlan *vlan;
+       u64 sol_time;
+       unsigned long flags;
+
+       FNIC_FCS_DBG(KERN_INFO, fnic->lport->host,
+                 "Received VLAN response...\n");
+
+       fiph = (struct fip_header *) skb->data;
+
+       FNIC_FCS_DBG(KERN_INFO, fnic->lport->host,
+                 "Received VLAN response... OP 0x%x SUB_OP 0x%x\n",
+                 ntohs(fiph->fip_op), fiph->fip_subcode);
+
+       rlen = ntohs(fiph->fip_dl_len) * 4;
+       fnic_fcoe_reset_vlans(fnic);
+       spin_lock_irqsave(&fnic->vlans_lock, flags);
+       desc = (struct fip_desc *)(fiph + 1);
+       while (rlen > 0) {
+               dlen = desc->fip_dlen * FIP_BPW;
+               switch (desc->fip_dtype) {
+               case FIP_DT_VLAN:
+                       vid = ntohs(((struct fip_vlan_desc *)desc)->fd_vlan);
+                       shost_printk(KERN_INFO, fnic->lport->host,
+                                 "process_vlan_resp: FIP VLAN %d\n", vid);
+                       vlan = kmalloc(sizeof(*vlan),
+                                                       GFP_ATOMIC);
+                       if (!vlan) {
+                               /* retry from timer */
+                               spin_unlock_irqrestore(&fnic->vlans_lock,
+                                                       flags);
+                               goto out;
+                       }
+                       memset(vlan, 0, sizeof(struct fcoe_vlan));
+                       vlan->vid = vid & 0x0fff;
+                       vlan->state = FIP_VLAN_AVAIL;
+                       list_add_tail(&vlan->list, &fnic->vlans);
+                       break;
+               }
+               desc = (struct fip_desc *)((char *)desc + dlen);
+               rlen -= dlen;
+       }
+
+       /* any VLAN descriptors present ? */
+       if (list_empty(&fnic->vlans)) {
+               /* retry from timer */
+               FNIC_FCS_DBG(KERN_INFO, fnic->lport->host,
+                         "No VLAN descriptors in FIP VLAN response\n");
+               spin_unlock_irqrestore(&fnic->vlans_lock, flags);
+               goto out;
+       }
+
+       vlan = list_first_entry(&fnic->vlans, struct fcoe_vlan, list);
+       fnic->set_vlan(fnic, vlan->vid);
+       vlan->state = FIP_VLAN_SENT; /* sent now */
+       vlan->sol_count++;
+       spin_unlock_irqrestore(&fnic->vlans_lock, flags);
+
+       /* start the solicitation */
+       fcoe_ctlr_link_up(fip);
+
+       sol_time = jiffies + msecs_to_jiffies(FCOE_CTLR_START_DELAY);
+       mod_timer(&fnic->fip_timer, round_jiffies(sol_time));
+out:
+       return;
+}
+
+static void fnic_fcoe_start_fcf_disc(struct fnic *fnic)
+{
+       unsigned long flags;
+       struct fcoe_vlan *vlan;
+       u64 sol_time;
+
+       spin_lock_irqsave(&fnic->vlans_lock, flags);
+       vlan = list_first_entry(&fnic->vlans, struct fcoe_vlan, list);
+       fnic->set_vlan(fnic, vlan->vid);
+       vlan->state = FIP_VLAN_SENT; /* sent now */
+       vlan->sol_count = 1;
+       spin_unlock_irqrestore(&fnic->vlans_lock, flags);
+
+       /* start the solicitation */
+       fcoe_ctlr_link_up(&fnic->ctlr);
+
+       sol_time = jiffies + msecs_to_jiffies(FCOE_CTLR_START_DELAY);
+       mod_timer(&fnic->fip_timer, round_jiffies(sol_time));
+}
+
+static int fnic_fcoe_vlan_check(struct fnic *fnic, u16 flag)
+{
+       unsigned long flags;
+       struct fcoe_vlan *fvlan;
+
+       spin_lock_irqsave(&fnic->vlans_lock, flags);
+       if (list_empty(&fnic->vlans)) {
+               spin_unlock_irqrestore(&fnic->vlans_lock, flags);
+               return -EINVAL;
+       }
+
+       fvlan = list_first_entry(&fnic->vlans, struct fcoe_vlan, list);
+       if (fvlan->state == FIP_VLAN_USED) {
+               spin_unlock_irqrestore(&fnic->vlans_lock, flags);
+               return 0;
+       }
+
+       if (fvlan->state == FIP_VLAN_SENT) {
+               fvlan->state = FIP_VLAN_USED;
+               spin_unlock_irqrestore(&fnic->vlans_lock, flags);
+               return 0;
+       }
+       spin_unlock_irqrestore(&fnic->vlans_lock, flags);
+       return -EINVAL;
+}
+
+static void fnic_event_enq(struct fnic *fnic, enum fnic_evt ev)
+{
+       struct fnic_event *fevt;
+       unsigned long flags;
+
+       fevt = kmalloc(sizeof(*fevt), GFP_ATOMIC);
+       if (!fevt)
+               return;
+
+       fevt->fnic = fnic;
+       fevt->event = ev;
+
+       spin_lock_irqsave(&fnic->fnic_lock, flags);
+       list_add_tail(&fevt->list, &fnic->evlist);
+       spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+
+       schedule_work(&fnic->event_work);
+}
+
+static int fnic_fcoe_handle_fip_frame(struct fnic *fnic, struct sk_buff *skb)
+{
+       struct fip_header *fiph;
+       int ret = 1;
+       u16 op;
+       u8 sub;
+
+       if (!skb || !(skb->data))
+               return -1;
+
+       if (skb_linearize(skb))
+               goto drop;
+
+       fiph = (struct fip_header *)skb->data;
+       op = ntohs(fiph->fip_op);
+       sub = fiph->fip_subcode;
+
+       if (FIP_VER_DECAPS(fiph->fip_ver) != FIP_VER)
+               goto drop;
+
+       if (ntohs(fiph->fip_dl_len) * FIP_BPW + sizeof(*fiph) > skb->len)
+               goto drop;
+
+       if (op == FIP_OP_DISC && sub == FIP_SC_ADV) {
+               if (fnic_fcoe_vlan_check(fnic, ntohs(fiph->fip_flags)))
+                       goto drop;
+               /* pass it on to fcoe */
+               ret = 1;
+       } else if (op == FIP_OP_VLAN && sub == FIP_SC_VL_REP) {
+               /* set the vlan as used */
+               fnic_fcoe_process_vlan_resp(fnic, skb);
+               ret = 0;
+       } else if (op == FIP_OP_CTRL && sub == FIP_SC_CLR_VLINK) {
+               /* received CVL request, restart vlan disc */
+               fnic_event_enq(fnic, FNIC_EVT_START_VLAN_DISC);
+               /* pass it on to fcoe */
+               ret = 1;
+       }
+drop:
+       return ret;
+}
+
+void fnic_handle_fip_frame(struct work_struct *work)
+{
+       struct fnic *fnic = container_of(work, struct fnic, fip_frame_work);
+       unsigned long flags;
+       struct sk_buff *skb;
+       struct ethhdr *eh;
+
+       while ((skb = skb_dequeue(&fnic->fip_frame_queue))) {
+               spin_lock_irqsave(&fnic->fnic_lock, flags);
+               if (fnic->stop_rx_link_events) {
+                       spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+                       dev_kfree_skb(skb);
+                       return;
+               }
+               /*
+                * If we're in a transitional state, just re-queue and return.
+                * The queue will be serviced when we get to a stable state.
+                */
+               if (fnic->state != FNIC_IN_FC_MODE &&
+                   fnic->state != FNIC_IN_ETH_MODE) {
+                       skb_queue_head(&fnic->fip_frame_queue, skb);
+                       spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+                       return;
+               }
+               spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+               eh = (struct ethhdr *)skb->data;
+               if (eh->h_proto == htons(ETH_P_FIP)) {
+                       skb_pull(skb, sizeof(*eh));
+                       if (fnic_fcoe_handle_fip_frame(fnic, skb) <= 0) {
+                               dev_kfree_skb(skb);
+                               continue;
+                       }
+                       /*
+                        * If there's FLOGI rejects - clear all
+                        * fcf's & restart from scratch
+                        */
+                       if (is_fnic_fip_flogi_reject(&fnic->ctlr, skb)) {
+                               shost_printk(KERN_INFO, fnic->lport->host,
+                                         "Trigger a Link down - VLAN Disc\n");
+                               fcoe_ctlr_link_down(&fnic->ctlr);
+                               /* start FCoE VLAN discovery */
+                               fnic_fcoe_send_vlan_req(fnic);
+                               dev_kfree_skb(skb);
+                               continue;
+                       }
+                       fcoe_ctlr_recv(&fnic->ctlr, skb);
+                       continue;
+               }
+       }
+}
+
 /**
  * fnic_import_rq_eth_pkt() - handle received FCoE or FIP frame.
  * @fnic:      fnic instance.
@@ -150,8 +603,14 @@ static inline int fnic_import_rq_eth_pkt(struct fnic *fnic, struct sk_buff *skb)
                skb_reset_mac_header(skb);
        }
        if (eh->h_proto == htons(ETH_P_FIP)) {
-               skb_pull(skb, sizeof(*eh));
-               fcoe_ctlr_recv(&fnic->ctlr, skb);
+               if (!(fnic->config.flags & VFCF_FIP_CAPABLE)) {
+                       printk(KERN_ERR "Dropped FIP frame, as firmware "
+                                       "uses non-FIP mode, Enable FIP "
+                                       "using UCSM\n");
+                       goto drop;
+               }
+               skb_queue_tail(&fnic->fip_frame_queue, skb);
+               queue_work(fnic_fip_queue, &fnic->fip_frame_work);
                return 1;               /* let caller know packet was used */
        }
        if (eh->h_proto != htons(ETH_P_FCOE))
@@ -720,3 +1179,104 @@ void fnic_free_wq_buf(struct vnic_wq *wq, struct vnic_wq_buf *buf)
        dev_kfree_skb(fp_skb(fp));
        buf->os_buf = NULL;
 }
+
+void fnic_fcoe_reset_vlans(struct fnic *fnic)
+{
+       unsigned long flags;
+       struct fcoe_vlan *vlan;
+       struct fcoe_vlan *next;
+
+       /*
+        * indicate a link down to fcoe so that all fcf's are free'd
+        * might not be required since we did this before sending vlan
+        * discovery request
+        */
+       spin_lock_irqsave(&fnic->vlans_lock, flags);
+       if (!list_empty(&fnic->vlans)) {
+               list_for_each_entry_safe(vlan, next, &fnic->vlans, list) {
+                       list_del(&vlan->list);
+                       kfree(vlan);
+               }
+       }
+       spin_unlock_irqrestore(&fnic->vlans_lock, flags);
+}
+
+void fnic_handle_fip_timer(struct fnic *fnic)
+{
+       unsigned long flags;
+       struct fcoe_vlan *vlan;
+       u64 sol_time;
+
+       spin_lock_irqsave(&fnic->fnic_lock, flags);
+       if (fnic->stop_rx_link_events) {
+               spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+               return;
+       }
+       spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+
+       if (fnic->ctlr.mode == FIP_ST_NON_FIP)
+               return;
+
+       spin_lock_irqsave(&fnic->vlans_lock, flags);
+       if (list_empty(&fnic->vlans)) {
+               /* no vlans available, try again */
+               FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host,
+                         "Start VLAN Discovery\n");
+               spin_unlock_irqrestore(&fnic->vlans_lock, flags);
+               fnic_event_enq(fnic, FNIC_EVT_START_VLAN_DISC);
+               return;
+       }
+
+       vlan = list_first_entry(&fnic->vlans, struct fcoe_vlan, list);
+       shost_printk(KERN_DEBUG, fnic->lport->host,
+                 "fip_timer: vlan %d state %d sol_count %d\n",
+                 vlan->vid, vlan->state, vlan->sol_count);
+       switch (vlan->state) {
+       case FIP_VLAN_USED:
+               FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host,
+                         "FIP VLAN is selected for FC transaction\n");
+               spin_unlock_irqrestore(&fnic->vlans_lock, flags);
+               break;
+       case FIP_VLAN_FAILED:
+               /* if all vlans are in failed state, restart vlan disc */
+               FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host,
+                         "Start VLAN Discovery\n");
+               spin_unlock_irqrestore(&fnic->vlans_lock, flags);
+               fnic_event_enq(fnic, FNIC_EVT_START_VLAN_DISC);
+               break;
+       case FIP_VLAN_SENT:
+               if (vlan->sol_count >= FCOE_CTLR_MAX_SOL) {
+                       /*
+                        * no response on this vlan, remove  from the list.
+                        * Try the next vlan
+                        */
+                       shost_printk(KERN_INFO, fnic->lport->host,
+                                 "Dequeue this VLAN ID %d from list\n",
+                                 vlan->vid);
+                       list_del(&vlan->list);
+                       kfree(vlan);
+                       vlan = NULL;
+                       if (list_empty(&fnic->vlans)) {
+                               /* we exhausted all vlans, restart vlan disc */
+                               spin_unlock_irqrestore(&fnic->vlans_lock,
+                                                       flags);
+                               shost_printk(KERN_INFO, fnic->lport->host,
+                                         "fip_timer: vlan list empty, "
+                                         "trigger vlan disc\n");
+                               fnic_event_enq(fnic, FNIC_EVT_START_VLAN_DISC);
+                               return;
+                       }
+                       /* check the next vlan */
+                       vlan = list_first_entry(&fnic->vlans, struct fcoe_vlan,
+                                                       list);
+                       fnic->set_vlan(fnic, vlan->vid);
+                       vlan->state = FIP_VLAN_SENT; /* sent now */
+               }
+               spin_unlock_irqrestore(&fnic->vlans_lock, flags);
+               vlan->sol_count++;
+               sol_time = jiffies + msecs_to_jiffies
+                                       (FCOE_CTLR_START_DELAY);
+               mod_timer(&fnic->fip_timer, round_jiffies(sol_time));
+               break;
+       }
+}
diff --git a/drivers/scsi/fnic/fnic_fip.h b/drivers/scsi/fnic/fnic_fip.h
new file mode 100644 (file)
index 0000000..87e74c2
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2008 Cisco Systems, Inc.  All rights reserved.
+ * Copyright 2007 Nuova Systems, Inc.  All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _FNIC_FIP_H_
+#define _FNIC_FIP_H_
+
+
+#define FCOE_CTLR_START_DELAY    2000    /* ms after first adv. to choose FCF */
+#define FCOE_CTLR_FIPVLAN_TOV    2000    /* ms after FIP VLAN disc */
+#define FCOE_CTLR_MAX_SOL        8
+
+#define FINC_MAX_FLOGI_REJECTS   8
+
+/*
+ * FIP_DT_VLAN descriptor.
+ */
+struct fip_vlan_desc {
+       struct fip_desc fd_desc;
+       __be16 fd_vlan;
+} __attribute__((packed));
+
+struct vlan {
+       __be16 vid;
+       __be16 type;
+};
+
+/*
+ * VLAN entry.
+ */
+struct fcoe_vlan {
+       struct list_head list;
+       u16 vid;                /* vlan ID */
+       u16 sol_count;          /* no. of sols sent */
+       u16 state;              /* state */
+};
+
+enum fip_vlan_state {
+       FIP_VLAN_AVAIL  = 0,    /* don't do anything */
+       FIP_VLAN_SENT   = 1,    /* sent */
+       FIP_VLAN_USED   = 2,    /* succeed */
+       FIP_VLAN_FAILED = 3,    /* failed to response */
+};
+
+struct fip_vlan {
+       struct ethhdr eth;
+       struct fip_header fip;
+       struct {
+               struct fip_mac_desc mac;
+               struct fip_wwn_desc wwnn;
+       } desc;
+};
+
+#endif  /* __FINC_FIP_H_ */
index d601ac5..5f09d18 100644 (file)
@@ -39,6 +39,7 @@
 #include "vnic_intr.h"
 #include "vnic_stats.h"
 #include "fnic_io.h"
+#include "fnic_fip.h"
 #include "fnic.h"
 
 #define PCI_DEVICE_ID_CISCO_FNIC       0x0045
@@ -292,6 +293,13 @@ static void fnic_notify_timer(unsigned long data)
                  round_jiffies(jiffies + FNIC_NOTIFY_TIMER_PERIOD));
 }
 
+static void fnic_fip_notify_timer(unsigned long data)
+{
+       struct fnic *fnic = (struct fnic *)data;
+
+       fnic_handle_fip_timer(fnic);
+}
+
 static void fnic_notify_timer_start(struct fnic *fnic)
 {
        switch (vnic_dev_get_intr_mode(fnic->vdev)) {
@@ -403,6 +411,12 @@ static u8 *fnic_get_mac(struct fc_lport *lport)
        return fnic->data_src_addr;
 }
 
+static void fnic_set_vlan(struct fnic *fnic, u16 vlan_id)
+{
+       u16 old_vlan;
+       old_vlan = vnic_dev_set_default_vlan(fnic->vdev, vlan_id);
+}
+
 static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct Scsi_Host *host;
@@ -620,7 +634,29 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                vnic_dev_packet_filter(fnic->vdev, 1, 1, 0, 0, 0);
                vnic_dev_add_addr(fnic->vdev, FIP_ALL_ENODE_MACS);
                vnic_dev_add_addr(fnic->vdev, fnic->ctlr.ctl_src_addr);
+               fnic->set_vlan = fnic_set_vlan;
                fcoe_ctlr_init(&fnic->ctlr, FIP_MODE_AUTO);
+               setup_timer(&fnic->fip_timer, fnic_fip_notify_timer,
+                                                       (unsigned long)fnic);
+               spin_lock_init(&fnic->vlans_lock);
+               INIT_WORK(&fnic->fip_frame_work, fnic_handle_fip_frame);
+               INIT_WORK(&fnic->event_work, fnic_handle_event);
+               skb_queue_head_init(&fnic->fip_frame_queue);
+               spin_lock_irqsave(&fnic_list_lock, flags);
+               if (!fnic_fip_queue) {
+                       fnic_fip_queue =
+                               create_singlethread_workqueue("fnic_fip_q");
+                       if (!fnic_fip_queue) {
+                               spin_unlock_irqrestore(&fnic_list_lock, flags);
+                               printk(KERN_ERR PFX "fnic FIP work queue "
+                                                "create failed\n");
+                               err = -ENOMEM;
+                               goto err_out_free_max_pool;
+                       }
+               }
+               spin_unlock_irqrestore(&fnic_list_lock, flags);
+               INIT_LIST_HEAD(&fnic->evlist);
+               INIT_LIST_HEAD(&fnic->vlans);
        } else {
                shost_printk(KERN_INFO, fnic->lport->host,
                             "firmware uses non-FIP mode\n");
@@ -807,6 +843,13 @@ static void fnic_remove(struct pci_dev *pdev)
        skb_queue_purge(&fnic->frame_queue);
        skb_queue_purge(&fnic->tx_queue);
 
+       if (fnic->config.flags & VFCF_FIP_CAPABLE) {
+               del_timer_sync(&fnic->fip_timer);
+               skb_queue_purge(&fnic->fip_frame_queue);
+               fnic_fcoe_reset_vlans(fnic);
+               fnic_fcoe_evlist_free(fnic);
+       }
+
        /*
         * Log off the fabric. This stops all remote ports, dns port,
         * logs off the fabric. This flushes all rport, disc, lport work
@@ -889,8 +932,8 @@ static int __init fnic_init_module(void)
        len = sizeof(struct fnic_sgl_list);
        fnic_sgl_cache[FNIC_SGL_CACHE_MAX] = kmem_cache_create
                ("fnic_sgl_max", len + FNIC_SG_DESC_ALIGN, FNIC_SG_DESC_ALIGN,
-                SLAB_HWCACHE_ALIGN,
-                NULL);
+                 SLAB_HWCACHE_ALIGN,
+                 NULL);
        if (!fnic_sgl_cache[FNIC_SGL_CACHE_MAX]) {
                printk(KERN_ERR PFX "failed to create fnic max sgl slab\n");
                err = -ENOMEM;
@@ -951,6 +994,10 @@ static void __exit fnic_cleanup_module(void)
 {
        pci_unregister_driver(&fnic_driver);
        destroy_workqueue(fnic_event_queue);
+       if (fnic_fip_queue) {
+               flush_workqueue(fnic_fip_queue);
+               destroy_workqueue(fnic_fip_queue);
+       }
        kmem_cache_destroy(fnic_sgl_cache[FNIC_SGL_CACHE_MAX]);
        kmem_cache_destroy(fnic_sgl_cache[FNIC_SGL_CACHE_DFLT]);
        kmem_cache_destroy(fnic_io_req_cache);
index b576be7..9795d6f 100644 (file)
@@ -584,6 +584,16 @@ int vnic_dev_init(struct vnic_dev *vdev, int arg)
        return vnic_dev_cmd(vdev, CMD_INIT, &a0, &a1, wait);
 }
 
+u16 vnic_dev_set_default_vlan(struct vnic_dev *vdev, u16 new_default_vlan)
+{
+       u64 a0 = new_default_vlan, a1 = 0;
+       int wait = 1000;
+       int old_vlan = 0;
+
+       old_vlan = vnic_dev_cmd(vdev, CMD_SET_DEFAULT_VLAN, &a0, &a1, wait);
+       return (u16)old_vlan;
+}
+
 int vnic_dev_link_status(struct vnic_dev *vdev)
 {
        if (vdev->linkstatus)
index f9935a8..40d4195 100644 (file)
@@ -148,6 +148,8 @@ int vnic_dev_disable(struct vnic_dev *vdev);
 int vnic_dev_open(struct vnic_dev *vdev, int arg);
 int vnic_dev_open_done(struct vnic_dev *vdev, int *done);
 int vnic_dev_init(struct vnic_dev *vdev, int arg);
+u16 vnic_dev_set_default_vlan(struct vnic_dev *vdev,
+                               u16 new_default_vlan);
 int vnic_dev_soft_reset(struct vnic_dev *vdev, int arg);
 int vnic_dev_soft_reset_done(struct vnic_dev *vdev, int *done);
 void vnic_dev_set_intr_mode(struct vnic_dev *vdev,
index 7c9ccbd..3e2fcbd 100644 (file)
@@ -196,6 +196,73 @@ enum vnic_devcmd_cmd {
 
        /* undo initialize of virtual link */
        CMD_DEINIT              = _CMDCNW(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 34),
+
+       /* check fw capability of a cmd:
+        * in:  (u32)a0=cmd
+        * out: (u32)a0=errno, 0:valid cmd, a1=supported VNIC_STF_* bits */
+       CMD_CAPABILITY      = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 36),
+
+       /* persistent binding info
+        * in:  (u64)a0=paddr of arg
+        *      (u32)a1=CMD_PERBI_XXX */
+       CMD_PERBI       = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_FC, 37),
+
+       /* Interrupt Assert Register functionality
+        * in: (u16)a0=interrupt number to assert
+        */
+       CMD_IAR         = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 38),
+
+       /* initiate hangreset, like softreset after hang detected */
+       CMD_HANG_RESET      = _CMDC(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 39),
+
+       /* hangreset status:
+        *    out: a0=0 reset complete, a0=1 reset in progress */
+       CMD_HANG_RESET_STATUS   = _CMDC(_CMD_DIR_READ, _CMD_VTYPE_ALL, 40),
+
+       /*
+        * Set hw ingress packet vlan rewrite mode:
+        * in:  (u32)a0=new vlan rewrite mode
+        * out: (u32)a0=old vlan rewrite mode */
+       CMD_IG_VLAN_REWRITE_MODE = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ENET, 41),
+
+       /*
+        * in:  (u16)a0=bdf of target vnic
+        *      (u32)a1=cmd to proxy
+        *      a2-a15=args to cmd in a1
+        * out: (u32)a0=status of proxied cmd
+        *      a1-a15=out args of proxied cmd */
+       CMD_PROXY_BY_BDF =  _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 42),
+
+       /*
+        * As for BY_BDF except a0 is index of hvnlink subordinate vnic
+        * or SR-IOV virtual vnic
+        */
+       CMD_PROXY_BY_INDEX =    _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 43),
+
+       /*
+        * For HPP toggle:
+        * adapter-info-get
+        * in:  (u64)a0=phsical address of buffer passed in from caller.
+        *      (u16)a1=size of buffer specified in a0.
+        * out: (u64)a0=phsical address of buffer passed in from caller.
+        *      (u16)a1=actual bytes from VIF-CONFIG-INFO TLV, or
+        *              0 if no VIF-CONFIG-INFO TLV was ever received. */
+       CMD_CONFIG_INFO_GET = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 44),
+
+       /*
+        * INT13 API: (u64)a0=paddr to vnic_int13_params struct
+        *            (u32)a1=INT13_CMD_xxx
+        */
+       CMD_INT13_ALL = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 45),
+
+       /*
+        * Set default vlan:
+        * in: (u16)a0=new default vlan
+        *     (u16)a1=zero for overriding vlan with param a0,
+        *             non-zero for resetting vlan to the default
+        * out: (u16)a0=old default vlan
+        */
+       CMD_SET_DEFAULT_VLAN = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 46)
 };
 
 /* flags for CMD_OPEN */
index cc82d0f..4e31caa 100644 (file)
@@ -2179,7 +2179,7 @@ static int ibmvfc_cancel_all(struct scsi_device *sdev, int type)
                return 0;
        }
 
-       if (vhost->state == IBMVFC_ACTIVE) {
+       if (vhost->logged_in) {
                evt = ibmvfc_get_event(vhost);
                ibmvfc_init_event(evt, ibmvfc_sync_completion, IBMVFC_MAD_FORMAT);
 
@@ -2190,7 +2190,12 @@ static int ibmvfc_cancel_all(struct scsi_device *sdev, int type)
                tmf->common.length = sizeof(*tmf);
                tmf->scsi_id = rport->port_id;
                int_to_scsilun(sdev->lun, &tmf->lun);
-               tmf->flags = (type | IBMVFC_TMF_LUA_VALID);
+               if (!(vhost->login_buf->resp.capabilities & IBMVFC_CAN_SUPPRESS_ABTS))
+                       type &= ~IBMVFC_TMF_SUPPRESS_ABTS;
+               if (vhost->state == IBMVFC_ACTIVE)
+                       tmf->flags = (type | IBMVFC_TMF_LUA_VALID);
+               else
+                       tmf->flags = ((type & IBMVFC_TMF_SUPPRESS_ABTS) | IBMVFC_TMF_LUA_VALID);
                tmf->cancel_key = (unsigned long)sdev->hostdata;
                tmf->my_cancel_key = (unsigned long)starget->hostdata;
 
@@ -2327,7 +2332,7 @@ static int ibmvfc_abort_task_set(struct scsi_device *sdev)
        timeout = wait_for_completion_timeout(&evt->comp, timeout);
 
        if (!timeout) {
-               rc = ibmvfc_cancel_all(sdev, IBMVFC_TMF_ABORT_TASK_SET);
+               rc = ibmvfc_cancel_all(sdev, 0);
                if (!rc) {
                        rc = ibmvfc_wait_for_ops(vhost, sdev->hostdata, ibmvfc_match_key);
                        if (rc == SUCCESS)
@@ -2383,24 +2388,30 @@ out:
  * @cmd:       scsi command to abort
  *
  * Returns:
- *     SUCCESS / FAILED
+ *     SUCCESS / FAST_IO_FAIL / FAILED
  **/
 static int ibmvfc_eh_abort_handler(struct scsi_cmnd *cmd)
 {
        struct scsi_device *sdev = cmd->device;
        struct ibmvfc_host *vhost = shost_priv(sdev->host);
-       int cancel_rc, abort_rc;
+       int cancel_rc, block_rc;
        int rc = FAILED;
 
        ENTER;
-       fc_block_scsi_eh(cmd);
+       block_rc = fc_block_scsi_eh(cmd);
        ibmvfc_wait_while_resetting(vhost);
-       cancel_rc = ibmvfc_cancel_all(sdev, IBMVFC_TMF_ABORT_TASK_SET);
-       abort_rc = ibmvfc_abort_task_set(sdev);
+       if (block_rc != FAST_IO_FAIL) {
+               cancel_rc = ibmvfc_cancel_all(sdev, IBMVFC_TMF_ABORT_TASK_SET);
+               ibmvfc_abort_task_set(sdev);
+       } else
+               cancel_rc = ibmvfc_cancel_all(sdev, IBMVFC_TMF_SUPPRESS_ABTS);
 
-       if (!cancel_rc && !abort_rc)
+       if (!cancel_rc)
                rc = ibmvfc_wait_for_ops(vhost, sdev, ibmvfc_match_lun);
 
+       if (block_rc == FAST_IO_FAIL && rc != FAILED)
+               rc = FAST_IO_FAIL;
+
        LEAVE;
        return rc;
 }
@@ -2410,28 +2421,46 @@ static int ibmvfc_eh_abort_handler(struct scsi_cmnd *cmd)
  * @cmd:       scsi command struct
  *
  * Returns:
- *     SUCCESS / FAILED
+ *     SUCCESS / FAST_IO_FAIL / FAILED
  **/
 static int ibmvfc_eh_device_reset_handler(struct scsi_cmnd *cmd)
 {
        struct scsi_device *sdev = cmd->device;
        struct ibmvfc_host *vhost = shost_priv(sdev->host);
-       int cancel_rc, reset_rc;
+       int cancel_rc, block_rc, reset_rc = 0;
        int rc = FAILED;
 
        ENTER;
-       fc_block_scsi_eh(cmd);
+       block_rc = fc_block_scsi_eh(cmd);
        ibmvfc_wait_while_resetting(vhost);
-       cancel_rc = ibmvfc_cancel_all(sdev, IBMVFC_TMF_LUN_RESET);
-       reset_rc = ibmvfc_reset_device(sdev, IBMVFC_LUN_RESET, "LUN");
+       if (block_rc != FAST_IO_FAIL) {
+               cancel_rc = ibmvfc_cancel_all(sdev, IBMVFC_TMF_LUN_RESET);
+               reset_rc = ibmvfc_reset_device(sdev, IBMVFC_LUN_RESET, "LUN");
+       } else
+               cancel_rc = ibmvfc_cancel_all(sdev, IBMVFC_TMF_SUPPRESS_ABTS);
 
        if (!cancel_rc && !reset_rc)
                rc = ibmvfc_wait_for_ops(vhost, sdev, ibmvfc_match_lun);
 
+       if (block_rc == FAST_IO_FAIL && rc != FAILED)
+               rc = FAST_IO_FAIL;
+
        LEAVE;
        return rc;
 }
 
+/**
+ * ibmvfc_dev_cancel_all_noreset - Device iterated cancel all function
+ * @sdev:      scsi device struct
+ * @data:      return code
+ *
+ **/
+static void ibmvfc_dev_cancel_all_noreset(struct scsi_device *sdev, void *data)
+{
+       unsigned long *rc = data;
+       *rc |= ibmvfc_cancel_all(sdev, IBMVFC_TMF_SUPPRESS_ABTS);
+}
+
 /**
  * ibmvfc_dev_cancel_all_reset - Device iterated cancel all function
  * @sdev:      scsi device struct
@@ -2449,26 +2478,33 @@ static void ibmvfc_dev_cancel_all_reset(struct scsi_device *sdev, void *data)
  * @cmd:       scsi command struct
  *
  * Returns:
- *     SUCCESS / FAILED
+ *     SUCCESS / FAST_IO_FAIL / FAILED
  **/
 static int ibmvfc_eh_target_reset_handler(struct scsi_cmnd *cmd)
 {
        struct scsi_device *sdev = cmd->device;
        struct ibmvfc_host *vhost = shost_priv(sdev->host);
        struct scsi_target *starget = scsi_target(sdev);
-       int reset_rc;
+       int block_rc;
+       int reset_rc = 0;
        int rc = FAILED;
        unsigned long cancel_rc = 0;
 
        ENTER;
-       fc_block_scsi_eh(cmd);
+       block_rc = fc_block_scsi_eh(cmd);
        ibmvfc_wait_while_resetting(vhost);
-       starget_for_each_device(starget, &cancel_rc, ibmvfc_dev_cancel_all_reset);
-       reset_rc = ibmvfc_reset_device(sdev, IBMVFC_TARGET_RESET, "target");
+       if (block_rc != FAST_IO_FAIL) {
+               starget_for_each_device(starget, &cancel_rc, ibmvfc_dev_cancel_all_reset);
+               reset_rc = ibmvfc_reset_device(sdev, IBMVFC_TARGET_RESET, "target");
+       } else
+               starget_for_each_device(starget, &cancel_rc, ibmvfc_dev_cancel_all_noreset);
 
        if (!cancel_rc && !reset_rc)
                rc = ibmvfc_wait_for_ops(vhost, starget, ibmvfc_match_target);
 
+       if (block_rc == FAST_IO_FAIL && rc != FAILED)
+               rc = FAST_IO_FAIL;
+
        LEAVE;
        return rc;
 }
@@ -2480,12 +2516,16 @@ static int ibmvfc_eh_target_reset_handler(struct scsi_cmnd *cmd)
  **/
 static int ibmvfc_eh_host_reset_handler(struct scsi_cmnd *cmd)
 {
-       int rc;
+       int rc, block_rc;
        struct ibmvfc_host *vhost = shost_priv(cmd->device->host);
 
-       fc_block_scsi_eh(cmd);
+       block_rc = fc_block_scsi_eh(cmd);
        dev_err(vhost->dev, "Resetting connection due to error recovery\n");
        rc = ibmvfc_issue_fc_host_lip(vhost->host);
+
+       if (block_rc == FAST_IO_FAIL)
+               return FAST_IO_FAIL;
+
        return rc ? FAILED : SUCCESS;
 }
 
@@ -2509,8 +2549,7 @@ static void ibmvfc_terminate_rport_io(struct fc_rport *rport)
                dev_rport = starget_to_rport(scsi_target(sdev));
                if (dev_rport != rport)
                        continue;
-               ibmvfc_cancel_all(sdev, IBMVFC_TMF_ABORT_TASK_SET);
-               ibmvfc_abort_task_set(sdev);
+               ibmvfc_cancel_all(sdev, IBMVFC_TMF_SUPPRESS_ABTS);
        }
 
        rc = ibmvfc_wait_for_ops(vhost, rport, ibmvfc_match_rport);
index 3be8af6..017a529 100644 (file)
@@ -29,8 +29,8 @@
 #include "viosrp.h"
 
 #define IBMVFC_NAME    "ibmvfc"
-#define IBMVFC_DRIVER_VERSION          "1.0.10"
-#define IBMVFC_DRIVER_DATE             "(August 24, 2012)"
+#define IBMVFC_DRIVER_VERSION          "1.0.11"
+#define IBMVFC_DRIVER_DATE             "(April 12, 2013)"
 
 #define IBMVFC_DEFAULT_TIMEOUT 60
 #define IBMVFC_ADISC_CANCEL_TIMEOUT    45
@@ -208,10 +208,10 @@ struct ibmvfc_npiv_login_resp {
        u16 error;
        u32 flags;
 #define IBMVFC_NATIVE_FC               0x01
-#define IBMVFC_CAN_FLUSH_ON_HALT       0x08
        u32 reserved;
        u64 capabilities;
 #define IBMVFC_CAN_FLUSH_ON_HALT       0x08
+#define IBMVFC_CAN_SUPPRESS_ABTS       0x10
        u32 max_cmds;
        u32 scsi_id_sz;
        u64 max_dma_len;
@@ -351,6 +351,7 @@ struct ibmvfc_tmf {
 #define IBMVFC_TMF_LUN_RESET           0x10
 #define IBMVFC_TMF_TGT_RESET           0x20
 #define IBMVFC_TMF_LUA_VALID           0x40
+#define IBMVFC_TMF_SUPPRESS_ABTS       0x80
        u32 cancel_key;
        u32 my_cancel_key;
        u32 pad;
index 2197b57..82a3c1e 100644 (file)
@@ -4777,7 +4777,7 @@ static int ipr_eh_host_reset(struct scsi_cmnd *cmd)
        ioa_cfg = (struct ipr_ioa_cfg *) cmd->device->host->hostdata;
        spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
 
-       if (!ioa_cfg->in_reset_reload) {
+       if (!ioa_cfg->in_reset_reload && !ioa_cfg->hrrq[IPR_INIT_HRRQ].ioa_is_dead) {
                ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_ABBREV);
                dev_err(&ioa_cfg->pdev->dev,
                        "Adapter being reset as a result of error recovery.\n");
@@ -6421,7 +6421,7 @@ static void ipr_build_ata_ioadl64(struct ipr_cmnd *ipr_cmd,
 {
        u32 ioadl_flags = 0;
        struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb;
-       struct ipr_ioadl64_desc *ioadl64 = ipr_cmd->i.ioadl64;
+       struct ipr_ioadl64_desc *ioadl64 = ipr_cmd->i.ata_ioadl.ioadl64;
        struct ipr_ioadl64_desc *last_ioadl64 = NULL;
        int len = qc->nbytes;
        struct scatterlist *sg;
@@ -6441,7 +6441,7 @@ static void ipr_build_ata_ioadl64(struct ipr_cmnd *ipr_cmd,
        ioarcb->ioadl_len =
                cpu_to_be32(sizeof(struct ipr_ioadl64_desc) * ipr_cmd->dma_use_sg);
        ioarcb->u.sis64_addr_data.data_ioadl_addr =
-               cpu_to_be64(dma_addr + offsetof(struct ipr_cmnd, i.ata_ioadl));
+               cpu_to_be64(dma_addr + offsetof(struct ipr_cmnd, i.ata_ioadl.ioadl64));
 
        for_each_sg(qc->sg, sg, qc->n_elem, si) {
                ioadl64->flags = cpu_to_be32(ioadl_flags);
@@ -6739,6 +6739,7 @@ static int ipr_invalid_adapter(struct ipr_ioa_cfg *ioa_cfg)
 static int ipr_ioa_bringdown_done(struct ipr_cmnd *ipr_cmd)
 {
        struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
+       int i;
 
        ENTER;
        if (!ioa_cfg->hrrq[IPR_INIT_HRRQ].removing_ioa) {
@@ -6750,6 +6751,13 @@ static int ipr_ioa_bringdown_done(struct ipr_cmnd *ipr_cmd)
 
        ioa_cfg->in_reset_reload = 0;
        ioa_cfg->reset_retries = 0;
+       for (i = 0; i < ioa_cfg->hrrq_num; i++) {
+               spin_lock(&ioa_cfg->hrrq[i]._lock);
+               ioa_cfg->hrrq[i].ioa_is_dead = 1;
+               spin_unlock(&ioa_cfg->hrrq[i]._lock);
+       }
+       wmb();
+
        list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
        wake_up_all(&ioa_cfg->reset_wait_q);
        LEAVE;
@@ -8651,7 +8659,7 @@ static void ipr_pci_perm_failure(struct pci_dev *pdev)
        spin_lock_irqsave(ioa_cfg->host->host_lock, flags);
        if (ioa_cfg->sdt_state == WAIT_FOR_DUMP)
                ioa_cfg->sdt_state = ABORT_DUMP;
-       ioa_cfg->reset_retries = IPR_NUM_RESET_RELOAD_RETRIES;
+       ioa_cfg->reset_retries = IPR_NUM_RESET_RELOAD_RETRIES - 1;
        ioa_cfg->in_ioa_bringdown = 1;
        for (i = 0; i < ioa_cfg->hrrq_num; i++) {
                spin_lock(&ioa_cfg->hrrq[i]._lock);
index 21a6ff1..a1fb840 100644 (file)
@@ -552,7 +552,7 @@ struct ipr_ioarcb_ata_regs {        /* 22 bytes */
        u8 hob_lbam;
        u8 hob_lbah;
        u8 ctl;
-}__attribute__ ((packed, aligned(4)));
+}__attribute__ ((packed, aligned(2)));
 
 struct ipr_ioadl_desc {
        __be32 flags_and_data_len;
index c3aa6c5..96a26f4 100644 (file)
@@ -1085,7 +1085,7 @@ static void sci_remote_device_ready_state_enter(struct sci_base_state_machine *s
        struct isci_host *ihost = idev->owning_port->owning_controller;
        struct domain_device *dev = idev->domain_dev;
 
-       if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_SATA)) {
+       if (dev->dev_type == SAS_SATA_DEV || (dev->tproto & SAS_PROTOCOL_SATA)) {
                sci_change_state(&idev->sm, SCI_STP_DEV_IDLE);
        } else if (dev_is_expander(dev)) {
                sci_change_state(&idev->sm, SCI_SMP_DEV_IDLE);
@@ -1098,7 +1098,7 @@ static void sci_remote_device_ready_state_exit(struct sci_base_state_machine *sm
        struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm);
        struct domain_device *dev = idev->domain_dev;
 
-       if (dev->dev_type == SAS_END_DEV) {
+       if (dev->dev_type == SAS_END_DEVICE) {
                struct isci_host *ihost = idev->owning_port->owning_controller;
 
                isci_remote_device_not_ready(ihost, idev,
index 7674caa..47a013f 100644 (file)
@@ -297,7 +297,7 @@ static inline struct isci_remote_device *rnc_to_dev(struct sci_remote_node_conte
 
 static inline bool dev_is_expander(struct domain_device *dev)
 {
-       return dev->dev_type == EDGE_DEV || dev->dev_type == FANOUT_DEV;
+       return dev->dev_type == SAS_EDGE_EXPANDER_DEVICE || dev->dev_type == SAS_FANOUT_EXPANDER_DEVICE;
 }
 
 static inline void sci_remote_device_decrement_request_count(struct isci_remote_device *idev)
index 9594ab6..e3e3bcb 100644 (file)
@@ -2978,7 +2978,7 @@ static void sci_request_started_state_enter(struct sci_base_state_machine *sm)
        /* all unaccelerated request types (non ssp or ncq) handled with
         * substates
         */
-       if (!task && dev->dev_type == SAS_END_DEV) {
+       if (!task && dev->dev_type == SAS_END_DEVICE) {
                state = SCI_REQ_TASK_WAIT_TC_COMP;
        } else if (task && task->task_proto == SAS_PROTOCOL_SMP) {
                state = SCI_REQ_SMP_WAIT_RESP;
@@ -3101,7 +3101,7 @@ sci_io_request_construct(struct isci_host *ihost,
        if (idev->rnc.remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX)
                return SCI_FAILURE_INVALID_REMOTE_DEVICE;
 
-       if (dev->dev_type == SAS_END_DEV)
+       if (dev->dev_type == SAS_END_DEVICE)
                /* pass */;
        else if (dev_is_sata(dev))
                memset(&ireq->stp.cmd, 0, sizeof(ireq->stp.cmd));
@@ -3125,7 +3125,7 @@ enum sci_status sci_task_request_construct(struct isci_host *ihost,
        /* Build the common part of the request */
        sci_general_request_construct(ihost, idev, ireq);
 
-       if (dev->dev_type == SAS_END_DEV || dev_is_sata(dev)) {
+       if (dev->dev_type == SAS_END_DEVICE || dev_is_sata(dev)) {
                set_bit(IREQ_TMF, &ireq->flags);
                memset(ireq->tc, 0, sizeof(struct scu_task_context));
 
index b6f19a1..9bb020a 100644 (file)
@@ -250,7 +250,7 @@ static struct isci_request *isci_task_request_build(struct isci_host *ihost,
        }
 
        /* XXX convert to get this from task->tproto like other drivers */
-       if (dev->dev_type == SAS_END_DEV) {
+       if (dev->dev_type == SAS_END_DEVICE) {
                isci_tmf->proto = SAS_PROTOCOL_SSP;
                status = sci_task_request_construct_ssp(ireq);
                if (status != SCI_SUCCESS)
index bdb81cd..161c98e 100644 (file)
@@ -285,14 +285,14 @@ int sas_get_ata_info(struct domain_device *dev, struct ex_phy *phy)
        if (phy->attached_tproto & SAS_PROTOCOL_STP)
                dev->tproto = phy->attached_tproto;
        if (phy->attached_sata_dev)
-               dev->tproto |= SATA_DEV;
+               dev->tproto |= SAS_SATA_DEV;
 
-       if (phy->attached_dev_type == SATA_PENDING)
-               dev->dev_type = SATA_PENDING;
+       if (phy->attached_dev_type == SAS_SATA_PENDING)
+               dev->dev_type = SAS_SATA_PENDING;
        else {
                int res;
 
-               dev->dev_type = SATA_DEV;
+               dev->dev_type = SAS_SATA_DEV;
                res = sas_get_report_phy_sata(dev->parent, phy->phy_id,
                                              &dev->sata_dev.rps_resp);
                if (res) {
@@ -314,7 +314,7 @@ static int sas_ata_clear_pending(struct domain_device *dev, struct ex_phy *phy)
        int res;
 
        /* we weren't pending, so successfully end the reset sequence now */
-       if (dev->dev_type != SATA_PENDING)
+       if (dev->dev_type != SAS_SATA_PENDING)
                return 1;
 
        /* hmmm, if this succeeds do we need to repost the domain_device to the
@@ -348,9 +348,9 @@ static int smp_ata_check_ready(struct ata_link *link)
                return 0;
 
        switch (ex_phy->attached_dev_type) {
-       case SATA_PENDING:
+       case SAS_SATA_PENDING:
                return 0;
-       case SAS_END_DEV:
+       case SAS_END_DEVICE:
                if (ex_phy->attached_sata_dev)
                        return sas_ata_clear_pending(dev, ex_phy);
        default:
@@ -631,7 +631,7 @@ static void sas_get_ata_command_set(struct domain_device *dev)
        struct dev_to_host_fis *fis =
                (struct dev_to_host_fis *) dev->frame_rcvd;
 
-       if (dev->dev_type == SATA_PENDING)
+       if (dev->dev_type == SAS_SATA_PENDING)
                return;
 
        if ((fis->sector_count == 1 && /* ATA */
@@ -797,7 +797,7 @@ int sas_discover_sata(struct domain_device *dev)
 {
        int res;
 
-       if (dev->dev_type == SATA_PM)
+       if (dev->dev_type == SAS_SATA_PM)
                return -ENODEV;
 
        sas_get_ata_command_set(dev);
index a0c3003..62b58d3 100644 (file)
 void sas_init_dev(struct domain_device *dev)
 {
        switch (dev->dev_type) {
-       case SAS_END_DEV:
+       case SAS_END_DEVICE:
                INIT_LIST_HEAD(&dev->ssp_dev.eh_list_node);
                break;
-       case EDGE_DEV:
-       case FANOUT_DEV:
+       case SAS_EDGE_EXPANDER_DEVICE:
+       case SAS_FANOUT_EXPANDER_DEVICE:
                INIT_LIST_HEAD(&dev->ex_dev.children);
                mutex_init(&dev->ex_dev.cmd_mutex);
                break;
@@ -93,9 +93,9 @@ static int sas_get_port_device(struct asd_sas_port *port)
                if (fis->interrupt_reason == 1 && fis->lbal == 1 &&
                    fis->byte_count_low==0x69 && fis->byte_count_high == 0x96
                    && (fis->device & ~0x10) == 0)
-                       dev->dev_type = SATA_PM;
+                       dev->dev_type = SAS_SATA_PM;
                else
-                       dev->dev_type = SATA_DEV;
+                       dev->dev_type = SAS_SATA_DEV;
                dev->tproto = SAS_PROTOCOL_SATA;
        } else {
                struct sas_identify_frame *id =
@@ -109,21 +109,21 @@ static int sas_get_port_device(struct asd_sas_port *port)
 
        dev->port = port;
        switch (dev->dev_type) {
-       case SATA_DEV:
+       case SAS_SATA_DEV:
                rc = sas_ata_init(dev);
                if (rc) {
                        rphy = NULL;
                        break;
                }
                /* fall through */
-       case SAS_END_DEV:
+       case SAS_END_DEVICE:
                rphy = sas_end_device_alloc(port->port);
                break;
-       case EDGE_DEV:
+       case SAS_EDGE_EXPANDER_DEVICE:
                rphy = sas_expander_alloc(port->port,
                                          SAS_EDGE_EXPANDER_DEVICE);
                break;
-       case FANOUT_DEV:
+       case SAS_FANOUT_EXPANDER_DEVICE:
                rphy = sas_expander_alloc(port->port,
                                          SAS_FANOUT_EXPANDER_DEVICE);
                break;
@@ -156,7 +156,7 @@ static int sas_get_port_device(struct asd_sas_port *port)
        dev->rphy = rphy;
        get_device(&dev->rphy->dev);
 
-       if (dev_is_sata(dev) || dev->dev_type == SAS_END_DEV)
+       if (dev_is_sata(dev) || dev->dev_type == SAS_END_DEVICE)
                list_add_tail(&dev->disco_list_node, &port->disco_list);
        else {
                spin_lock_irq(&port->dev_list_lock);
@@ -315,7 +315,7 @@ void sas_free_device(struct kref *kref)
        dev->phy = NULL;
 
        /* remove the phys and ports, everything else should be gone */
-       if (dev->dev_type == EDGE_DEV || dev->dev_type == FANOUT_DEV)
+       if (dev->dev_type == SAS_EDGE_EXPANDER_DEVICE || dev->dev_type == SAS_FANOUT_EXPANDER_DEVICE)
                kfree(dev->ex_dev.ex_phy);
 
        if (dev_is_sata(dev) && dev->sata_dev.ap) {
@@ -343,7 +343,7 @@ static void sas_unregister_common_dev(struct asd_sas_port *port, struct domain_d
        spin_unlock_irq(&port->dev_list_lock);
 
        spin_lock_irq(&ha->lock);
-       if (dev->dev_type == SAS_END_DEV &&
+       if (dev->dev_type == SAS_END_DEVICE &&
            !list_empty(&dev->ssp_dev.eh_list_node)) {
                list_del_init(&dev->ssp_dev.eh_list_node);
                ha->eh_active--;
@@ -457,15 +457,15 @@ static void sas_discover_domain(struct work_struct *work)
                    task_pid_nr(current));
 
        switch (dev->dev_type) {
-       case SAS_END_DEV:
+       case SAS_END_DEVICE:
                error = sas_discover_end_dev(dev);
                break;
-       case EDGE_DEV:
-       case FANOUT_DEV:
+       case SAS_EDGE_EXPANDER_DEVICE:
+       case SAS_FANOUT_EXPANDER_DEVICE:
                error = sas_discover_root_expander(dev);
                break;
-       case SATA_DEV:
-       case SATA_PM:
+       case SAS_SATA_DEV:
+       case SAS_SATA_PM:
 #ifdef CONFIG_SCSI_SAS_ATA
                error = sas_discover_sata(dev);
                break;
index f42b0e1..446b851 100644 (file)
@@ -183,21 +183,21 @@ static char sas_route_char(struct domain_device *dev, struct ex_phy *phy)
        }
 }
 
-static enum sas_dev_type to_dev_type(struct discover_resp *dr)
+static enum sas_device_type to_dev_type(struct discover_resp *dr)
 {
        /* This is detecting a failure to transmit initial dev to host
         * FIS as described in section J.5 of sas-2 r16
         */
-       if (dr->attached_dev_type == NO_DEVICE && dr->attached_sata_dev &&
+       if (dr->attached_dev_type == SAS_PHY_UNUSED && dr->attached_sata_dev &&
            dr->linkrate >= SAS_LINK_RATE_1_5_GBPS)
-               return SATA_PENDING;
+               return SAS_SATA_PENDING;
        else
                return dr->attached_dev_type;
 }
 
 static void sas_set_ex_phy(struct domain_device *dev, int phy_id, void *rsp)
 {
-       enum sas_dev_type dev_type;
+       enum sas_device_type dev_type;
        enum sas_linkrate linkrate;
        u8 sas_addr[SAS_ADDR_SIZE];
        struct smp_resp *resp = rsp;
@@ -238,7 +238,7 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id, void *rsp)
        /* Handle vacant phy - rest of dr data is not valid so skip it */
        if (phy->phy_state == PHY_VACANT) {
                memset(phy->attached_sas_addr, 0, SAS_ADDR_SIZE);
-               phy->attached_dev_type = NO_DEVICE;
+               phy->attached_dev_type = SAS_PHY_UNUSED;
                if (!test_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state)) {
                        phy->phy_id = phy_id;
                        goto skip;
@@ -259,7 +259,7 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id, void *rsp)
        /* help some expanders that fail to zero sas_address in the 'no
         * device' case
         */
-       if (phy->attached_dev_type == NO_DEVICE ||
+       if (phy->attached_dev_type == SAS_PHY_UNUSED ||
            phy->linkrate < SAS_LINK_RATE_1_5_GBPS)
                memset(phy->attached_sas_addr, 0, SAS_ADDR_SIZE);
        else
@@ -292,13 +292,13 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id, void *rsp)
 
  out:
        switch (phy->attached_dev_type) {
-       case SATA_PENDING:
+       case SAS_SATA_PENDING:
                type = "stp pending";
                break;
-       case NO_DEVICE:
+       case SAS_PHY_UNUSED:
                type = "no device";
                break;
-       case SAS_END_DEV:
+       case SAS_END_DEVICE:
                if (phy->attached_iproto) {
                        if (phy->attached_tproto)
                                type = "host+target";
@@ -311,8 +311,8 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id, void *rsp)
                                type = "ssp";
                }
                break;
-       case EDGE_DEV:
-       case FANOUT_DEV:
+       case SAS_EDGE_EXPANDER_DEVICE:
+       case SAS_FANOUT_EXPANDER_DEVICE:
                type = "smp";
                break;
        default:
@@ -833,7 +833,7 @@ static struct domain_device *sas_ex_discover_end_dev(
        } else
 #endif
          if (phy->attached_tproto & SAS_PROTOCOL_SSP) {
-               child->dev_type = SAS_END_DEV;
+               child->dev_type = SAS_END_DEVICE;
                rphy = sas_end_device_alloc(phy->port);
                /* FIXME: error handling */
                if (unlikely(!rphy))
@@ -932,11 +932,11 @@ static struct domain_device *sas_ex_discover_expander(
 
 
        switch (phy->attached_dev_type) {
-       case EDGE_DEV:
+       case SAS_EDGE_EXPANDER_DEVICE:
                rphy = sas_expander_alloc(phy->port,
                                          SAS_EDGE_EXPANDER_DEVICE);
                break;
-       case FANOUT_DEV:
+       case SAS_FANOUT_EXPANDER_DEVICE:
                rphy = sas_expander_alloc(phy->port,
                                          SAS_FANOUT_EXPANDER_DEVICE);
                break;
@@ -1013,7 +1013,7 @@ static int sas_ex_discover_dev(struct domain_device *dev, int phy_id)
        if (sas_dev_present_in_domain(dev->port, ex_phy->attached_sas_addr))
                sas_ex_disable_port(dev, ex_phy->attached_sas_addr);
 
-       if (ex_phy->attached_dev_type == NO_DEVICE) {
+       if (ex_phy->attached_dev_type == SAS_PHY_UNUSED) {
                if (ex_phy->routing_attr == DIRECT_ROUTING) {
                        memset(ex_phy->attached_sas_addr, 0, SAS_ADDR_SIZE);
                        sas_configure_routing(dev, ex_phy->attached_sas_addr);
@@ -1022,10 +1022,10 @@ static int sas_ex_discover_dev(struct domain_device *dev, int phy_id)
        } else if (ex_phy->linkrate == SAS_LINK_RATE_UNKNOWN)
                return 0;
 
-       if (ex_phy->attached_dev_type != SAS_END_DEV &&
-           ex_phy->attached_dev_type != FANOUT_DEV &&
-           ex_phy->attached_dev_type != EDGE_DEV &&
-           ex_phy->attached_dev_type != SATA_PENDING) {
+       if (ex_phy->attached_dev_type != SAS_END_DEVICE &&
+           ex_phy->attached_dev_type != SAS_FANOUT_EXPANDER_DEVICE &&
+           ex_phy->attached_dev_type != SAS_EDGE_EXPANDER_DEVICE &&
+           ex_phy->attached_dev_type != SAS_SATA_PENDING) {
                SAS_DPRINTK("unknown device type(0x%x) attached to ex %016llx "
                            "phy 0x%x\n", ex_phy->attached_dev_type,
                            SAS_ADDR(dev->sas_addr),
@@ -1049,11 +1049,11 @@ static int sas_ex_discover_dev(struct domain_device *dev, int phy_id)
        }
 
        switch (ex_phy->attached_dev_type) {
-       case SAS_END_DEV:
-       case SATA_PENDING:
+       case SAS_END_DEVICE:
+       case SAS_SATA_PENDING:
                child = sas_ex_discover_end_dev(dev, phy_id);
                break;
-       case FANOUT_DEV:
+       case SAS_FANOUT_EXPANDER_DEVICE:
                if (SAS_ADDR(dev->port->disc.fanout_sas_addr)) {
                        SAS_DPRINTK("second fanout expander %016llx phy 0x%x "
                                    "attached to ex %016llx phy 0x%x\n",
@@ -1067,7 +1067,7 @@ static int sas_ex_discover_dev(struct domain_device *dev, int phy_id)
                        memcpy(dev->port->disc.fanout_sas_addr,
                               ex_phy->attached_sas_addr, SAS_ADDR_SIZE);
                /* fallthrough */
-       case EDGE_DEV:
+       case SAS_EDGE_EXPANDER_DEVICE:
                child = sas_ex_discover_expander(dev, phy_id);
                break;
        default:
@@ -1111,8 +1111,8 @@ static int sas_find_sub_addr(struct domain_device *dev, u8 *sub_addr)
                    phy->phy_state == PHY_NOT_PRESENT)
                        continue;
 
-               if ((phy->attached_dev_type == EDGE_DEV ||
-                    phy->attached_dev_type == FANOUT_DEV) &&
+               if ((phy->attached_dev_type == SAS_EDGE_EXPANDER_DEVICE ||
+                    phy->attached_dev_type == SAS_FANOUT_EXPANDER_DEVICE) &&
                    phy->routing_attr == SUBTRACTIVE_ROUTING) {
 
                        memcpy(sub_addr, phy->attached_sas_addr,SAS_ADDR_SIZE);
@@ -1130,8 +1130,8 @@ static int sas_check_level_subtractive_boundary(struct domain_device *dev)
        u8 sub_addr[8] = {0, };
 
        list_for_each_entry(child, &ex->children, siblings) {
-               if (child->dev_type != EDGE_DEV &&
-                   child->dev_type != FANOUT_DEV)
+               if (child->dev_type != SAS_EDGE_EXPANDER_DEVICE &&
+                   child->dev_type != SAS_FANOUT_EXPANDER_DEVICE)
                        continue;
                if (sub_addr[0] == 0) {
                        sas_find_sub_addr(child, sub_addr);
@@ -1208,7 +1208,7 @@ static int sas_check_ex_subtractive_boundary(struct domain_device *dev)
        int i;
        u8  *sub_sas_addr = NULL;
 
-       if (dev->dev_type != EDGE_DEV)
+       if (dev->dev_type != SAS_EDGE_EXPANDER_DEVICE)
                return 0;
 
        for (i = 0; i < ex->num_phys; i++) {
@@ -1218,8 +1218,8 @@ static int sas_check_ex_subtractive_boundary(struct domain_device *dev)
                    phy->phy_state == PHY_NOT_PRESENT)
                        continue;
 
-               if ((phy->attached_dev_type == FANOUT_DEV ||
-                    phy->attached_dev_type == EDGE_DEV) &&
+               if ((phy->attached_dev_type == SAS_FANOUT_EXPANDER_DEVICE ||
+                    phy->attached_dev_type == SAS_EDGE_EXPANDER_DEVICE) &&
                    phy->routing_attr == SUBTRACTIVE_ROUTING) {
 
                        if (!sub_sas_addr)
@@ -1245,8 +1245,8 @@ static void sas_print_parent_topology_bug(struct domain_device *child,
                                                 struct ex_phy *child_phy)
 {
        static const char *ex_type[] = {
-               [EDGE_DEV] = "edge",
-               [FANOUT_DEV] = "fanout",
+               [SAS_EDGE_EXPANDER_DEVICE] = "edge",
+               [SAS_FANOUT_EXPANDER_DEVICE] = "fanout",
        };
        struct domain_device *parent = child->parent;
 
@@ -1321,8 +1321,8 @@ static int sas_check_parent_topology(struct domain_device *child)
        if (!child->parent)
                return 0;
 
-       if (child->parent->dev_type != EDGE_DEV &&
-           child->parent->dev_type != FANOUT_DEV)
+       if (child->parent->dev_type != SAS_EDGE_EXPANDER_DEVICE &&
+           child->parent->dev_type != SAS_FANOUT_EXPANDER_DEVICE)
                return 0;
 
        parent_ex = &child->parent->ex_dev;
@@ -1341,8 +1341,8 @@ static int sas_check_parent_topology(struct domain_device *child)
                child_phy = &child_ex->ex_phy[parent_phy->attached_phy_id];
 
                switch (child->parent->dev_type) {
-               case EDGE_DEV:
-                       if (child->dev_type == FANOUT_DEV) {
+               case SAS_EDGE_EXPANDER_DEVICE:
+                       if (child->dev_type == SAS_FANOUT_EXPANDER_DEVICE) {
                                if (parent_phy->routing_attr != SUBTRACTIVE_ROUTING ||
                                    child_phy->routing_attr != TABLE_ROUTING) {
                                        sas_print_parent_topology_bug(child, parent_phy, child_phy);
@@ -1366,7 +1366,7 @@ static int sas_check_parent_topology(struct domain_device *child)
                                }
                        }
                        break;
-               case FANOUT_DEV:
+               case SAS_FANOUT_EXPANDER_DEVICE:
                        if (parent_phy->routing_attr != TABLE_ROUTING ||
                            child_phy->routing_attr != SUBTRACTIVE_ROUTING) {
                                sas_print_parent_topology_bug(child, parent_phy, child_phy);
@@ -1619,8 +1619,8 @@ static int sas_ex_level_discovery(struct asd_sas_port *port, const int level)
        struct domain_device *dev;
 
        list_for_each_entry(dev, &port->dev_list, dev_list_node) {
-               if (dev->dev_type == EDGE_DEV ||
-                   dev->dev_type == FANOUT_DEV) {
+               if (dev->dev_type == SAS_EDGE_EXPANDER_DEVICE ||
+                   dev->dev_type == SAS_FANOUT_EXPANDER_DEVICE) {
                        struct sas_expander_device *ex =
                                rphy_to_expander_device(dev->rphy);
 
@@ -1720,7 +1720,7 @@ static int sas_get_phy_change_count(struct domain_device *dev,
 }
 
 static int sas_get_phy_attached_dev(struct domain_device *dev, int phy_id,
-                                   u8 *sas_addr, enum sas_dev_type *type)
+                                   u8 *sas_addr, enum sas_device_type *type)
 {
        int res;
        struct smp_resp *disc_resp;
@@ -1849,7 +1849,7 @@ static int sas_find_bcast_dev(struct domain_device *dev,
                        SAS_DPRINTK("Expander phys DID NOT change\n");
        }
        list_for_each_entry(ch, &ex->children, siblings) {
-               if (ch->dev_type == EDGE_DEV || ch->dev_type == FANOUT_DEV) {
+               if (ch->dev_type == SAS_EDGE_EXPANDER_DEVICE || ch->dev_type == SAS_FANOUT_EXPANDER_DEVICE) {
                        res = sas_find_bcast_dev(ch, src_dev);
                        if (*src_dev)
                                return res;
@@ -1866,8 +1866,8 @@ static void sas_unregister_ex_tree(struct asd_sas_port *port, struct domain_devi
 
        list_for_each_entry_safe(child, n, &ex->children, siblings) {
                set_bit(SAS_DEV_GONE, &child->state);
-               if (child->dev_type == EDGE_DEV ||
-                   child->dev_type == FANOUT_DEV)
+               if (child->dev_type == SAS_EDGE_EXPANDER_DEVICE ||
+                   child->dev_type == SAS_FANOUT_EXPANDER_DEVICE)
                        sas_unregister_ex_tree(port, child);
                else
                        sas_unregister_dev(port, child);
@@ -1887,8 +1887,8 @@ static void sas_unregister_devs_sas_addr(struct domain_device *parent,
                        if (SAS_ADDR(child->sas_addr) ==
                            SAS_ADDR(phy->attached_sas_addr)) {
                                set_bit(SAS_DEV_GONE, &child->state);
-                               if (child->dev_type == EDGE_DEV ||
-                                   child->dev_type == FANOUT_DEV)
+                               if (child->dev_type == SAS_EDGE_EXPANDER_DEVICE ||
+                                   child->dev_type == SAS_FANOUT_EXPANDER_DEVICE)
                                        sas_unregister_ex_tree(parent->port, child);
                                else
                                        sas_unregister_dev(parent->port, child);
@@ -1916,8 +1916,8 @@ static int sas_discover_bfs_by_root_level(struct domain_device *root,
        int res = 0;
 
        list_for_each_entry(child, &ex_root->children, siblings) {
-               if (child->dev_type == EDGE_DEV ||
-                   child->dev_type == FANOUT_DEV) {
+               if (child->dev_type == SAS_EDGE_EXPANDER_DEVICE ||
+                   child->dev_type == SAS_FANOUT_EXPANDER_DEVICE) {
                        struct sas_expander_device *ex =
                                rphy_to_expander_device(child->rphy);
 
@@ -1970,8 +1970,8 @@ static int sas_discover_new(struct domain_device *dev, int phy_id)
        list_for_each_entry(child, &dev->ex_dev.children, siblings) {
                if (SAS_ADDR(child->sas_addr) ==
                    SAS_ADDR(ex_phy->attached_sas_addr)) {
-                       if (child->dev_type == EDGE_DEV ||
-                           child->dev_type == FANOUT_DEV)
+                       if (child->dev_type == SAS_EDGE_EXPANDER_DEVICE ||
+                           child->dev_type == SAS_FANOUT_EXPANDER_DEVICE)
                                res = sas_discover_bfs_by_root(child);
                        break;
                }
@@ -1979,16 +1979,16 @@ static int sas_discover_new(struct domain_device *dev, int phy_id)
        return res;
 }
 
-static bool dev_type_flutter(enum sas_dev_type new, enum sas_dev_type old)
+static bool dev_type_flutter(enum sas_device_type new, enum sas_device_type old)
 {
        if (old == new)
                return true;
 
        /* treat device directed resets as flutter, if we went
-        * SAS_END_DEV to SATA_PENDING the link needs recovery
+        * SAS_END_DEVICE to SAS_SATA_PENDING the link needs recovery
         */
-       if ((old == SATA_PENDING && new == SAS_END_DEV) ||
-           (old == SAS_END_DEV && new == SATA_PENDING))
+       if ((old == SAS_SATA_PENDING && new == SAS_END_DEVICE) ||
+           (old == SAS_END_DEVICE && new == SAS_SATA_PENDING))
                return true;
 
        return false;
@@ -1998,7 +1998,7 @@ static int sas_rediscover_dev(struct domain_device *dev, int phy_id, bool last)
 {
        struct expander_device *ex = &dev->ex_dev;
        struct ex_phy *phy = &ex->ex_phy[phy_id];
-       enum sas_dev_type type = NO_DEVICE;
+       enum sas_device_type type = SAS_PHY_UNUSED;
        u8 sas_addr[8];
        int res;
 
@@ -2032,7 +2032,7 @@ static int sas_rediscover_dev(struct domain_device *dev, int phy_id, bool last)
 
                sas_ex_phy_discover(dev, phy_id);
 
-               if (ata_dev && phy->attached_dev_type == SATA_PENDING)
+               if (ata_dev && phy->attached_dev_type == SAS_SATA_PENDING)
                        action = ", needs recovery";
                SAS_DPRINTK("ex %016llx phy 0x%x broadcast flutter%s\n",
                            SAS_ADDR(dev->sas_addr), phy_id, action);
index 1de6796..7e7ba83 100644 (file)
@@ -131,16 +131,16 @@ static inline void sas_fill_in_rphy(struct domain_device *dev,
        rphy->identify.initiator_port_protocols = dev->iproto;
        rphy->identify.target_port_protocols = dev->tproto;
        switch (dev->dev_type) {
-       case SATA_DEV:
+       case SAS_SATA_DEV:
                /* FIXME: need sata device type */
-       case SAS_END_DEV:
-       case SATA_PENDING:
+       case SAS_END_DEVICE:
+       case SAS_SATA_PENDING:
                rphy->identify.device_type = SAS_END_DEVICE;
                break;
-       case EDGE_DEV:
+       case SAS_EDGE_EXPANDER_DEVICE:
                rphy->identify.device_type = SAS_EDGE_EXPANDER_DEVICE;
                break;
-       case FANOUT_DEV:
+       case SAS_FANOUT_EXPANDER_DEVICE:
                rphy->identify.device_type = SAS_FANOUT_EXPANDER_DEVICE;
                break;
        default:
index 1398b71..d3c5297 100644 (file)
@@ -69,7 +69,7 @@ static void sas_resume_port(struct asd_sas_phy *phy)
                        continue;
                }
 
-               if (dev->dev_type == EDGE_DEV || dev->dev_type == FANOUT_DEV) {
+               if (dev->dev_type == SAS_EDGE_EXPANDER_DEVICE || dev->dev_type == SAS_FANOUT_EXPANDER_DEVICE) {
                        dev->ex_dev.ex_change_count = -1;
                        for (i = 0; i < dev->ex_dev.num_phys; i++) {
                                struct ex_phy *phy = &dev->ex_dev.ex_phy[i];
index 7706c99..bcc56ca 100644 (file)
@@ -46,10 +46,15 @@ struct lpfc_sli2_slim;
 #define LPFC_DEFAULT_MENLO_SG_SEG_CNT 128      /* sg element count per scsi
                cmnd for menlo needs nearly twice as for firmware
                downloads using bsg */
-#define LPFC_DEFAULT_PROT_SG_SEG_CNT 4096 /* sg protection elements count */
+
+#define LPFC_MIN_SG_SLI4_BUF_SZ        0x800   /* based on LPFC_DEFAULT_SG_SEG_CNT */
+#define LPFC_MAX_SG_SLI4_SEG_CNT_DIF 128 /* sg element count per scsi cmnd */
+#define LPFC_MAX_SG_SEG_CNT_DIF 512    /* sg element count per scsi cmnd  */
 #define LPFC_MAX_SG_SEG_CNT    4096    /* sg element count per scsi cmnd */
+#define LPFC_MAX_SGL_SEG_CNT   512     /* SGL element count per scsi cmnd */
+#define LPFC_MAX_BPL_SEG_CNT   4096    /* BPL element count per scsi cmnd */
+
 #define LPFC_MAX_SGE_SIZE       0x80000000 /* Maximum data allowed in a SGE */
-#define LPFC_MAX_PROT_SG_SEG_CNT 4096  /* prot sg element count per scsi cmd*/
 #define LPFC_IOCB_LIST_CNT     2250    /* list of IOCBs for fast-path usage. */
 #define LPFC_Q_RAMP_UP_INTERVAL 120     /* lun q_depth ramp up interval */
 #define LPFC_VNAME_LEN         100     /* vport symbolic name length */
@@ -66,8 +71,10 @@ struct lpfc_sli2_slim;
  * queue depths when there are driver resource error or Firmware
  * resource error.
  */
-#define QUEUE_RAMP_DOWN_INTERVAL       (1 * HZ)   /* 1 Second */
-#define QUEUE_RAMP_UP_INTERVAL         (300 * HZ) /* 5 minutes */
+/* 1 Second */
+#define QUEUE_RAMP_DOWN_INTERVAL       (msecs_to_jiffies(1000 * 1))
+/* 5 minutes */
+#define QUEUE_RAMP_UP_INTERVAL         (msecs_to_jiffies(1000 * 300))
 
 /* Number of exchanges reserved for discovery to complete */
 #define LPFC_DISC_IOCB_BUFF_COUNT 20
@@ -671,6 +678,7 @@ struct lpfc_hba {
        uint32_t lmt;
 
        uint32_t fc_topology;   /* link topology, from LINK INIT */
+       uint32_t fc_topology_changed;   /* link topology, from LINK INIT */
 
        struct lpfc_stats fc_stat;
 
@@ -701,9 +709,11 @@ struct lpfc_hba {
        uint32_t cfg_poll_tmo;
        uint32_t cfg_use_msi;
        uint32_t cfg_fcp_imax;
+       uint32_t cfg_fcp_cpu_map;
        uint32_t cfg_fcp_wq_count;
        uint32_t cfg_fcp_eq_count;
        uint32_t cfg_fcp_io_channel;
+       uint32_t cfg_total_seg_cnt;
        uint32_t cfg_sg_seg_cnt;
        uint32_t cfg_prot_sg_seg_cnt;
        uint32_t cfg_sg_dma_buf_size;
@@ -804,8 +814,10 @@ struct lpfc_hba {
        uint64_t bg_reftag_err_cnt;
 
        /* fastpath list. */
-       spinlock_t scsi_buf_list_lock;
-       struct list_head lpfc_scsi_buf_list;
+       spinlock_t scsi_buf_list_get_lock;  /* SCSI buf alloc list lock */
+       spinlock_t scsi_buf_list_put_lock;  /* SCSI buf free list lock */
+       struct list_head lpfc_scsi_buf_list_get;
+       struct list_head lpfc_scsi_buf_list_put;
        uint32_t total_scsi_bufs;
        struct list_head lpfc_iocb_list;
        uint32_t total_iocbq_bufs;
index 9290713..3c5625b 100644 (file)
@@ -674,6 +674,9 @@ lpfc_do_offline(struct lpfc_hba *phba, uint32_t type)
        int i;
        int rc;
 
+       if (phba->pport->fc_flag & FC_OFFLINE_MODE)
+               return 0;
+
        init_completion(&online_compl);
        rc = lpfc_workq_post_event(phba, &status, &online_compl,
                              LPFC_EVT_OFFLINE_PREP);
@@ -741,7 +744,8 @@ lpfc_selective_reset(struct lpfc_hba *phba)
        int status = 0;
        int rc;
 
-       if (!phba->cfg_enable_hba_reset)
+       if ((!phba->cfg_enable_hba_reset) ||
+           (phba->pport->fc_flag & FC_OFFLINE_MODE))
                return -EACCES;
 
        status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE);
@@ -895,6 +899,7 @@ lpfc_sli4_pdev_reg_request(struct lpfc_hba *phba, uint32_t opcode)
                pci_disable_sriov(pdev);
                phba->cfg_sriov_nr_virtfn = 0;
        }
+
        status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE);
 
        if (status != 0)
@@ -2801,6 +2806,8 @@ lpfc_topology_store(struct device *dev, struct device_attribute *attr,
                lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
                        "3054 lpfc_topology changed from %d to %d\n",
                        prev_val, val);
+               if (prev_val != val && phba->sli_rev == LPFC_SLI_REV4)
+                       phba->fc_topology_changed = 1;
                err = lpfc_issue_lip(lpfc_shost_from_vport(phba->pport));
                if (err) {
                        phba->cfg_topology = prev_val;
@@ -3792,6 +3799,141 @@ lpfc_fcp_imax_init(struct lpfc_hba *phba, int val)
 static DEVICE_ATTR(lpfc_fcp_imax, S_IRUGO | S_IWUSR,
                   lpfc_fcp_imax_show, lpfc_fcp_imax_store);
 
+/**
+ * lpfc_state_show - Display current driver CPU affinity
+ * @dev: class converted to a Scsi_host structure.
+ * @attr: device attribute, not used.
+ * @buf: on return contains text describing the state of the link.
+ *
+ * Returns: size of formatted string.
+ **/
+static ssize_t
+lpfc_fcp_cpu_map_show(struct device *dev, struct device_attribute *attr,
+                     char *buf)
+{
+       struct Scsi_Host  *shost = class_to_shost(dev);
+       struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata;
+       struct lpfc_hba   *phba = vport->phba;
+       struct lpfc_vector_map_info *cpup;
+       int  idx, len = 0;
+
+       if ((phba->sli_rev != LPFC_SLI_REV4) ||
+           (phba->intr_type != MSIX))
+               return len;
+
+       switch (phba->cfg_fcp_cpu_map) {
+       case 0:
+               len += snprintf(buf + len, PAGE_SIZE-len,
+                               "fcp_cpu_map: No mapping (%d)\n",
+                               phba->cfg_fcp_cpu_map);
+               return len;
+       case 1:
+               len += snprintf(buf + len, PAGE_SIZE-len,
+                               "fcp_cpu_map: HBA centric mapping (%d): "
+                               "%d online CPUs\n",
+                               phba->cfg_fcp_cpu_map,
+                               phba->sli4_hba.num_online_cpu);
+               break;
+       case 2:
+               len += snprintf(buf + len, PAGE_SIZE-len,
+                               "fcp_cpu_map: Driver centric mapping (%d): "
+                               "%d online CPUs\n",
+                               phba->cfg_fcp_cpu_map,
+                               phba->sli4_hba.num_online_cpu);
+               break;
+       }
+
+       cpup = phba->sli4_hba.cpu_map;
+       for (idx = 0; idx < phba->sli4_hba.num_present_cpu; idx++) {
+               if (cpup->irq == LPFC_VECTOR_MAP_EMPTY)
+                       len += snprintf(buf + len, PAGE_SIZE-len,
+                                       "CPU %02d io_chan %02d "
+                                       "physid %d coreid %d\n",
+                                       idx, cpup->channel_id, cpup->phys_id,
+                                       cpup->core_id);
+               else
+                       len += snprintf(buf + len, PAGE_SIZE-len,
+                                       "CPU %02d io_chan %02d "
+                                       "physid %d coreid %d IRQ %d\n",
+                                       idx, cpup->channel_id, cpup->phys_id,
+                                       cpup->core_id, cpup->irq);
+
+               cpup++;
+       }
+       return len;
+}
+
+/**
+ * lpfc_fcp_cpu_map_store - Change CPU affinity of driver vectors
+ * @dev: class device that is converted into a Scsi_host.
+ * @attr: device attribute, not used.
+ * @buf: one or more lpfc_polling_flags values.
+ * @count: not used.
+ *
+ * Returns:
+ * -EINVAL  - Not implemented yet.
+ **/
+static ssize_t
+lpfc_fcp_cpu_map_store(struct device *dev, struct device_attribute *attr,
+                      const char *buf, size_t count)
+{
+       int status = -EINVAL;
+       return status;
+}
+
+/*
+# lpfc_fcp_cpu_map: Defines how to map CPUs to IRQ vectors
+# for the HBA.
+#
+# Value range is [0 to 2]. Default value is LPFC_DRIVER_CPU_MAP (2).
+#      0 - Do not affinitze IRQ vectors
+#      1 - Affintize HBA vectors with respect to each HBA
+#          (start with CPU0 for each HBA)
+#      2 - Affintize HBA vectors with respect to the entire driver
+#          (round robin thru all CPUs across all HBAs)
+*/
+static int lpfc_fcp_cpu_map = LPFC_DRIVER_CPU_MAP;
+module_param(lpfc_fcp_cpu_map, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(lpfc_fcp_cpu_map,
+                "Defines how to map CPUs to IRQ vectors per HBA");
+
+/**
+ * lpfc_fcp_cpu_map_init - Set the initial sr-iov virtual function enable
+ * @phba: lpfc_hba pointer.
+ * @val: link speed value.
+ *
+ * Description:
+ * If val is in a valid range [0-2], then affinitze the adapter's
+ * MSIX vectors.
+ *
+ * Returns:
+ * zero if val saved.
+ * -EINVAL val out of range
+ **/
+static int
+lpfc_fcp_cpu_map_init(struct lpfc_hba *phba, int val)
+{
+       if (phba->sli_rev != LPFC_SLI_REV4) {
+               phba->cfg_fcp_cpu_map = 0;
+               return 0;
+       }
+
+       if (val >= LPFC_MIN_CPU_MAP && val <= LPFC_MAX_CPU_MAP) {
+               phba->cfg_fcp_cpu_map = val;
+               return 0;
+       }
+
+       lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                       "3326 fcp_cpu_map: %d out of range, using default\n",
+                       val);
+       phba->cfg_fcp_cpu_map = LPFC_DRIVER_CPU_MAP;
+
+       return 0;
+}
+
+static DEVICE_ATTR(lpfc_fcp_cpu_map, S_IRUGO | S_IWUSR,
+                  lpfc_fcp_cpu_map_show, lpfc_fcp_cpu_map_store);
+
 /*
 # lpfc_fcp_class:  Determines FC class to use for the FCP protocol.
 # Value range is [2,3]. Default value is 3.
@@ -4009,12 +4151,11 @@ LPFC_ATTR_R(enable_bg, 0, 0, 1, "Enable BlockGuard Support");
 #       0  = disabled (default)
 #       1  = enabled
 # Value range is [0,1]. Default value is 0.
+#
+# This feature in under investigation and may be supported in the future.
 */
 unsigned int lpfc_fcp_look_ahead = LPFC_LOOK_AHEAD_OFF;
 
-module_param(lpfc_fcp_look_ahead, uint, S_IRUGO);
-MODULE_PARM_DESC(lpfc_fcp_look_ahead, "Look ahead for completions");
-
 /*
 # lpfc_prot_mask: i
 #      - Bit mask of host protection capabilities used to register with the
@@ -4071,16 +4212,23 @@ MODULE_PARM_DESC(lpfc_delay_discovery,
 
 /*
  * lpfc_sg_seg_cnt - Initial Maximum DMA Segment Count
- * This value can be set to values between 64 and 256. The default value is
+ * This value can be set to values between 64 and 4096. The default value is
  * 64, but may be increased to allow for larger Max I/O sizes. The scsi layer
  * will be allowed to request I/Os of sizes up to (MAX_SEG_COUNT * SEG_SIZE).
+ * Because of the additional overhead involved in setting up T10-DIF,
+ * this parameter will be limited to 128 if BlockGuard is enabled under SLI4
+ * and will be limited to 512 if BlockGuard is enabled under SLI3.
  */
 LPFC_ATTR_R(sg_seg_cnt, LPFC_DEFAULT_SG_SEG_CNT, LPFC_DEFAULT_SG_SEG_CNT,
            LPFC_MAX_SG_SEG_CNT, "Max Scatter Gather Segment Count");
 
-LPFC_ATTR_R(prot_sg_seg_cnt, LPFC_DEFAULT_PROT_SG_SEG_CNT,
-               LPFC_DEFAULT_PROT_SG_SEG_CNT, LPFC_MAX_PROT_SG_SEG_CNT,
-               "Max Protection Scatter Gather Segment Count");
+/*
+ * This parameter will be depricated, the driver cannot limit the
+ * protection data s/g list.
+ */
+LPFC_ATTR_R(prot_sg_seg_cnt, LPFC_DEFAULT_SG_SEG_CNT,
+           LPFC_DEFAULT_SG_SEG_CNT, LPFC_MAX_SG_SEG_CNT,
+           "Max Protection Scatter Gather Segment Count");
 
 struct device_attribute *lpfc_hba_attrs[] = {
        &dev_attr_bg_info,
@@ -4141,6 +4289,7 @@ struct device_attribute *lpfc_hba_attrs[] = {
        &dev_attr_lpfc_poll_tmo,
        &dev_attr_lpfc_use_msi,
        &dev_attr_lpfc_fcp_imax,
+       &dev_attr_lpfc_fcp_cpu_map,
        &dev_attr_lpfc_fcp_wq_count,
        &dev_attr_lpfc_fcp_eq_count,
        &dev_attr_lpfc_fcp_io_channel,
@@ -5123,6 +5272,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
        lpfc_enable_rrq_init(phba, lpfc_enable_rrq);
        lpfc_use_msi_init(phba, lpfc_use_msi);
        lpfc_fcp_imax_init(phba, lpfc_fcp_imax);
+       lpfc_fcp_cpu_map_init(phba, lpfc_fcp_cpu_map);
        lpfc_fcp_wq_count_init(phba, lpfc_fcp_wq_count);
        lpfc_fcp_eq_count_init(phba, lpfc_fcp_eq_count);
        lpfc_fcp_io_channel_init(phba, lpfc_fcp_io_channel);
index 8886668..094be2c 100644 (file)
@@ -219,26 +219,35 @@ lpfc_bsg_copy_data(struct lpfc_dmabuf *dma_buffers,
        unsigned int transfer_bytes, bytes_copied = 0;
        unsigned int sg_offset, dma_offset;
        unsigned char *dma_address, *sg_address;
-       struct scatterlist *sgel;
        LIST_HEAD(temp_list);
-
+       struct sg_mapping_iter miter;
+       unsigned long flags;
+       unsigned int sg_flags = SG_MITER_ATOMIC;
+       bool sg_valid;
 
        list_splice_init(&dma_buffers->list, &temp_list);
        list_add(&dma_buffers->list, &temp_list);
        sg_offset = 0;
-       sgel = bsg_buffers->sg_list;
+       if (to_buffers)
+               sg_flags |= SG_MITER_FROM_SG;
+       else
+               sg_flags |= SG_MITER_TO_SG;
+       sg_miter_start(&miter, bsg_buffers->sg_list, bsg_buffers->sg_cnt,
+                      sg_flags);
+       local_irq_save(flags);
+       sg_valid = sg_miter_next(&miter);
        list_for_each_entry(mp, &temp_list, list) {
                dma_offset = 0;
-               while (bytes_to_transfer && sgel &&
+               while (bytes_to_transfer && sg_valid &&
                       (dma_offset < LPFC_BPL_SIZE)) {
                        dma_address = mp->virt + dma_offset;
                        if (sg_offset) {
                                /* Continue previous partial transfer of sg */
-                               sg_address = sg_virt(sgel) + sg_offset;
-                               transfer_bytes = sgel->length - sg_offset;
+                               sg_address = miter.addr + sg_offset;
+                               transfer_bytes = miter.length - sg_offset;
                        } else {
-                               sg_address = sg_virt(sgel);
-                               transfer_bytes = sgel->length;
+                               sg_address = miter.addr;
+                               transfer_bytes = miter.length;
                        }
                        if (bytes_to_transfer < transfer_bytes)
                                transfer_bytes = bytes_to_transfer;
@@ -252,12 +261,14 @@ lpfc_bsg_copy_data(struct lpfc_dmabuf *dma_buffers,
                        sg_offset += transfer_bytes;
                        bytes_to_transfer -= transfer_bytes;
                        bytes_copied += transfer_bytes;
-                       if (sg_offset >= sgel->length) {
+                       if (sg_offset >= miter.length) {
                                sg_offset = 0;
-                               sgel = sg_next(sgel);
+                               sg_valid = sg_miter_next(&miter);
                        }
                }
        }
+       sg_miter_stop(&miter);
+       local_irq_restore(flags);
        list_del_init(&dma_buffers->list);
        list_splice(&temp_list, &dma_buffers->list);
        return bytes_copied;
@@ -471,6 +482,7 @@ lpfc_bsg_send_mgmt_cmd(struct fc_bsg_job *job)
        cmdiocbq->context1 = dd_data;
        cmdiocbq->context2 = cmp;
        cmdiocbq->context3 = bmp;
+       cmdiocbq->context_un.ndlp = ndlp;
        dd_data->type = TYPE_IOCB;
        dd_data->set_job = job;
        dd_data->context_un.iocb.cmdiocbq = cmdiocbq;
@@ -1508,6 +1520,7 @@ lpfc_issue_ct_rsp(struct lpfc_hba *phba, struct fc_bsg_job *job, uint32_t tag,
        ctiocb->context1 = dd_data;
        ctiocb->context2 = cmp;
        ctiocb->context3 = bmp;
+       ctiocb->context_un.ndlp = ndlp;
        ctiocb->iocb_cmpl = lpfc_issue_ct_rsp_cmp;
 
        dd_data->type = TYPE_IOCB;
@@ -2576,7 +2589,8 @@ static int lpfcdiag_loop_get_xri(struct lpfc_hba *phba, uint16_t rpi,
        evt->wait_time_stamp = jiffies;
        time_left = wait_event_interruptible_timeout(
                evt->wq, !list_empty(&evt->events_to_see),
-               ((phba->fc_ratov * 2) + LPFC_DRVR_TIMEOUT) * HZ);
+               msecs_to_jiffies(1000 *
+                       ((phba->fc_ratov * 2) + LPFC_DRVR_TIMEOUT)));
        if (list_empty(&evt->events_to_see))
                ret_val = (time_left) ? -EINTR : -ETIMEDOUT;
        else {
@@ -3151,7 +3165,8 @@ lpfc_bsg_diag_loopback_run(struct fc_bsg_job *job)
        evt->waiting = 1;
        time_left = wait_event_interruptible_timeout(
                evt->wq, !list_empty(&evt->events_to_see),
-               ((phba->fc_ratov * 2) + LPFC_DRVR_TIMEOUT) * HZ);
+               msecs_to_jiffies(1000 *
+                       ((phba->fc_ratov * 2) + LPFC_DRVR_TIMEOUT)));
        evt->waiting = 0;
        if (list_empty(&evt->events_to_see)) {
                rc = (time_left) ? -EINTR : -ETIMEDOUT;
index 7631893..d41456e 100644 (file)
@@ -470,3 +470,4 @@ int lpfc_sli4_xri_sgl_update(struct lpfc_hba *);
 void lpfc_free_sgl_list(struct lpfc_hba *, struct list_head *);
 uint32_t lpfc_sli_port_speed_get(struct lpfc_hba *);
 int lpfc_sli4_request_firmware_update(struct lpfc_hba *, uint8_t);
+void lpfc_sli4_offline_eratt(struct lpfc_hba *);
index 7bff3a1..ae1a07c 100644 (file)
@@ -1811,7 +1811,8 @@ lpfc_fdmi_timeout_handler(struct lpfc_vport *vport)
                if (init_utsname()->nodename[0] != '\0')
                        lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_DHBA);
                else
-                       mod_timer(&vport->fc_fdmitmo, jiffies + HZ * 60);
+                       mod_timer(&vport->fc_fdmitmo, jiffies +
+                                 msecs_to_jiffies(1000 * 60));
        }
        return;
 }
index bbed847..3cae0a9 100644 (file)
@@ -29,6 +29,7 @@
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_transport_fc.h>
 
+
 #include "lpfc_hw4.h"
 #include "lpfc_hw.h"
 #include "lpfc_sli.h"
@@ -238,7 +239,10 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp,
 
                icmd->un.elsreq64.remoteID = did;               /* DID */
                icmd->ulpCommand = CMD_ELS_REQUEST64_CR;
-               icmd->ulpTimeout = phba->fc_ratov * 2;
+               if (elscmd == ELS_CMD_FLOGI)
+                       icmd->ulpTimeout = FF_DEF_RATOV * 2;
+               else
+                       icmd->ulpTimeout = phba->fc_ratov * 2;
        } else {
                icmd->un.xseq64.bdl.addrHigh = putPaddrHigh(pbuflist->phys);
                icmd->un.xseq64.bdl.addrLow = putPaddrLow(pbuflist->phys);
@@ -308,16 +312,20 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp,
                /* Xmit ELS command <elsCmd> to remote NPORT <did> */
                lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
                                 "0116 Xmit ELS command x%x to remote "
-                                "NPORT x%x I/O tag: x%x, port state: x%x\n",
+                                "NPORT x%x I/O tag: x%x, port state:x%x"
+                                " fc_flag:x%x\n",
                                 elscmd, did, elsiocb->iotag,
-                                vport->port_state);
+                                vport->port_state,
+                                vport->fc_flag);
        } else {
                /* Xmit ELS response <elsCmd> to remote NPORT <did> */
                lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
                                 "0117 Xmit ELS response x%x to remote "
-                                "NPORT x%x I/O tag: x%x, size: x%x\n",
+                                "NPORT x%x I/O tag: x%x, size: x%x "
+                                "port_state x%x fc_flag x%x\n",
                                 elscmd, ndlp->nlp_DID, elsiocb->iotag,
-                                cmdSize);
+                                cmdSize, vport->port_state,
+                                vport->fc_flag);
        }
        return elsiocb;
 
@@ -909,6 +917,23 @@ lpfc_cmpl_els_flogi_nport(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
        spin_lock_irq(shost->host_lock);
        vport->fc_flag |= FC_PT2PT;
        spin_unlock_irq(shost->host_lock);
+       /* If physical FC port changed, unreg VFI and ALL VPIs / RPIs */
+       if ((phba->sli_rev == LPFC_SLI_REV4) && phba->fc_topology_changed) {
+               lpfc_unregister_fcf_prep(phba);
+
+               /* The FC_VFI_REGISTERED flag will get clear in the cmpl
+                * handler for unreg_vfi, but if we don't force the
+                * FC_VFI_REGISTERED flag then the reg_vfi mailbox could be
+                * built with the update bit set instead of just the vp bit to
+                * change the Nport ID.  We need to have the vp set and the
+                * Upd cleared on topology changes.
+                */
+               spin_lock_irq(shost->host_lock);
+               vport->fc_flag &= ~FC_VFI_REGISTERED;
+               spin_unlock_irq(shost->host_lock);
+               phba->fc_topology_changed = 0;
+               lpfc_issue_reg_vfi(vport);
+       }
 
        /* Start discovery - this should just do CLEAR_LA */
        lpfc_disc_start(vport);
@@ -1030,9 +1055,19 @@ stop_rr_fcf_flogi:
                        vport->cfg_discovery_threads = LPFC_MAX_DISC_THREADS;
                if ((phba->sli_rev == LPFC_SLI_REV4) &&
                    (!(vport->fc_flag & FC_VFI_REGISTERED) ||
-                    (vport->fc_prevDID != vport->fc_myDID))) {
-                       if (vport->fc_flag & FC_VFI_REGISTERED)
-                               lpfc_sli4_unreg_all_rpis(vport);
+                    (vport->fc_prevDID != vport->fc_myDID) ||
+                       phba->fc_topology_changed)) {
+                       if (vport->fc_flag & FC_VFI_REGISTERED) {
+                               if (phba->fc_topology_changed) {
+                                       lpfc_unregister_fcf_prep(phba);
+                                       spin_lock_irq(shost->host_lock);
+                                       vport->fc_flag &= ~FC_VFI_REGISTERED;
+                                       spin_unlock_irq(shost->host_lock);
+                                       phba->fc_topology_changed = 0;
+                               } else {
+                                       lpfc_sli4_unreg_all_rpis(vport);
+                               }
+                       }
                        lpfc_issue_reg_vfi(vport);
                        lpfc_nlp_put(ndlp);
                        goto out;
@@ -1054,10 +1089,11 @@ stop_rr_fcf_flogi:
 
        /* FLOGI completes successfully */
        lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
-                        "0101 FLOGI completes successfully "
-                        "Data: x%x x%x x%x x%x\n",
+                        "0101 FLOGI completes successfully, I/O tag:x%x, "
+                        "Data: x%x x%x x%x x%x x%x x%x\n", cmdiocb->iotag,
                         irsp->un.ulpWord[4], sp->cmn.e_d_tov,
-                        sp->cmn.w2.r_a_tov, sp->cmn.edtovResolution);
+                        sp->cmn.w2.r_a_tov, sp->cmn.edtovResolution,
+                        vport->port_state, vport->fc_flag);
 
        if (vport->port_state == LPFC_FLOGI) {
                /*
@@ -5047,6 +5083,8 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
        struct ls_rjt stat;
        uint32_t cmd, did;
        int rc;
+       uint32_t fc_flag = 0;
+       uint32_t port_state = 0;
 
        cmd = *lp++;
        sp = (struct serv_parm *) lp;
@@ -5113,16 +5151,25 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
                         * will be.
                         */
                        vport->fc_myDID = PT2PT_LocalID;
-               }
+               } else
+                       vport->fc_myDID = PT2PT_RemoteID;
 
                /*
                 * The vport state should go to LPFC_FLOGI only
                 * AFTER we issue a FLOGI, not receive one.
                 */
                spin_lock_irq(shost->host_lock);
+               fc_flag = vport->fc_flag;
+               port_state = vport->port_state;
                vport->fc_flag |= FC_PT2PT;
                vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
+               vport->port_state = LPFC_FLOGI;
                spin_unlock_irq(shost->host_lock);
+               lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+                                "3311 Rcv Flogi PS x%x new PS x%x "
+                                "fc_flag x%x new fc_flag x%x\n",
+                                port_state, vport->port_state,
+                                fc_flag, vport->fc_flag);
 
                /*
                 * We temporarily set fc_myDID to make it look like we are
@@ -6241,7 +6288,8 @@ lpfc_els_timeout_handler(struct lpfc_vport *vport)
        }
 
        if (!list_empty(&phba->sli.ring[LPFC_ELS_RING].txcmplq))
-               mod_timer(&vport->els_tmofunc, jiffies + HZ * timeout);
+               mod_timer(&vport->els_tmofunc,
+                         jiffies + msecs_to_jiffies(1000 * timeout));
 }
 
 /**
@@ -6612,7 +6660,9 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
        /* ELS command <elsCmd> received from NPORT <did> */
        lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
                         "0112 ELS command x%x received from NPORT x%x "
-                        "Data: x%x\n", cmd, did, vport->port_state);
+                        "Data: x%x x%x x%x x%x\n",
+                       cmd, did, vport->port_state, vport->fc_flag,
+                       vport->fc_myDID, vport->fc_prevDID);
        switch (cmd) {
        case ELS_CMD_PLOGI:
                lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
@@ -6621,6 +6671,19 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
 
                phba->fc_stat.elsRcvPLOGI++;
                ndlp = lpfc_plogi_confirm_nport(phba, payload, ndlp);
+               if (phba->sli_rev == LPFC_SLI_REV4 &&
+                   (phba->pport->fc_flag & FC_PT2PT)) {
+                       vport->fc_prevDID = vport->fc_myDID;
+                       /* Our DID needs to be updated before registering
+                        * the vfi. This is done in lpfc_rcv_plogi but
+                        * that is called after the reg_vfi.
+                        */
+                       vport->fc_myDID = elsiocb->iocb.un.rcvels.parmRo;
+                       lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+                                        "3312 Remote port assigned DID x%x "
+                                        "%x\n", vport->fc_myDID,
+                                        vport->fc_prevDID);
+               }
 
                lpfc_send_els_event(vport, ndlp, payload);
 
@@ -6630,6 +6693,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
                        rjt_exp = LSEXP_NOTHING_MORE;
                        break;
                }
+               shost = lpfc_shost_from_vport(vport);
                if (vport->port_state < LPFC_DISC_AUTH) {
                        if (!(phba->pport->fc_flag & FC_PT2PT) ||
                                (phba->pport->fc_flag & FC_PT2PT_PLOGI)) {
@@ -6641,9 +6705,18 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
                         * another NPort and the other side has initiated
                         * the PLOGI before responding to our FLOGI.
                         */
+                       if (phba->sli_rev == LPFC_SLI_REV4 &&
+                           (phba->fc_topology_changed ||
+                            vport->fc_myDID != vport->fc_prevDID)) {
+                               lpfc_unregister_fcf_prep(phba);
+                               spin_lock_irq(shost->host_lock);
+                               vport->fc_flag &= ~FC_VFI_REGISTERED;
+                               spin_unlock_irq(shost->host_lock);
+                               phba->fc_topology_changed = 0;
+                               lpfc_issue_reg_vfi(vport);
+                       }
                }
 
-               shost = lpfc_shost_from_vport(vport);
                spin_lock_irq(shost->host_lock);
                ndlp->nlp_flag &= ~NLP_TARGET_REMOVE;
                spin_unlock_irq(shost->host_lock);
@@ -7002,8 +7075,11 @@ lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport)
        spin_lock_irq(shost->host_lock);
        if (vport->fc_flag & FC_DISC_DELAYED) {
                spin_unlock_irq(shost->host_lock);
+               lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
+                               "3334 Delay fc port discovery for %d seconds\n",
+                               phba->fc_ratov);
                mod_timer(&vport->delayed_disc_tmo,
-                       jiffies + HZ * phba->fc_ratov);
+                       jiffies + msecs_to_jiffies(1000 * phba->fc_ratov));
                return;
        }
        spin_unlock_irq(shost->host_lock);
@@ -7287,7 +7363,7 @@ lpfc_retry_pport_discovery(struct lpfc_hba *phba)
                return;
 
        shost = lpfc_shost_from_vport(phba->pport);
-       mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ);
+       mod_timer(&ndlp->nlp_delayfunc, jiffies + msecs_to_jiffies(1000));
        spin_lock_irq(shost->host_lock);
        ndlp->nlp_flag |= NLP_DELAY_TMO;
        spin_unlock_irq(shost->host_lock);
@@ -7791,7 +7867,8 @@ lpfc_block_fabric_iocbs(struct lpfc_hba *phba)
        blocked = test_and_set_bit(FABRIC_COMANDS_BLOCKED, &phba->bit_flags);
        /* Start a timer to unblock fabric iocbs after 100ms */
        if (!blocked)
-               mod_timer(&phba->fabric_block_timer, jiffies + HZ/10 );
+               mod_timer(&phba->fabric_block_timer,
+                         jiffies + msecs_to_jiffies(100));
 
        return;
 }
index 326e05a..0f6e254 100644 (file)
@@ -160,11 +160,12 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport)
        if (!list_empty(&evtp->evt_listp))
                return;
 
+       evtp->evt_arg1  = lpfc_nlp_get(ndlp);
+
        spin_lock_irq(&phba->hbalock);
        /* We need to hold the node by incrementing the reference
         * count until this queued work is done
         */
-       evtp->evt_arg1  = lpfc_nlp_get(ndlp);
        if (evtp->evt_arg1) {
                evtp->evt = LPFC_EVT_DEV_LOSS;
                list_add_tail(&evtp->evt_listp, &phba->work_list);
@@ -1008,9 +1009,6 @@ lpfc_linkup(struct lpfc_hba *phba)
                for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++)
                        lpfc_linkup_port(vports[i]);
        lpfc_destroy_vport_work_array(phba, vports);
-       if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) &&
-           (phba->sli_rev < LPFC_SLI_REV4))
-               lpfc_issue_clear_la(phba, phba->pport);
 
        return 0;
 }
@@ -1436,7 +1434,8 @@ lpfc_register_fcf(struct lpfc_hba *phba)
        if (phba->fcf.fcf_flag & FCF_REGISTERED) {
                phba->fcf.fcf_flag |= (FCF_SCAN_DONE | FCF_IN_USE);
                phba->hba_flag &= ~FCF_TS_INPROG;
-               if (phba->pport->port_state != LPFC_FLOGI) {
+               if (phba->pport->port_state != LPFC_FLOGI &&
+                   phba->pport->fc_flag & FC_FABRIC) {
                        phba->hba_flag |= FCF_RR_INPROG;
                        spin_unlock_irq(&phba->hbalock);
                        lpfc_initial_flogi(phba->pport);
@@ -2270,8 +2269,11 @@ lpfc_mbx_cmpl_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
                                spin_unlock_irq(&phba->hbalock);
                                lpfc_printf_log(phba, KERN_INFO, LOG_FIP,
                                                "2836 New FCF matches in-use "
-                                               "FCF (x%x)\n",
-                                               phba->fcf.current_rec.fcf_indx);
+                                               "FCF (x%x), port_state:x%x, "
+                                               "fc_flag:x%x\n",
+                                               phba->fcf.current_rec.fcf_indx,
+                                               phba->pport->port_state,
+                                               phba->pport->fc_flag);
                                goto out;
                        } else
                                lpfc_printf_log(phba, KERN_ERR, LOG_FIP,
@@ -2796,7 +2798,19 @@ void
 lpfc_issue_init_vpi(struct lpfc_vport *vport)
 {
        LPFC_MBOXQ_t *mboxq;
-       int rc;
+       int rc, vpi;
+
+       if ((vport->port_type != LPFC_PHYSICAL_PORT) && (!vport->vpi)) {
+               vpi = lpfc_alloc_vpi(vport->phba);
+               if (!vpi) {
+                       lpfc_printf_vlog(vport, KERN_ERR,
+                                        LOG_MBOX,
+                                        "3303 Failed to obtain vport vpi\n");
+                       lpfc_vport_set_state(vport, FC_VPORT_FAILED);
+                       return;
+               }
+               vport->vpi = vpi;
+       }
 
        mboxq = mempool_alloc(vport->phba->mbox_mem_pool, GFP_KERNEL);
        if (!mboxq) {
@@ -2894,9 +2908,14 @@ lpfc_mbx_cmpl_reg_vfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
                goto out_free_mem;
        }
 
-       /* If the VFI is already registered, there is nothing else to do */
+       /* If the VFI is already registered, there is nothing else to do
+        * Unless this was a VFI update and we are in PT2PT mode, then
+        * we should drop through to set the port state to ready.
+        */
        if (vport->fc_flag & FC_VFI_REGISTERED)
-               goto out_free_mem;
+               if (!(phba->sli_rev == LPFC_SLI_REV4 &&
+                     vport->fc_flag & FC_PT2PT))
+                       goto out_free_mem;
 
        /* The VPI is implicitly registered when the VFI is registered */
        spin_lock_irq(shost->host_lock);
@@ -2913,6 +2932,13 @@ lpfc_mbx_cmpl_reg_vfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
                goto out_free_mem;
        }
 
+       lpfc_printf_vlog(vport, KERN_INFO, LOG_SLI,
+                        "3313 cmpl reg vfi  port_state:%x fc_flag:%x myDid:%x "
+                        "alpacnt:%d LinkState:%x topology:%x\n",
+                        vport->port_state, vport->fc_flag, vport->fc_myDID,
+                        vport->phba->alpa_map[0],
+                        phba->link_state, phba->fc_topology);
+
        if (vport->port_state == LPFC_FABRIC_CFG_LINK) {
                /*
                 * For private loop or for NPort pt2pt,
@@ -2925,7 +2951,10 @@ lpfc_mbx_cmpl_reg_vfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
                        /* Use loop map to make discovery list */
                        lpfc_disc_list_loopmap(vport);
                        /* Start discovery */
-                       lpfc_disc_start(vport);
+                       if (vport->fc_flag & FC_PT2PT)
+                               vport->port_state = LPFC_VPORT_READY;
+                       else
+                               lpfc_disc_start(vport);
                } else {
                        lpfc_start_fdiscs(phba);
                        lpfc_do_scr_ns_plogi(phba, vport);
@@ -3007,6 +3036,15 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la)
                break;
        }
 
+       if (phba->fc_topology &&
+           phba->fc_topology != bf_get(lpfc_mbx_read_top_topology, la)) {
+               lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
+                               "3314 Toplogy changed was 0x%x is 0x%x\n",
+                               phba->fc_topology,
+                               bf_get(lpfc_mbx_read_top_topology, la));
+               phba->fc_topology_changed = 1;
+       }
+
        phba->fc_topology = bf_get(lpfc_mbx_read_top_topology, la);
        phba->link_flag &= ~LS_NPIV_FAB_SUPPORTED;
 
@@ -4235,7 +4273,7 @@ lpfc_set_disctmo(struct lpfc_vport *vport)
                        tmo, vport->port_state, vport->fc_flag);
        }
 
-       mod_timer(&vport->fc_disctmo, jiffies + HZ * tmo);
+       mod_timer(&vport->fc_disctmo, jiffies + msecs_to_jiffies(1000 * tmo));
        spin_lock_irq(shost->host_lock);
        vport->fc_flag |= FC_DISC_TMO;
        spin_unlock_irq(shost->host_lock);
@@ -4949,8 +4987,12 @@ lpfc_disc_start(struct lpfc_vport *vport)
        uint32_t clear_la_pending;
        int did_changed;
 
-       if (!lpfc_is_link_up(phba))
+       if (!lpfc_is_link_up(phba)) {
+               lpfc_printf_vlog(vport, KERN_INFO, LOG_SLI,
+                                "3315 Link is not up %x\n",
+                                phba->link_state);
                return;
+       }
 
        if (phba->link_state == LPFC_CLEAR_LA)
                clear_la_pending = 1;
@@ -4983,11 +5025,13 @@ lpfc_disc_start(struct lpfc_vport *vport)
        if (num_sent)
                return;
 
-       /* Register the VPI for SLI3, NON-NPIV only. */
+       /* Register the VPI for SLI3, NPIV only. */
        if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) &&
            !(vport->fc_flag & FC_PT2PT) &&
            !(vport->fc_flag & FC_RSCN_MODE) &&
            (phba->sli_rev < LPFC_SLI_REV4)) {
+               if (vport->port_type == LPFC_PHYSICAL_PORT)
+                       lpfc_issue_clear_la(phba, vport);
                lpfc_issue_reg_vpi(phba, vport);
                return;
        }
@@ -5410,7 +5454,8 @@ lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
        if (vport->cfg_fdmi_on == 1)
                lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_DHBA);
        else
-               mod_timer(&vport->fc_fdmitmo, jiffies + HZ * 60);
+               mod_timer(&vport->fc_fdmitmo,
+                         jiffies + msecs_to_jiffies(1000 * 60));
 
        /* decrement the node reference count held for this callback
         * function.
@@ -5855,7 +5900,7 @@ lpfc_unregister_fcf_prep(struct lpfc_hba *phba)
        struct lpfc_vport **vports;
        struct lpfc_nodelist *ndlp;
        struct Scsi_Host *shost;
-       int i, rc;
+       int i = 0, rc;
 
        /* Unregister RPIs */
        if (lpfc_fcf_inuse(phba))
@@ -5883,6 +5928,20 @@ lpfc_unregister_fcf_prep(struct lpfc_hba *phba)
                        spin_unlock_irq(shost->host_lock);
                }
        lpfc_destroy_vport_work_array(phba, vports);
+       if (i == 0 && (!(phba->sli3_options & LPFC_SLI3_NPIV_ENABLED))) {
+               ndlp = lpfc_findnode_did(phba->pport, Fabric_DID);
+               if (ndlp)
+                       lpfc_cancel_retry_delay_tmo(phba->pport, ndlp);
+               lpfc_cleanup_pending_mbox(phba->pport);
+               if (phba->sli_rev == LPFC_SLI_REV4)
+                       lpfc_sli4_unreg_all_rpis(phba->pport);
+               lpfc_mbx_unreg_vpi(phba->pport);
+               shost = lpfc_shost_from_vport(phba->pport);
+               spin_lock_irq(shost->host_lock);
+               phba->pport->fc_flag |= FC_VPORT_NEEDS_INIT_VPI;
+               phba->pport->vpi_state &= ~LPFC_VPI_REGISTERED;
+               spin_unlock_irq(shost->host_lock);
+       }
 
        /* Cleanup any outstanding ELS commands */
        lpfc_els_flush_all_cmd(phba);
index e8c4760..83700c1 100644 (file)
@@ -1667,6 +1667,7 @@ enum lpfc_protgrp_type {
 #define        BG_OP_IN_CSUM_OUT_CSUM          0x5
 #define        BG_OP_IN_CRC_OUT_CSUM           0x6
 #define        BG_OP_IN_CSUM_OUT_CRC           0x7
+#define        BG_OP_RAW_MODE                  0x8
 
 struct lpfc_pde5 {
        uint32_t word0;
index 1dd2f6f..713a461 100644 (file)
@@ -200,6 +200,11 @@ struct lpfc_sli_intf {
 #define LPFC_MAX_IMAX          5000000
 #define LPFC_DEF_IMAX          50000
 
+#define LPFC_MIN_CPU_MAP       0
+#define LPFC_MAX_CPU_MAP       2
+#define LPFC_HBA_CPU_MAP       1
+#define LPFC_DRIVER_CPU_MAP    2  /* Default */
+
 /* PORT_CAPABILITIES constants. */
 #define LPFC_MAX_SUPPORTED_PAGES       8
 
@@ -621,7 +626,7 @@ struct lpfc_register {
 #define lpfc_sliport_status_rdy_SHIFT  23
 #define lpfc_sliport_status_rdy_MASK   0x1
 #define lpfc_sliport_status_rdy_WORD   word0
-#define MAX_IF_TYPE_2_RESETS   1000
+#define MAX_IF_TYPE_2_RESETS           6
 
 #define LPFC_CTL_PORT_CTL_OFFSET       0x408
 #define lpfc_sliport_ctrl_end_SHIFT    30
index 90b8b05..cb465b2 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/slab.h>
 #include <linux/firmware.h>
 #include <linux/miscdevice.h>
+#include <linux/percpu.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_device.h>
@@ -58,6 +59,9 @@ char *_dump_buf_dif;
 unsigned long _dump_buf_dif_order;
 spinlock_t _dump_buf_lock;
 
+/* Used when mapping IRQ vectors in a driver centric manner */
+uint16_t lpfc_used_cpu[LPFC_MAX_CPU];
+
 static void lpfc_get_hba_model_desc(struct lpfc_hba *, uint8_t *, uint8_t *);
 static int lpfc_post_rcv_buf(struct lpfc_hba *);
 static int lpfc_sli4_queue_verify(struct lpfc_hba *);
@@ -541,13 +545,16 @@ lpfc_config_port_post(struct lpfc_hba *phba)
 
        /* Set up ring-0 (ELS) timer */
        timeout = phba->fc_ratov * 2;
-       mod_timer(&vport->els_tmofunc, jiffies + HZ * timeout);
+       mod_timer(&vport->els_tmofunc,
+                 jiffies + msecs_to_jiffies(1000 * timeout));
        /* Set up heart beat (HB) timer */
-       mod_timer(&phba->hb_tmofunc, jiffies + HZ * LPFC_HB_MBOX_INTERVAL);
+       mod_timer(&phba->hb_tmofunc,
+                 jiffies + msecs_to_jiffies(1000 * LPFC_HB_MBOX_INTERVAL));
        phba->hb_outstanding = 0;
        phba->last_completion_time = jiffies;
        /* Set up error attention (ERATT) polling timer */
-       mod_timer(&phba->eratt_poll, jiffies + HZ * LPFC_ERATT_POLL_INTERVAL);
+       mod_timer(&phba->eratt_poll,
+                 jiffies + msecs_to_jiffies(1000 * LPFC_ERATT_POLL_INTERVAL));
 
        if (phba->hba_flag & LINK_DISABLED) {
                lpfc_printf_log(phba,
@@ -908,9 +915,9 @@ lpfc_hba_down_post_s4(struct lpfc_hba *phba)
                psb->pCmd = NULL;
                psb->status = IOSTAT_SUCCESS;
        }
-       spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag);
-       list_splice(&aborts, &phba->lpfc_scsi_buf_list);
-       spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag);
+       spin_lock_irqsave(&phba->scsi_buf_list_put_lock, iflag);
+       list_splice(&aborts, &phba->lpfc_scsi_buf_list_put);
+       spin_unlock_irqrestore(&phba->scsi_buf_list_put_lock, iflag);
        return 0;
 }
 
@@ -1021,7 +1028,8 @@ lpfc_hb_mbox_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq)
                !(phba->link_state == LPFC_HBA_ERROR) &&
                !(phba->pport->load_flag & FC_UNLOADING))
                mod_timer(&phba->hb_tmofunc,
-                       jiffies + HZ * LPFC_HB_MBOX_INTERVAL);
+                         jiffies +
+                         msecs_to_jiffies(1000 * LPFC_HB_MBOX_INTERVAL));
        return;
 }
 
@@ -1064,15 +1072,18 @@ lpfc_hb_timeout_handler(struct lpfc_hba *phba)
 
        spin_lock_irq(&phba->pport->work_port_lock);
 
-       if (time_after(phba->last_completion_time + LPFC_HB_MBOX_INTERVAL * HZ,
-               jiffies)) {
+       if (time_after(phba->last_completion_time +
+                       msecs_to_jiffies(1000 * LPFC_HB_MBOX_INTERVAL),
+                       jiffies)) {
                spin_unlock_irq(&phba->pport->work_port_lock);
                if (!phba->hb_outstanding)
                        mod_timer(&phba->hb_tmofunc,
-                               jiffies + HZ * LPFC_HB_MBOX_INTERVAL);
+                               jiffies +
+                               msecs_to_jiffies(1000 * LPFC_HB_MBOX_INTERVAL));
                else
                        mod_timer(&phba->hb_tmofunc,
-                               jiffies + HZ * LPFC_HB_MBOX_TIMEOUT);
+                               jiffies +
+                               msecs_to_jiffies(1000 * LPFC_HB_MBOX_TIMEOUT));
                return;
        }
        spin_unlock_irq(&phba->pport->work_port_lock);
@@ -1104,7 +1115,8 @@ lpfc_hb_timeout_handler(struct lpfc_hba *phba)
                                if (!pmboxq) {
                                        mod_timer(&phba->hb_tmofunc,
                                                 jiffies +
-                                                HZ * LPFC_HB_MBOX_INTERVAL);
+                                                msecs_to_jiffies(1000 *
+                                                LPFC_HB_MBOX_INTERVAL));
                                        return;
                                }
 
@@ -1120,7 +1132,8 @@ lpfc_hb_timeout_handler(struct lpfc_hba *phba)
                                                        phba->mbox_mem_pool);
                                        mod_timer(&phba->hb_tmofunc,
                                                jiffies +
-                                               HZ * LPFC_HB_MBOX_INTERVAL);
+                                               msecs_to_jiffies(1000 *
+                                               LPFC_HB_MBOX_INTERVAL));
                                        return;
                                }
                                phba->skipped_hb = 0;
@@ -1136,7 +1149,8 @@ lpfc_hb_timeout_handler(struct lpfc_hba *phba)
                                phba->skipped_hb = jiffies;
 
                        mod_timer(&phba->hb_tmofunc,
-                                 jiffies + HZ * LPFC_HB_MBOX_TIMEOUT);
+                                jiffies +
+                                msecs_to_jiffies(1000 * LPFC_HB_MBOX_TIMEOUT));
                        return;
                } else {
                        /*
@@ -1150,7 +1164,8 @@ lpfc_hb_timeout_handler(struct lpfc_hba *phba)
                                        jiffies_to_msecs(jiffies
                                                 - phba->last_completion_time));
                        mod_timer(&phba->hb_tmofunc,
-                                 jiffies + HZ * LPFC_HB_MBOX_TIMEOUT);
+                               jiffies +
+                               msecs_to_jiffies(1000 * LPFC_HB_MBOX_TIMEOUT));
                }
        }
 }
@@ -1191,7 +1206,7 @@ lpfc_offline_eratt(struct lpfc_hba *phba)
  * This routine is called to bring a SLI4 HBA offline when HBA hardware error
  * other than Port Error 6 has been detected.
  **/
-static void
+void
 lpfc_sli4_offline_eratt(struct lpfc_hba *phba)
 {
        lpfc_offline_prep(phba, LPFC_MBX_NO_WAIT);
@@ -2633,6 +2648,7 @@ lpfc_online(struct lpfc_hba *phba)
        struct lpfc_vport *vport;
        struct lpfc_vport **vports;
        int i;
+       bool vpis_cleared = false;
 
        if (!phba)
                return 0;
@@ -2656,6 +2672,10 @@ lpfc_online(struct lpfc_hba *phba)
                        lpfc_unblock_mgmt_io(phba);
                        return 1;
                }
+               spin_lock_irq(&phba->hbalock);
+               if (!phba->sli4_hba.max_cfg_param.vpi_used)
+                       vpis_cleared = true;
+               spin_unlock_irq(&phba->hbalock);
        } else {
                if (lpfc_sli_hba_setup(phba)) { /* Initialize SLI2/SLI3 HBA */
                        lpfc_unblock_mgmt_io(phba);
@@ -2672,8 +2692,13 @@ lpfc_online(struct lpfc_hba *phba)
                        vports[i]->fc_flag &= ~FC_OFFLINE_MODE;
                        if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED)
                                vports[i]->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
-                       if (phba->sli_rev == LPFC_SLI_REV4)
+                       if (phba->sli_rev == LPFC_SLI_REV4) {
                                vports[i]->fc_flag |= FC_VPORT_NEEDS_INIT_VPI;
+                               if ((vpis_cleared) &&
+                                   (vports[i]->port_type !=
+                                       LPFC_PHYSICAL_PORT))
+                                       vports[i]->vpi = 0;
+                       }
                        spin_unlock_irq(shost->host_lock);
                }
                lpfc_destroy_vport_work_array(phba, vports);
@@ -2833,16 +2858,30 @@ lpfc_scsi_free(struct lpfc_hba *phba)
        struct lpfc_iocbq *io, *io_next;
 
        spin_lock_irq(&phba->hbalock);
+
        /* Release all the lpfc_scsi_bufs maintained by this host. */
-       spin_lock(&phba->scsi_buf_list_lock);
-       list_for_each_entry_safe(sb, sb_next, &phba->lpfc_scsi_buf_list, list) {
+
+       spin_lock(&phba->scsi_buf_list_put_lock);
+       list_for_each_entry_safe(sb, sb_next, &phba->lpfc_scsi_buf_list_put,
+                                list) {
                list_del(&sb->list);
                pci_pool_free(phba->lpfc_scsi_dma_buf_pool, sb->data,
                              sb->dma_handle);
                kfree(sb);
                phba->total_scsi_bufs--;
        }
-       spin_unlock(&phba->scsi_buf_list_lock);
+       spin_unlock(&phba->scsi_buf_list_put_lock);
+
+       spin_lock(&phba->scsi_buf_list_get_lock);
+       list_for_each_entry_safe(sb, sb_next, &phba->lpfc_scsi_buf_list_get,
+                                list) {
+               list_del(&sb->list);
+               pci_pool_free(phba->lpfc_scsi_dma_buf_pool, sb->data,
+                             sb->dma_handle);
+               kfree(sb);
+               phba->total_scsi_bufs--;
+       }
+       spin_unlock(&phba->scsi_buf_list_get_lock);
 
        /* Release all the lpfc_iocbq entries maintained by this host. */
        list_for_each_entry_safe(io, io_next, &phba->lpfc_iocb_list, list) {
@@ -2978,9 +3017,12 @@ lpfc_sli4_xri_sgl_update(struct lpfc_hba *phba)
                        phba->sli4_hba.scsi_xri_cnt,
                        phba->sli4_hba.scsi_xri_max);
 
-       spin_lock_irq(&phba->scsi_buf_list_lock);
-       list_splice_init(&phba->lpfc_scsi_buf_list, &scsi_sgl_list);
-       spin_unlock_irq(&phba->scsi_buf_list_lock);
+       spin_lock_irq(&phba->scsi_buf_list_get_lock);
+       spin_lock_irq(&phba->scsi_buf_list_put_lock);
+       list_splice_init(&phba->lpfc_scsi_buf_list_get, &scsi_sgl_list);
+       list_splice(&phba->lpfc_scsi_buf_list_put, &scsi_sgl_list);
+       spin_unlock_irq(&phba->scsi_buf_list_put_lock);
+       spin_unlock_irq(&phba->scsi_buf_list_get_lock);
 
        if (phba->sli4_hba.scsi_xri_cnt > phba->sli4_hba.scsi_xri_max) {
                /* max scsi xri shrinked below the allocated scsi buffers */
@@ -2994,9 +3036,9 @@ lpfc_sli4_xri_sgl_update(struct lpfc_hba *phba)
                                      psb->dma_handle);
                        kfree(psb);
                }
-               spin_lock_irq(&phba->scsi_buf_list_lock);
+               spin_lock_irq(&phba->scsi_buf_list_get_lock);
                phba->sli4_hba.scsi_xri_cnt -= scsi_xri_cnt;
-               spin_unlock_irq(&phba->scsi_buf_list_lock);
+               spin_unlock_irq(&phba->scsi_buf_list_get_lock);
        }
 
        /* update xris associated to remaining allocated scsi buffers */
@@ -3014,9 +3056,12 @@ lpfc_sli4_xri_sgl_update(struct lpfc_hba *phba)
                psb->cur_iocbq.sli4_lxritag = lxri;
                psb->cur_iocbq.sli4_xritag = phba->sli4_hba.xri_ids[lxri];
        }
-       spin_lock_irq(&phba->scsi_buf_list_lock);
-       list_splice_init(&scsi_sgl_list, &phba->lpfc_scsi_buf_list);
-       spin_unlock_irq(&phba->scsi_buf_list_lock);
+       spin_lock_irq(&phba->scsi_buf_list_get_lock);
+       spin_lock_irq(&phba->scsi_buf_list_put_lock);
+       list_splice_init(&scsi_sgl_list, &phba->lpfc_scsi_buf_list_get);
+       INIT_LIST_HEAD(&phba->lpfc_scsi_buf_list_put);
+       spin_unlock_irq(&phba->scsi_buf_list_put_lock);
+       spin_unlock_irq(&phba->scsi_buf_list_get_lock);
 
        return 0;
 
@@ -3197,14 +3242,15 @@ int lpfc_scan_finished(struct Scsi_Host *shost, unsigned long time)
                stat = 1;
                goto finished;
        }
-       if (time >= 30 * HZ) {
+       if (time >= msecs_to_jiffies(30 * 1000)) {
                lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
                                "0461 Scanning longer than 30 "
                                "seconds.  Continuing initialization\n");
                stat = 1;
                goto finished;
        }
-       if (time >= 15 * HZ && phba->link_state <= LPFC_LINK_DOWN) {
+       if (time >= msecs_to_jiffies(15 * 1000) &&
+           phba->link_state <= LPFC_LINK_DOWN) {
                lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
                                "0465 Link down longer than 15 "
                                "seconds.  Continuing initialization\n");
@@ -3216,7 +3262,7 @@ int lpfc_scan_finished(struct Scsi_Host *shost, unsigned long time)
                goto finished;
        if (vport->num_disc_nodes || vport->fc_prli_sent)
                goto finished;
-       if (vport->fc_map_cnt == 0 && time < 2 * HZ)
+       if (vport->fc_map_cnt == 0 && time < msecs_to_jiffies(2 * 1000))
                goto finished;
        if ((phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE) != 0)
                goto finished;
@@ -4215,7 +4261,8 @@ lpfc_sli4_async_fip_evt(struct lpfc_hba *phba,
                         * If there are other active VLinks present,
                         * re-instantiate the Vlink using FDISC.
                         */
-                       mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ);
+                       mod_timer(&ndlp->nlp_delayfunc,
+                                 jiffies + msecs_to_jiffies(1000));
                        shost = lpfc_shost_from_vport(vport);
                        spin_lock_irq(shost->host_lock);
                        ndlp->nlp_flag |= NLP_DELAY_TMO;
@@ -4707,23 +4754,52 @@ lpfc_sli_driver_resource_setup(struct lpfc_hba *phba)
                return -ENOMEM;
 
        /*
-        * Since the sg_tablesize is module parameter, the sg_dma_buf_size
+        * Since lpfc_sg_seg_cnt is module parameter, the sg_dma_buf_size
         * used to create the sg_dma_buf_pool must be dynamically calculated.
-        * 2 segments are added since the IOCB needs a command and response bde.
         */
-       phba->cfg_sg_dma_buf_size = sizeof(struct fcp_cmnd) +
-               sizeof(struct fcp_rsp) +
-                       ((phba->cfg_sg_seg_cnt + 2) * sizeof(struct ulp_bde64));
 
+       /* Initialize the host templates the configured values. */
+       lpfc_vport_template.sg_tablesize = phba->cfg_sg_seg_cnt;
+       lpfc_template.sg_tablesize = phba->cfg_sg_seg_cnt;
+
+       /* There are going to be 2 reserved BDEs: 1 FCP cmnd + 1 FCP rsp */
        if (phba->cfg_enable_bg) {
-               phba->cfg_sg_seg_cnt = LPFC_MAX_SG_SEG_CNT;
-               phba->cfg_sg_dma_buf_size +=
-                       phba->cfg_prot_sg_seg_cnt * sizeof(struct ulp_bde64);
+               /*
+                * The scsi_buf for a T10-DIF I/O will hold the FCP cmnd,
+                * the FCP rsp, and a BDE for each. Sice we have no control
+                * over how many protection data segments the SCSI Layer
+                * will hand us (ie: there could be one for every block
+                * in the IO), we just allocate enough BDEs to accomidate
+                * our max amount and we need to limit lpfc_sg_seg_cnt to
+                * minimize the risk of running out.
+                */
+               phba->cfg_sg_dma_buf_size = sizeof(struct fcp_cmnd) +
+                       sizeof(struct fcp_rsp) +
+                       (LPFC_MAX_SG_SEG_CNT * sizeof(struct ulp_bde64));
+
+               if (phba->cfg_sg_seg_cnt > LPFC_MAX_SG_SEG_CNT_DIF)
+                       phba->cfg_sg_seg_cnt = LPFC_MAX_SG_SEG_CNT_DIF;
+
+               /* Total BDEs in BPL for scsi_sg_list and scsi_sg_prot_list */
+               phba->cfg_total_seg_cnt = LPFC_MAX_SG_SEG_CNT;
+       } else {
+               /*
+                * The scsi_buf for a regular I/O will hold the FCP cmnd,
+                * the FCP rsp, a BDE for each, and a BDE for up to
+                * cfg_sg_seg_cnt data segments.
+                */
+               phba->cfg_sg_dma_buf_size = sizeof(struct fcp_cmnd) +
+                       sizeof(struct fcp_rsp) +
+                       ((phba->cfg_sg_seg_cnt + 2) * sizeof(struct ulp_bde64));
+
+               /* Total BDEs in BPL for scsi_sg_list */
+               phba->cfg_total_seg_cnt = phba->cfg_sg_seg_cnt + 2;
        }
 
-       /* Also reinitialize the host templates with new values. */
-       lpfc_vport_template.sg_tablesize = phba->cfg_sg_seg_cnt;
-       lpfc_template.sg_tablesize = phba->cfg_sg_seg_cnt;
+       lpfc_printf_log(phba, KERN_INFO, LOG_INIT | LOG_FCP,
+                       "9088 sg_tablesize:%d dmabuf_size:%d total_bde:%d\n",
+                       phba->cfg_sg_seg_cnt, phba->cfg_sg_dma_buf_size,
+                       phba->cfg_total_seg_cnt);
 
        phba->max_vpi = LPFC_MAX_VPI;
        /* This will be set to correct value after config_port mbox */
@@ -4789,13 +4865,13 @@ lpfc_sli_driver_resource_unset(struct lpfc_hba *phba)
 static int
 lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
 {
+       struct lpfc_vector_map_info *cpup;
        struct lpfc_sli *psli;
        LPFC_MBOXQ_t *mboxq;
-       int rc, i, hbq_count, buf_size, dma_buf_size, max_buf_size;
+       int rc, i, hbq_count, max_buf_size;
        uint8_t pn_page[LPFC_MAX_SUPPORTED_PAGES] = {0};
        struct lpfc_mqe *mqe;
-       int longs, sli_family;
-       int sges_per_segment;
+       int longs;
 
        /* Before proceed, wait for POST done and device ready */
        rc = lpfc_sli4_post_status_check(phba);
@@ -4863,11 +4939,6 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
        phba->fc_map[1] = LPFC_FCOE_FCF_MAP1;
        phba->fc_map[2] = LPFC_FCOE_FCF_MAP2;
 
-       /* With BlockGuard we can have multiple SGEs per Data Segemnt */
-       sges_per_segment = 1;
-       if (phba->cfg_enable_bg)
-               sges_per_segment = 2;
-
        /*
         * For SLI4, instead of using ring 0 (LPFC_FCP_RING) for FCP commands
         * we will associate a new ring, for each FCP fastpath EQ/CQ/WQ tuple.
@@ -4878,43 +4949,71 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
                        sizeof(struct lpfc_sli_ring), GFP_KERNEL);
        if (!phba->sli.ring)
                return -ENOMEM;
+
        /*
-        * Since the sg_tablesize is module parameter, the sg_dma_buf_size
+        * It doesn't matter what family our adapter is in, we are
+        * limited to 2 Pages, 512 SGEs, for our SGL.
+        * There are going to be 2 reserved SGEs: 1 FCP cmnd + 1 FCP rsp
+        */
+       max_buf_size = (2 * SLI4_PAGE_SIZE);
+       if (phba->cfg_sg_seg_cnt > LPFC_MAX_SGL_SEG_CNT - 2)
+               phba->cfg_sg_seg_cnt = LPFC_MAX_SGL_SEG_CNT - 2;
+
+       /*
+        * Since lpfc_sg_seg_cnt is module parameter, the sg_dma_buf_size
         * used to create the sg_dma_buf_pool must be dynamically calculated.
-        * 2 segments are added since the IOCB needs a command and response bde.
-        * To insure that the scsi sgl does not cross a 4k page boundary only
-        * sgl sizes of must be a power of 2.
         */
-       buf_size = (sizeof(struct fcp_cmnd) + sizeof(struct fcp_rsp) +
-                   (((phba->cfg_sg_seg_cnt * sges_per_segment) + 2) *
-                   sizeof(struct sli4_sge)));
-
-       sli_family = bf_get(lpfc_sli_intf_sli_family, &phba->sli4_hba.sli_intf);
-       max_buf_size = LPFC_SLI4_MAX_BUF_SIZE;
-       switch (sli_family) {
-       case LPFC_SLI_INTF_FAMILY_BE2:
-       case LPFC_SLI_INTF_FAMILY_BE3:
-               /* There is a single hint for BE - 2 pages per BPL. */
-               if (bf_get(lpfc_sli_intf_sli_hint1, &phba->sli4_hba.sli_intf) ==
-                   LPFC_SLI_INTF_SLI_HINT1_1)
-                       max_buf_size = LPFC_SLI4_FL1_MAX_BUF_SIZE;
-               break;
-       case LPFC_SLI_INTF_FAMILY_LNCR_A0:
-       case LPFC_SLI_INTF_FAMILY_LNCR_B0:
-       default:
-               break;
+
+       if (phba->cfg_enable_bg) {
+               /*
+                * The scsi_buf for a T10-DIF I/O will hold the FCP cmnd,
+                * the FCP rsp, and a SGE for each. Sice we have no control
+                * over how many protection data segments the SCSI Layer
+                * will hand us (ie: there could be one for every block
+                * in the IO), we just allocate enough SGEs to accomidate
+                * our max amount and we need to limit lpfc_sg_seg_cnt to
+                * minimize the risk of running out.
+                */
+               phba->cfg_sg_dma_buf_size = sizeof(struct fcp_cmnd) +
+                       sizeof(struct fcp_rsp) + max_buf_size;
+
+               /* Total SGEs for scsi_sg_list and scsi_sg_prot_list */
+               phba->cfg_total_seg_cnt = LPFC_MAX_SGL_SEG_CNT;
+
+               if (phba->cfg_sg_seg_cnt > LPFC_MAX_SG_SLI4_SEG_CNT_DIF)
+                       phba->cfg_sg_seg_cnt = LPFC_MAX_SG_SLI4_SEG_CNT_DIF;
+       } else {
+               /*
+                * The scsi_buf for a regular I/O will hold the FCP cmnd,
+                * the FCP rsp, a SGE for each, and a SGE for up to
+                * cfg_sg_seg_cnt data segments.
+                */
+               phba->cfg_sg_dma_buf_size = sizeof(struct fcp_cmnd) +
+                       sizeof(struct fcp_rsp) +
+                       ((phba->cfg_sg_seg_cnt + 2) * sizeof(struct sli4_sge));
+
+               /* Total SGEs for scsi_sg_list */
+               phba->cfg_total_seg_cnt = phba->cfg_sg_seg_cnt + 2;
+               /*
+                * NOTE: if (phba->cfg_sg_seg_cnt + 2) <= 256 we only need
+                * to post 1 page for the SGL.
+                */
        }
 
-       for (dma_buf_size = LPFC_SLI4_MIN_BUF_SIZE;
-            dma_buf_size < max_buf_size && buf_size > dma_buf_size;
-            dma_buf_size = dma_buf_size << 1)
-               ;
-       if (dma_buf_size == max_buf_size)
-               phba->cfg_sg_seg_cnt = (dma_buf_size -
-                       sizeof(struct fcp_cmnd) - sizeof(struct fcp_rsp) -
-                       (2 * sizeof(struct sli4_sge))) /
-                               sizeof(struct sli4_sge);
-       phba->cfg_sg_dma_buf_size = dma_buf_size;
+       /* Initialize the host templates with the updated values. */
+       lpfc_vport_template.sg_tablesize = phba->cfg_sg_seg_cnt;
+       lpfc_template.sg_tablesize = phba->cfg_sg_seg_cnt;
+
+       if (phba->cfg_sg_dma_buf_size  <= LPFC_MIN_SG_SLI4_BUF_SZ)
+               phba->cfg_sg_dma_buf_size = LPFC_MIN_SG_SLI4_BUF_SZ;
+       else
+               phba->cfg_sg_dma_buf_size =
+                       SLI4_PAGE_ALIGN(phba->cfg_sg_dma_buf_size);
+
+       lpfc_printf_log(phba, KERN_INFO, LOG_INIT | LOG_FCP,
+                       "9087 sg_tablesize:%d dmabuf_size:%d total_sge:%d\n",
+                       phba->cfg_sg_seg_cnt, phba->cfg_sg_dma_buf_size,
+                       phba->cfg_total_seg_cnt);
 
        /* Initialize buffer queue management fields */
        hbq_count = lpfc_sli_hbq_count();
@@ -5104,6 +5203,26 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
                goto out_free_fcp_eq_hdl;
        }
 
+       phba->sli4_hba.cpu_map = kzalloc((sizeof(struct lpfc_vector_map_info) *
+                                        phba->sli4_hba.num_present_cpu),
+                                        GFP_KERNEL);
+       if (!phba->sli4_hba.cpu_map) {
+               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                               "3327 Failed allocate memory for msi-x "
+                               "interrupt vector mapping\n");
+               rc = -ENOMEM;
+               goto out_free_msix;
+       }
+       /* Initialize io channels for round robin */
+       cpup = phba->sli4_hba.cpu_map;
+       rc = 0;
+       for (i = 0; i < phba->sli4_hba.num_present_cpu; i++) {
+               cpup->channel_id = rc;
+               rc++;
+               if (rc >= phba->cfg_fcp_io_channel)
+                       rc = 0;
+       }
+
        /*
         * Enable sr-iov virtual functions if supported and configured
         * through the module parameter.
@@ -5123,6 +5242,8 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
 
        return 0;
 
+out_free_msix:
+       kfree(phba->sli4_hba.msix_entries);
 out_free_fcp_eq_hdl:
        kfree(phba->sli4_hba.fcp_eq_hdl);
 out_free_fcf_rr_bmask:
@@ -5152,6 +5273,11 @@ lpfc_sli4_driver_resource_unset(struct lpfc_hba *phba)
 {
        struct lpfc_fcf_conn_entry *conn_entry, *next_conn_entry;
 
+       /* Free memory allocated for msi-x interrupt vector to CPU mapping */
+       kfree(phba->sli4_hba.cpu_map);
+       phba->sli4_hba.num_present_cpu = 0;
+       phba->sli4_hba.num_online_cpu = 0;
+
        /* Free memory allocated for msi-x interrupt vector entries */
        kfree(phba->sli4_hba.msix_entries);
 
@@ -5260,8 +5386,10 @@ lpfc_setup_driver_resource_phase1(struct lpfc_hba *phba)
        init_waitqueue_head(&phba->work_waitq);
 
        /* Initialize the scsi buffer list used by driver for scsi IO */
-       spin_lock_init(&phba->scsi_buf_list_lock);
-       INIT_LIST_HEAD(&phba->lpfc_scsi_buf_list);
+       spin_lock_init(&phba->scsi_buf_list_get_lock);
+       INIT_LIST_HEAD(&phba->lpfc_scsi_buf_list_get);
+       spin_lock_init(&phba->scsi_buf_list_put_lock);
+       INIT_LIST_HEAD(&phba->lpfc_scsi_buf_list_put);
 
        /* Initialize the fabric iocb list */
        INIT_LIST_HEAD(&phba->fabric_iocb_list);
@@ -6696,6 +6824,7 @@ lpfc_sli4_queue_verify(struct lpfc_hba *phba)
        int cfg_fcp_io_channel;
        uint32_t cpu;
        uint32_t i = 0;
+       uint32_t j = 0;
 
 
        /*
@@ -6706,15 +6835,21 @@ lpfc_sli4_queue_verify(struct lpfc_hba *phba)
        /* Sanity check on HBA EQ parameters */
        cfg_fcp_io_channel = phba->cfg_fcp_io_channel;
 
-       /* It doesn't make sense to have more io channels then CPUs */
-       for_each_online_cpu(cpu) {
-               i++;
+       /* It doesn't make sense to have more io channels then online CPUs */
+       for_each_present_cpu(cpu) {
+               if (cpu_online(cpu))
+                       i++;
+               j++;
        }
+       phba->sli4_hba.num_online_cpu = i;
+       phba->sli4_hba.num_present_cpu = j;
+
        if (i < cfg_fcp_io_channel) {
                lpfc_printf_log(phba,
                                KERN_ERR, LOG_INIT,
                                "3188 Reducing IO channels to match number of "
-                               "CPUs: from %d to %d\n", cfg_fcp_io_channel, i);
+                               "online CPUs: from %d to %d\n",
+                               cfg_fcp_io_channel, i);
                cfg_fcp_io_channel = i;
        }
 
@@ -7743,8 +7878,13 @@ lpfc_pci_function_reset(struct lpfc_hba *phba)
 
 out:
        /* Catch the not-ready port failure after a port reset. */
-       if (num_resets >= MAX_IF_TYPE_2_RESETS)
+       if (num_resets >= MAX_IF_TYPE_2_RESETS) {
+               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                               "3317 HBA not functional: IP Reset Failed "
+                               "after (%d) retries, try: "
+                               "echo fw_reset > board_mode\n", num_resets);
                rc = -ENODEV;
+       }
 
        return rc;
 }
@@ -8208,6 +8348,269 @@ lpfc_sli_disable_intr(struct lpfc_hba *phba)
        return;
 }
 
+/**
+ * lpfc_find_next_cpu - Find next available CPU that matches the phys_id
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * Find next available CPU to use for IRQ to CPU affinity.
+ */
+static int
+lpfc_find_next_cpu(struct lpfc_hba *phba, uint32_t phys_id)
+{
+       struct lpfc_vector_map_info *cpup;
+       int cpu;
+
+       cpup = phba->sli4_hba.cpu_map;
+       for (cpu = 0; cpu < phba->sli4_hba.num_present_cpu; cpu++) {
+               /* CPU must be online */
+               if (cpu_online(cpu)) {
+                       if ((cpup->irq == LPFC_VECTOR_MAP_EMPTY) &&
+                           (lpfc_used_cpu[cpu] == LPFC_VECTOR_MAP_EMPTY) &&
+                           (cpup->phys_id == phys_id)) {
+                               return cpu;
+                       }
+               }
+               cpup++;
+       }
+
+       /*
+        * If we get here, we have used ALL CPUs for the specific
+        * phys_id. Now we need to clear out lpfc_used_cpu and start
+        * reusing CPUs.
+        */
+
+       for (cpu = 0; cpu < phba->sli4_hba.num_present_cpu; cpu++) {
+               if (lpfc_used_cpu[cpu] == phys_id)
+                       lpfc_used_cpu[cpu] = LPFC_VECTOR_MAP_EMPTY;
+       }
+
+       cpup = phba->sli4_hba.cpu_map;
+       for (cpu = 0; cpu < phba->sli4_hba.num_present_cpu; cpu++) {
+               /* CPU must be online */
+               if (cpu_online(cpu)) {
+                       if ((cpup->irq == LPFC_VECTOR_MAP_EMPTY) &&
+                           (cpup->phys_id == phys_id)) {
+                               return cpu;
+                       }
+               }
+               cpup++;
+       }
+       return LPFC_VECTOR_MAP_EMPTY;
+}
+
+/**
+ * lpfc_sli4_set_affinity - Set affinity for HBA IRQ vectors
+ * @phba:      pointer to lpfc hba data structure.
+ * @vectors:   number of HBA vectors
+ *
+ * Affinitize MSIX IRQ vectors to CPUs. Try to equally spread vector
+ * affinization across multple physical CPUs (numa nodes).
+ * In addition, this routine will assign an IO channel for each CPU
+ * to use when issuing I/Os.
+ */
+static int
+lpfc_sli4_set_affinity(struct lpfc_hba *phba, int vectors)
+{
+       int i, idx, saved_chann, used_chann, cpu, phys_id;
+       int max_phys_id, num_io_channel, first_cpu;
+       struct lpfc_vector_map_info *cpup;
+#ifdef CONFIG_X86
+       struct cpuinfo_x86 *cpuinfo;
+#endif
+       struct cpumask *mask;
+       uint8_t chann[LPFC_FCP_IO_CHAN_MAX+1];
+
+       /* If there is no mapping, just return */
+       if (!phba->cfg_fcp_cpu_map)
+               return 1;
+
+       /* Init cpu_map array */
+       memset(phba->sli4_hba.cpu_map, 0xff,
+              (sizeof(struct lpfc_vector_map_info) *
+               phba->sli4_hba.num_present_cpu));
+
+       max_phys_id = 0;
+       phys_id = 0;
+       num_io_channel = 0;
+       first_cpu = LPFC_VECTOR_MAP_EMPTY;
+
+       /* Update CPU map with physical id and core id of each CPU */
+       cpup = phba->sli4_hba.cpu_map;
+       for (cpu = 0; cpu < phba->sli4_hba.num_present_cpu; cpu++) {
+#ifdef CONFIG_X86
+               cpuinfo = &cpu_data(cpu);
+               cpup->phys_id = cpuinfo->phys_proc_id;
+               cpup->core_id = cpuinfo->cpu_core_id;
+#else
+               /* No distinction between CPUs for other platforms */
+               cpup->phys_id = 0;
+               cpup->core_id = 0;
+#endif
+
+               lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+                               "3328 CPU physid %d coreid %d\n",
+                               cpup->phys_id, cpup->core_id);
+
+               if (cpup->phys_id > max_phys_id)
+                       max_phys_id = cpup->phys_id;
+               cpup++;
+       }
+
+       /* Now associate the HBA vectors with specific CPUs */
+       for (idx = 0; idx < vectors; idx++) {
+               cpup = phba->sli4_hba.cpu_map;
+               cpu = lpfc_find_next_cpu(phba, phys_id);
+               if (cpu == LPFC_VECTOR_MAP_EMPTY) {
+
+                       /* Try for all phys_id's */
+                       for (i = 1; i < max_phys_id; i++) {
+                               phys_id++;
+                               if (phys_id > max_phys_id)
+                                       phys_id = 0;
+                               cpu = lpfc_find_next_cpu(phba, phys_id);
+                               if (cpu == LPFC_VECTOR_MAP_EMPTY)
+                                       continue;
+                               goto found;
+                       }
+
+                       lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                                       "3329 Cannot set affinity:"
+                                       "Error mapping vector %d (%d)\n",
+                                       idx, vectors);
+                       return 0;
+               }
+found:
+               cpup += cpu;
+               if (phba->cfg_fcp_cpu_map == LPFC_DRIVER_CPU_MAP)
+                       lpfc_used_cpu[cpu] = phys_id;
+
+               /* Associate vector with selected CPU */
+               cpup->irq = phba->sli4_hba.msix_entries[idx].vector;
+
+               /* Associate IO channel with selected CPU */
+               cpup->channel_id = idx;
+               num_io_channel++;
+
+               if (first_cpu == LPFC_VECTOR_MAP_EMPTY)
+                       first_cpu = cpu;
+
+               /* Now affinitize to the selected CPU */
+               mask = &cpup->maskbits;
+               cpumask_clear(mask);
+               cpumask_set_cpu(cpu, mask);
+               i = irq_set_affinity_hint(phba->sli4_hba.msix_entries[idx].
+                                         vector, mask);
+
+               lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+                               "3330 Set Affinity: CPU %d channel %d "
+                               "irq %d (%x)\n",
+                               cpu, cpup->channel_id,
+                               phba->sli4_hba.msix_entries[idx].vector, i);
+
+               /* Spread vector mapping across multple physical CPU nodes */
+               phys_id++;
+               if (phys_id > max_phys_id)
+                       phys_id = 0;
+       }
+
+       /*
+        * Finally fill in the IO channel for any remaining CPUs.
+        * At this point, all IO channels have been assigned to a specific
+        * MSIx vector, mapped to a specific CPU.
+        * Base the remaining IO channel assigned, to IO channels already
+        * assigned to other CPUs on the same phys_id.
+        */
+       for (i = 0; i <= max_phys_id; i++) {
+               /*
+                * If there are no io channels already mapped to
+                * this phys_id, just round robin thru the io_channels.
+                * Setup chann[] for round robin.
+                */
+               for (idx = 0; idx < phba->cfg_fcp_io_channel; idx++)
+                       chann[idx] = idx;
+
+               saved_chann = 0;
+               used_chann = 0;
+
+               /*
+                * First build a list of IO channels already assigned
+                * to this phys_id before reassigning the same IO
+                * channels to the remaining CPUs.
+                */
+               cpup = phba->sli4_hba.cpu_map;
+               cpu = first_cpu;
+               cpup += cpu;
+               for (idx = 0; idx < phba->sli4_hba.num_present_cpu;
+                    idx++) {
+                       if (cpup->phys_id == i) {
+                               /*
+                                * Save any IO channels that are
+                                * already mapped to this phys_id.
+                                */
+                               if (cpup->irq != LPFC_VECTOR_MAP_EMPTY) {
+                                       chann[saved_chann] =
+                                               cpup->channel_id;
+                                       saved_chann++;
+                                       goto out;
+                               }
+
+                               /* See if we are using round-robin */
+                               if (saved_chann == 0)
+                                       saved_chann =
+                                               phba->cfg_fcp_io_channel;
+
+                               /* Associate next IO channel with CPU */
+                               cpup->channel_id = chann[used_chann];
+                               num_io_channel++;
+                               used_chann++;
+                               if (used_chann == saved_chann)
+                                       used_chann = 0;
+
+                               lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+                                               "3331 Set IO_CHANN "
+                                               "CPU %d channel %d\n",
+                                               idx, cpup->channel_id);
+                       }
+out:
+                       cpu++;
+                       if (cpu >= phba->sli4_hba.num_present_cpu) {
+                               cpup = phba->sli4_hba.cpu_map;
+                               cpu = 0;
+                       } else {
+                               cpup++;
+                       }
+               }
+       }
+
+       if (phba->sli4_hba.num_online_cpu != phba->sli4_hba.num_present_cpu) {
+               cpup = phba->sli4_hba.cpu_map;
+               for (idx = 0; idx < phba->sli4_hba.num_present_cpu; idx++) {
+                       if (cpup->channel_id == LPFC_VECTOR_MAP_EMPTY) {
+                               cpup->channel_id = 0;
+                               num_io_channel++;
+
+                               lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+                                               "3332 Assign IO_CHANN "
+                                               "CPU %d channel %d\n",
+                                               idx, cpup->channel_id);
+                       }
+                       cpup++;
+               }
+       }
+
+       /* Sanity check */
+       if (num_io_channel != phba->sli4_hba.num_present_cpu)
+               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                               "3333 Set affinity mismatch:"
+                               "%d chann != %d cpus: %d vactors\n",
+                               num_io_channel, phba->sli4_hba.num_present_cpu,
+                               vectors);
+
+       phba->cfg_fcp_io_sched = LPFC_FCP_SCHED_BY_CPU;
+       return 1;
+}
+
+
 /**
  * lpfc_sli4_enable_msix - Enable MSI-X interrupt mode to SLI-4 device
  * @phba: pointer to lpfc hba data structure.
@@ -8259,9 +8662,7 @@ enable_msix_vectors:
                                phba->sli4_hba.msix_entries[index].vector,
                                phba->sli4_hba.msix_entries[index].entry);
 
-       /*
-        * Assign MSI-X vectors to interrupt handlers
-        */
+       /* Assign MSI-X vectors to interrupt handlers */
        for (index = 0; index < vectors; index++) {
                memset(&phba->sli4_hba.handler_name[index], 0, 16);
                sprintf((char *)&phba->sli4_hba.handler_name[index],
@@ -8289,6 +8690,8 @@ enable_msix_vectors:
                                phba->cfg_fcp_io_channel, vectors);
                phba->cfg_fcp_io_channel = vectors;
        }
+
+       lpfc_sli4_set_affinity(phba, vectors);
        return rc;
 
 cfg_fail_out:
@@ -9213,15 +9616,15 @@ lpfc_sli_prep_dev_for_reset(struct lpfc_hba *phba)
        /* Block all SCSI devices' I/Os on the host */
        lpfc_scsi_dev_block(phba);
 
+       /* Flush all driver's outstanding SCSI I/Os as we are to reset */
+       lpfc_sli_flush_fcp_rings(phba);
+
        /* stop all timers */
        lpfc_stop_hba_timers(phba);
 
        /* Disable interrupt and pci device */
        lpfc_sli_disable_intr(phba);
        pci_disable_device(phba->pcidev);
-
-       /* Flush all driver's outstanding SCSI I/Os as we are to reset */
-       lpfc_sli_flush_fcp_rings(phba);
 }
 
 /**
@@ -9966,6 +10369,9 @@ lpfc_sli4_prep_dev_for_reset(struct lpfc_hba *phba)
        /* Block all SCSI devices' I/Os on the host */
        lpfc_scsi_dev_block(phba);
 
+       /* Flush all driver's outstanding SCSI I/Os as we are to reset */
+       lpfc_sli_flush_fcp_rings(phba);
+
        /* stop all timers */
        lpfc_stop_hba_timers(phba);
 
@@ -9973,9 +10379,6 @@ lpfc_sli4_prep_dev_for_reset(struct lpfc_hba *phba)
        lpfc_sli4_disable_intr(phba);
        lpfc_sli4_queue_destroy(phba);
        pci_disable_device(phba->pcidev);
-
-       /* Flush all driver's outstanding SCSI I/Os as we are to reset */
-       lpfc_sli_flush_fcp_rings(phba);
 }
 
 /**
@@ -10535,6 +10938,7 @@ static struct miscdevice lpfc_mgmt_dev = {
 static int __init
 lpfc_init(void)
 {
+       int cpu;
        int error = 0;
 
        printk(LPFC_MODULE_DESC "\n");
@@ -10561,6 +10965,11 @@ lpfc_init(void)
                        return -ENOMEM;
                }
        }
+
+       /* Initialize in case vector mapping is needed */
+       for (cpu = 0; cpu < LPFC_MAX_CPU; cpu++)
+               lpfc_used_cpu[cpu] = LPFC_VECTOR_MAP_EMPTY;
+
        error = pci_register_driver(&lpfc_driver);
        if (error) {
                fc_release_transport(lpfc_transport_template);
index baf53e6..2a4e5d2 100644 (file)
@@ -37,6 +37,7 @@
 #define LOG_EVENT      0x00010000      /* CT,TEMP,DUMP, logging */
 #define LOG_FIP                0x00020000      /* FIP events */
 #define LOG_FCP_UNDER  0x00040000      /* FCP underruns errors */
+#define LOG_SCSI_CMD   0x00080000      /* ALL SCSI commands */
 #define LOG_ALL_MSG    0xffffffff      /* LOG all messages */
 
 #define lpfc_printf_vlog(vport, level, mask, fmt, arg...) \
index a7a9fa4..41363db 100644 (file)
@@ -2149,18 +2149,21 @@ lpfc_reg_vfi(struct lpfcMboxq *mbox, struct lpfc_vport *vport, dma_addr_t phys)
 
        /* Only FC supports upd bit */
        if ((phba->sli4_hba.lnk_info.lnk_tp == LPFC_LNK_TYPE_FC) &&
-           (vport->fc_flag & FC_VFI_REGISTERED)) {
+           (vport->fc_flag & FC_VFI_REGISTERED) &&
+           (!phba->fc_topology_changed)) {
                bf_set(lpfc_reg_vfi_vp, reg_vfi, 0);
                bf_set(lpfc_reg_vfi_upd, reg_vfi, 1);
        }
        lpfc_printf_vlog(vport, KERN_INFO, LOG_MBOX,
                        "3134 Register VFI, mydid:x%x, fcfi:%d, "
-                       " vfi:%d, vpi:%d, fc_pname:%x%x\n",
+                       " vfi:%d, vpi:%d, fc_pname:%x%x fc_flag:x%x"
+                       " port_state:x%x topology chg:%d\n",
                        vport->fc_myDID,
                        phba->fcf.fcfi,
                        phba->sli4_hba.vfi_ids[vport->vfi],
                        phba->vpi_ids[vport->vpi],
-                       reg_vfi->wwn[0], reg_vfi->wwn[1]);
+                       reg_vfi->wwn[0], reg_vfi->wwn[1], vport->fc_flag,
+                       vport->port_state, phba->fc_topology_changed);
 }
 
 /**
index cd86069..812d0cd 100644 (file)
@@ -64,18 +64,26 @@ lpfc_mem_alloc(struct lpfc_hba *phba, int align)
        struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool;
        int i;
 
-       if (phba->sli_rev == LPFC_SLI_REV4)
+       if (phba->sli_rev == LPFC_SLI_REV4) {
+               /* Calculate alignment */
+               if (phba->cfg_sg_dma_buf_size < SLI4_PAGE_SIZE)
+                       i = phba->cfg_sg_dma_buf_size;
+               else
+                       i = SLI4_PAGE_SIZE;
+
                phba->lpfc_scsi_dma_buf_pool =
                        pci_pool_create("lpfc_scsi_dma_buf_pool",
                                phba->pcidev,
                                phba->cfg_sg_dma_buf_size,
-                               phba->cfg_sg_dma_buf_size,
+                               i,
                                0);
-       else
+       } else {
                phba->lpfc_scsi_dma_buf_pool =
                        pci_pool_create("lpfc_scsi_dma_buf_pool",
                                phba->pcidev, phba->cfg_sg_dma_buf_size,
                                align, 0);
+       }
+
        if (!phba->lpfc_scsi_dma_buf_pool)
                goto fail;
 
index 82f4d35..31e9b92 100644 (file)
@@ -332,9 +332,11 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
 
        /* PLOGI chkparm OK */
        lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
-                        "0114 PLOGI chkparm OK Data: x%x x%x x%x x%x\n",
+                        "0114 PLOGI chkparm OK Data: x%x x%x x%x "
+                        "x%x x%x x%x\n",
                         ndlp->nlp_DID, ndlp->nlp_state, ndlp->nlp_flag,
-                        ndlp->nlp_rpi);
+                        ndlp->nlp_rpi, vport->port_state,
+                        vport->fc_flag);
 
        if (vport->cfg_fcp_class == 2 && sp->cls2.classValid)
                ndlp->nlp_fcp_info |= CLASS2;
@@ -574,7 +576,7 @@ out:
        lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
 
        /* 1 sec timeout */
-       mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ);
+       mod_timer(&ndlp->nlp_delayfunc, jiffies + msecs_to_jiffies(1000));
 
        spin_lock_irq(shost->host_lock);
        ndlp->nlp_flag |= NLP_DELAY_TMO;
@@ -631,7 +633,8 @@ lpfc_rcv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
                         * If there are other active VLinks present,
                         * re-instantiate the Vlink using FDISC.
                         */
-                       mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ);
+                       mod_timer(&ndlp->nlp_delayfunc,
+                                 jiffies + msecs_to_jiffies(1000));
                        spin_lock_irq(shost->host_lock);
                        ndlp->nlp_flag |= NLP_DELAY_TMO;
                        spin_unlock_irq(shost->host_lock);
@@ -648,7 +651,8 @@ lpfc_rcv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
                !(ndlp->nlp_type & NLP_FCP_INITIATOR))) ||
                (ndlp->nlp_state == NLP_STE_ADISC_ISSUE)) {
                /* Only try to re-login if this is NOT a Fabric Node */
-               mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1);
+               mod_timer(&ndlp->nlp_delayfunc,
+                         jiffies + msecs_to_jiffies(1000 * 1));
                spin_lock_irq(shost->host_lock);
                ndlp->nlp_flag |= NLP_DELAY_TMO;
                spin_unlock_irq(shost->host_lock);
@@ -969,7 +973,7 @@ lpfc_rcv_els_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
        }
 
        /* Put ndlp in npr state set plogi timer for 1 sec */
-       mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1);
+       mod_timer(&ndlp->nlp_delayfunc, jiffies + msecs_to_jiffies(1000 * 1));
        spin_lock_irq(shost->host_lock);
        ndlp->nlp_flag |= NLP_DELAY_TMO;
        spin_unlock_irq(shost->host_lock);
@@ -1303,7 +1307,8 @@ lpfc_cmpl_adisc_adisc_issue(struct lpfc_vport *vport,
        if ((irsp->ulpStatus) ||
            (!lpfc_check_adisc(vport, ndlp, &ap->nodeName, &ap->portName))) {
                /* 1 sec timeout */
-               mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ);
+               mod_timer(&ndlp->nlp_delayfunc,
+                         jiffies + msecs_to_jiffies(1000));
                spin_lock_irq(shost->host_lock);
                ndlp->nlp_flag |= NLP_DELAY_TMO;
                spin_unlock_irq(shost->host_lock);
@@ -1509,7 +1514,8 @@ lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_vport *vport,
                }
 
                /* Put ndlp in npr state set plogi timer for 1 sec */
-               mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1);
+               mod_timer(&ndlp->nlp_delayfunc,
+                         jiffies + msecs_to_jiffies(1000 * 1));
                spin_lock_irq(shost->host_lock);
                ndlp->nlp_flag |= NLP_DELAY_TMO;
                spin_unlock_irq(shost->host_lock);
@@ -2145,7 +2151,8 @@ lpfc_rcv_prlo_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
        lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
 
        if ((ndlp->nlp_flag & NLP_DELAY_TMO) == 0) {
-               mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1);
+               mod_timer(&ndlp->nlp_delayfunc,
+                         jiffies + msecs_to_jiffies(1000 * 1));
                spin_lock_irq(shost->host_lock);
                ndlp->nlp_flag |= NLP_DELAY_TMO;
                ndlp->nlp_flag &= ~NLP_NPR_ADISC;
index 74b8710..8523b27 100644 (file)
@@ -24,6 +24,8 @@
 #include <linux/export.h>
 #include <linux/delay.h>
 #include <asm/unaligned.h>
+#include <linux/crc-t10dif.h>
+#include <net/checksum.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_device.h>
@@ -48,7 +50,7 @@
 #define LPFC_RESET_WAIT  2
 #define LPFC_ABORT_WAIT  2
 
-int _dump_buf_done;
+int _dump_buf_done = 1;
 
 static char *dif_op_str[] = {
        "PROT_NORMAL",
@@ -66,6 +68,10 @@ struct scsi_dif_tuple {
        __be32 ref_tag;         /* Target LBA or indirect LBA */
 };
 
+#if !defined(SCSI_PROT_GUARD_CHECK) || !defined(SCSI_PROT_REF_CHECK)
+#define scsi_prot_flagged(sc, flg)     sc
+#endif
+
 static void
 lpfc_release_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb);
 static void
@@ -534,7 +540,16 @@ lpfc_new_scsi_buf_s3(struct lpfc_vport *vport, int num_to_alloc)
        dma_addr_t pdma_phys_fcp_rsp;
        dma_addr_t pdma_phys_bpl;
        uint16_t iotag;
-       int bcnt;
+       int bcnt, bpl_size;
+
+       bpl_size = phba->cfg_sg_dma_buf_size -
+               (sizeof(struct fcp_cmnd) + sizeof(struct fcp_rsp));
+
+       lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP,
+                        "9067 ALLOC %d scsi_bufs: %d (%d + %d + %d)\n",
+                        num_to_alloc, phba->cfg_sg_dma_buf_size,
+                        (int)sizeof(struct fcp_cmnd),
+                        (int)sizeof(struct fcp_rsp), bpl_size);
 
        for (bcnt = 0; bcnt < num_to_alloc; bcnt++) {
                psb = kzalloc(sizeof(struct lpfc_scsi_buf), GFP_KERNEL);
@@ -759,7 +774,7 @@ lpfc_sli4_post_scsi_sgl_list(struct lpfc_hba *phba,
                             struct list_head *post_sblist, int sb_count)
 {
        struct lpfc_scsi_buf *psb, *psb_next;
-       int status;
+       int status, sgl_size;
        int post_cnt = 0, block_cnt = 0, num_posting = 0, num_posted = 0;
        dma_addr_t pdma_phys_bpl1;
        int last_xritag = NO_XRI;
@@ -771,6 +786,9 @@ lpfc_sli4_post_scsi_sgl_list(struct lpfc_hba *phba,
        if (sb_count <= 0)
                return -EINVAL;
 
+       sgl_size = phba->cfg_sg_dma_buf_size -
+               (sizeof(struct fcp_cmnd) + sizeof(struct fcp_rsp));
+
        list_for_each_entry_safe(psb, psb_next, post_sblist, list) {
                list_del_init(&psb->list);
                block_cnt++;
@@ -803,7 +821,7 @@ lpfc_sli4_post_scsi_sgl_list(struct lpfc_hba *phba,
                                post_cnt = block_cnt;
                        } else if (block_cnt == 1) {
                                /* last single sgl with non-contiguous xri */
-                               if (phba->cfg_sg_dma_buf_size > SGL_PAGE_SIZE)
+                               if (sgl_size > SGL_PAGE_SIZE)
                                        pdma_phys_bpl1 = psb->dma_phys_bpl +
                                                                SGL_PAGE_SIZE;
                                else
@@ -885,9 +903,12 @@ lpfc_sli4_repost_scsi_sgl_list(struct lpfc_hba *phba)
        int num_posted, rc = 0;
 
        /* get all SCSI buffers need to repost to a local list */
-       spin_lock_irq(&phba->scsi_buf_list_lock);
-       list_splice_init(&phba->lpfc_scsi_buf_list, &post_sblist);
-       spin_unlock_irq(&phba->scsi_buf_list_lock);
+       spin_lock_irq(&phba->scsi_buf_list_get_lock);
+       spin_lock_irq(&phba->scsi_buf_list_put_lock);
+       list_splice_init(&phba->lpfc_scsi_buf_list_get, &post_sblist);
+       list_splice(&phba->lpfc_scsi_buf_list_put, &post_sblist);
+       spin_unlock_irq(&phba->scsi_buf_list_put_lock);
+       spin_unlock_irq(&phba->scsi_buf_list_get_lock);
 
        /* post the list of scsi buffer sgls to port if available */
        if (!list_empty(&post_sblist)) {
@@ -923,13 +944,22 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc)
        IOCB_t *iocb;
        dma_addr_t pdma_phys_fcp_cmd;
        dma_addr_t pdma_phys_fcp_rsp;
-       dma_addr_t pdma_phys_bpl, pdma_phys_bpl1;
+       dma_addr_t pdma_phys_bpl;
        uint16_t iotag, lxri = 0;
-       int bcnt, num_posted;
+       int bcnt, num_posted, sgl_size;
        LIST_HEAD(prep_sblist);
        LIST_HEAD(post_sblist);
        LIST_HEAD(scsi_sblist);
 
+       sgl_size = phba->cfg_sg_dma_buf_size -
+               (sizeof(struct fcp_cmnd) + sizeof(struct fcp_rsp));
+
+       lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP,
+                        "9068 ALLOC %d scsi_bufs: %d (%d + %d + %d)\n",
+                        num_to_alloc, phba->cfg_sg_dma_buf_size, sgl_size,
+                        (int)sizeof(struct fcp_cmnd),
+                        (int)sizeof(struct fcp_rsp));
+
        for (bcnt = 0; bcnt < num_to_alloc; bcnt++) {
                psb = kzalloc(sizeof(struct lpfc_scsi_buf), GFP_KERNEL);
                if (!psb)
@@ -948,6 +978,15 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc)
                }
                memset(psb->data, 0, phba->cfg_sg_dma_buf_size);
 
+               /* Page alignment is CRITICAL, double check to be sure */
+               if (((unsigned long)(psb->data) &
+                   (unsigned long)(SLI4_PAGE_SIZE - 1)) != 0) {
+                       pci_pool_free(phba->lpfc_scsi_dma_buf_pool,
+                                     psb->data, psb->dma_handle);
+                       kfree(psb);
+                       break;
+               }
+
                /* Allocate iotag for psb->cur_iocbq. */
                iotag = lpfc_sli_next_iotag(phba, &psb->cur_iocbq);
                if (iotag == 0) {
@@ -968,17 +1007,14 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc)
                psb->cur_iocbq.sli4_xritag = phba->sli4_hba.xri_ids[lxri];
                psb->cur_iocbq.iocb_flag |= LPFC_IO_FCP;
                psb->fcp_bpl = psb->data;
-               psb->fcp_cmnd = (psb->data + phba->cfg_sg_dma_buf_size)
-                       - (sizeof(struct fcp_cmnd) + sizeof(struct fcp_rsp));
+               psb->fcp_cmnd = (psb->data + sgl_size);
                psb->fcp_rsp = (struct fcp_rsp *)((uint8_t *)psb->fcp_cmnd +
                                        sizeof(struct fcp_cmnd));
 
                /* Initialize local short-hand pointers. */
                sgl = (struct sli4_sge *)psb->fcp_bpl;
                pdma_phys_bpl = psb->dma_handle;
-               pdma_phys_fcp_cmd =
-                       (psb->dma_handle + phba->cfg_sg_dma_buf_size)
-                        - (sizeof(struct fcp_cmnd) + sizeof(struct fcp_rsp));
+               pdma_phys_fcp_cmd = (psb->dma_handle + sgl_size);
                pdma_phys_fcp_rsp = pdma_phys_fcp_cmd + sizeof(struct fcp_cmnd);
 
                /*
@@ -1020,17 +1056,13 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc)
                iocb->ulpLe = 1;
                iocb->ulpClass = CLASS3;
                psb->cur_iocbq.context1 = psb;
-               if (phba->cfg_sg_dma_buf_size > SGL_PAGE_SIZE)
-                       pdma_phys_bpl1 = pdma_phys_bpl + SGL_PAGE_SIZE;
-               else
-                       pdma_phys_bpl1 = 0;
                psb->dma_phys_bpl = pdma_phys_bpl;
 
                /* add the scsi buffer to a post list */
                list_add_tail(&psb->list, &post_sblist);
-               spin_lock_irq(&phba->scsi_buf_list_lock);
+               spin_lock_irq(&phba->scsi_buf_list_get_lock);
                phba->sli4_hba.scsi_xri_cnt++;
-               spin_unlock_irq(&phba->scsi_buf_list_lock);
+               spin_unlock_irq(&phba->scsi_buf_list_get_lock);
        }
        lpfc_printf_log(phba, KERN_INFO, LOG_BG,
                        "3021 Allocate %d out of %d requested new SCSI "
@@ -1079,17 +1111,23 @@ static struct lpfc_scsi_buf*
 lpfc_get_scsi_buf_s3(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
 {
        struct  lpfc_scsi_buf * lpfc_cmd = NULL;
-       struct list_head *scsi_buf_list = &phba->lpfc_scsi_buf_list;
-       unsigned long iflag = 0;
-
-       spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag);
-       list_remove_head(scsi_buf_list, lpfc_cmd, struct lpfc_scsi_buf, list);
-       if (lpfc_cmd) {
-               lpfc_cmd->seg_cnt = 0;
-               lpfc_cmd->nonsg_phys = 0;
-               lpfc_cmd->prot_seg_cnt = 0;
+       struct list_head *scsi_buf_list_get = &phba->lpfc_scsi_buf_list_get;
+       unsigned long gflag = 0;
+       unsigned long pflag = 0;
+
+       spin_lock_irqsave(&phba->scsi_buf_list_get_lock, gflag);
+       list_remove_head(scsi_buf_list_get, lpfc_cmd, struct lpfc_scsi_buf,
+                        list);
+       if (!lpfc_cmd) {
+               spin_lock_irqsave(&phba->scsi_buf_list_put_lock, pflag);
+               list_splice(&phba->lpfc_scsi_buf_list_put,
+                           &phba->lpfc_scsi_buf_list_get);
+               INIT_LIST_HEAD(&phba->lpfc_scsi_buf_list_put);
+               list_remove_head(scsi_buf_list_get, lpfc_cmd,
+                                struct lpfc_scsi_buf, list);
+               spin_unlock_irqrestore(&phba->scsi_buf_list_put_lock, pflag);
        }
-       spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag);
+       spin_unlock_irqrestore(&phba->scsi_buf_list_get_lock, gflag);
        return  lpfc_cmd;
 }
 /**
@@ -1107,28 +1145,39 @@ static struct lpfc_scsi_buf*
 lpfc_get_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
 {
        struct lpfc_scsi_buf *lpfc_cmd ;
-       unsigned long iflag = 0;
+       unsigned long gflag = 0;
+       unsigned long pflag = 0;
        int found = 0;
 
-       spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag);
-       list_for_each_entry(lpfc_cmd, &phba->lpfc_scsi_buf_list,
-                                                       list) {
+       spin_lock_irqsave(&phba->scsi_buf_list_get_lock, gflag);
+       list_for_each_entry(lpfc_cmd, &phba->lpfc_scsi_buf_list_get, list) {
                if (lpfc_test_rrq_active(phba, ndlp,
                                         lpfc_cmd->cur_iocbq.sli4_lxritag))
                        continue;
                list_del(&lpfc_cmd->list);
                found = 1;
-               lpfc_cmd->seg_cnt = 0;
-               lpfc_cmd->nonsg_phys = 0;
-               lpfc_cmd->prot_seg_cnt = 0;
                break;
        }
-       spin_unlock_irqrestore(&phba->scsi_buf_list_lock,
-                                                iflag);
+       if (!found) {
+               spin_lock_irqsave(&phba->scsi_buf_list_put_lock, pflag);
+               list_splice(&phba->lpfc_scsi_buf_list_put,
+                           &phba->lpfc_scsi_buf_list_get);
+               INIT_LIST_HEAD(&phba->lpfc_scsi_buf_list_put);
+               spin_unlock_irqrestore(&phba->scsi_buf_list_put_lock, pflag);
+               list_for_each_entry(lpfc_cmd, &phba->lpfc_scsi_buf_list_get,
+                                   list) {
+                       if (lpfc_test_rrq_active(
+                               phba, ndlp, lpfc_cmd->cur_iocbq.sli4_lxritag))
+                               continue;
+                       list_del(&lpfc_cmd->list);
+                       found = 1;
+                       break;
+               }
+       }
+       spin_unlock_irqrestore(&phba->scsi_buf_list_get_lock, gflag);
        if (!found)
                return NULL;
-       else
-               return  lpfc_cmd;
+       return  lpfc_cmd;
 }
 /**
  * lpfc_get_scsi_buf - Get a scsi buffer from lpfc_scsi_buf_list of the HBA
@@ -1160,10 +1209,15 @@ lpfc_release_scsi_buf_s3(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb)
 {
        unsigned long iflag = 0;
 
-       spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag);
+       psb->seg_cnt = 0;
+       psb->nonsg_phys = 0;
+       psb->prot_seg_cnt = 0;
+
+       spin_lock_irqsave(&phba->scsi_buf_list_put_lock, iflag);
        psb->pCmd = NULL;
-       list_add_tail(&psb->list, &phba->lpfc_scsi_buf_list);
-       spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag);
+       psb->cur_iocbq.iocb_flag = LPFC_IO_FCP;
+       list_add_tail(&psb->list, &phba->lpfc_scsi_buf_list_put);
+       spin_unlock_irqrestore(&phba->scsi_buf_list_put_lock, iflag);
 }
 
 /**
@@ -1181,6 +1235,10 @@ lpfc_release_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb)
 {
        unsigned long iflag = 0;
 
+       psb->seg_cnt = 0;
+       psb->nonsg_phys = 0;
+       psb->prot_seg_cnt = 0;
+
        if (psb->exch_busy) {
                spin_lock_irqsave(&phba->sli4_hba.abts_scsi_buf_list_lock,
                                        iflag);
@@ -1190,11 +1248,11 @@ lpfc_release_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb)
                spin_unlock_irqrestore(&phba->sli4_hba.abts_scsi_buf_list_lock,
                                        iflag);
        } else {
-
-               spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag);
                psb->pCmd = NULL;
-               list_add_tail(&psb->list, &phba->lpfc_scsi_buf_list);
-               spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag);
+               psb->cur_iocbq.iocb_flag = LPFC_IO_FCP;
+               spin_lock_irqsave(&phba->scsi_buf_list_put_lock, iflag);
+               list_add_tail(&psb->list, &phba->lpfc_scsi_buf_list_put);
+               spin_unlock_irqrestore(&phba->scsi_buf_list_put_lock, iflag);
        }
 }
 
@@ -1268,6 +1326,7 @@ lpfc_scsi_prep_dma_buf_s3(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)
                               "dma_map_sg.  Config %d, seg_cnt %d\n",
                               __func__, phba->cfg_sg_seg_cnt,
                               lpfc_cmd->seg_cnt);
+                       lpfc_cmd->seg_cnt = 0;
                        scsi_dma_unmap(scsi_cmnd);
                        return 1;
                }
@@ -2013,9 +2072,21 @@ lpfc_bg_setup_bpl(struct lpfc_hba *phba, struct scsi_cmnd *sc,
        bf_set(pde6_type, pde6, LPFC_PDE6_DESCRIPTOR);
        bf_set(pde6_optx, pde6, txop);
        bf_set(pde6_oprx, pde6, rxop);
+
+       /*
+        * We only need to check the data on READs, for WRITEs
+        * protection data is automatically generated, not checked.
+        */
        if (datadir == DMA_FROM_DEVICE) {
-               bf_set(pde6_ce, pde6, checking);
-               bf_set(pde6_re, pde6, checking);
+               if (scsi_prot_flagged(sc, SCSI_PROT_GUARD_CHECK))
+                       bf_set(pde6_ce, pde6, checking);
+               else
+                       bf_set(pde6_ce, pde6, 0);
+
+               if (scsi_prot_flagged(sc, SCSI_PROT_REF_CHECK))
+                       bf_set(pde6_re, pde6, checking);
+               else
+                       bf_set(pde6_re, pde6, 0);
        }
        bf_set(pde6_ai, pde6, 1);
        bf_set(pde6_ae, pde6, 0);
@@ -2145,6 +2216,10 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc,
 
        split_offset = 0;
        do {
+               /* Check to see if we ran out of space */
+               if (num_bde >= (phba->cfg_total_seg_cnt - 2))
+                       return num_bde + 3;
+
                /* setup PDE5 with what we have */
                pde5 = (struct lpfc_pde5 *) bpl;
                memset(pde5, 0, sizeof(struct lpfc_pde5));
@@ -2164,8 +2239,17 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc,
                bf_set(pde6_type, pde6, LPFC_PDE6_DESCRIPTOR);
                bf_set(pde6_optx, pde6, txop);
                bf_set(pde6_oprx, pde6, rxop);
-               bf_set(pde6_ce, pde6, checking);
-               bf_set(pde6_re, pde6, checking);
+
+               if (scsi_prot_flagged(sc, SCSI_PROT_GUARD_CHECK))
+                       bf_set(pde6_ce, pde6, checking);
+               else
+                       bf_set(pde6_ce, pde6, 0);
+
+               if (scsi_prot_flagged(sc, SCSI_PROT_REF_CHECK))
+                       bf_set(pde6_re, pde6, checking);
+               else
+                       bf_set(pde6_re, pde6, 0);
+
                bf_set(pde6_ai, pde6, 1);
                bf_set(pde6_ae, pde6, 0);
                bf_set(pde6_apptagval, pde6, 0);
@@ -2213,6 +2297,10 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc,
                pgdone = 0;
                subtotal = 0; /* total bytes processed for current prot grp */
                while (!pgdone) {
+                       /* Check to see if we ran out of space */
+                       if (num_bde >= phba->cfg_total_seg_cnt)
+                               return num_bde + 1;
+
                        if (!sgde) {
                                lpfc_printf_log(phba, KERN_ERR, LOG_BG,
                                        "9065 BLKGRD:%s Invalid data segment\n",
@@ -2324,7 +2412,6 @@ lpfc_bg_setup_sgl(struct lpfc_hba *phba, struct scsi_cmnd *sc,
        struct sli4_sge_diseed *diseed = NULL;
        dma_addr_t physaddr;
        int i = 0, num_sge = 0, status;
-       int datadir = sc->sc_data_direction;
        uint32_t reftag;
        unsigned blksize;
        uint8_t txop, rxop;
@@ -2362,13 +2449,26 @@ lpfc_bg_setup_sgl(struct lpfc_hba *phba, struct scsi_cmnd *sc,
        diseed->ref_tag = cpu_to_le32(reftag);
        diseed->ref_tag_tran = diseed->ref_tag;
 
+       /*
+        * We only need to check the data on READs, for WRITEs
+        * protection data is automatically generated, not checked.
+        */
+       if (sc->sc_data_direction == DMA_FROM_DEVICE) {
+               if (scsi_prot_flagged(sc, SCSI_PROT_GUARD_CHECK))
+                       bf_set(lpfc_sli4_sge_dif_ce, diseed, checking);
+               else
+                       bf_set(lpfc_sli4_sge_dif_ce, diseed, 0);
+
+               if (scsi_prot_flagged(sc, SCSI_PROT_REF_CHECK))
+                       bf_set(lpfc_sli4_sge_dif_re, diseed, checking);
+               else
+                       bf_set(lpfc_sli4_sge_dif_re, diseed, 0);
+       }
+
        /* setup DISEED with the rest of the info */
        bf_set(lpfc_sli4_sge_dif_optx, diseed, txop);
        bf_set(lpfc_sli4_sge_dif_oprx, diseed, rxop);
-       if (datadir == DMA_FROM_DEVICE) {
-               bf_set(lpfc_sli4_sge_dif_ce, diseed, checking);
-               bf_set(lpfc_sli4_sge_dif_re, diseed, checking);
-       }
+
        bf_set(lpfc_sli4_sge_dif_ai, diseed, 1);
        bf_set(lpfc_sli4_sge_dif_me, diseed, 0);
 
@@ -2497,6 +2597,10 @@ lpfc_bg_setup_sgl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc,
 
        split_offset = 0;
        do {
+               /* Check to see if we ran out of space */
+               if (num_sge >= (phba->cfg_total_seg_cnt - 2))
+                       return num_sge + 3;
+
                /* setup DISEED with what we have */
                diseed = (struct sli4_sge_diseed *) sgl;
                memset(diseed, 0, sizeof(struct sli4_sge_diseed));
@@ -2506,11 +2610,34 @@ lpfc_bg_setup_sgl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc,
                diseed->ref_tag = cpu_to_le32(reftag);
                diseed->ref_tag_tran = diseed->ref_tag;
 
+               if (scsi_prot_flagged(sc, SCSI_PROT_GUARD_CHECK)) {
+                       bf_set(lpfc_sli4_sge_dif_ce, diseed, checking);
+
+               } else {
+                       bf_set(lpfc_sli4_sge_dif_ce, diseed, 0);
+                       /*
+                        * When in this mode, the hardware will replace
+                        * the guard tag from the host with a
+                        * newly generated good CRC for the wire.
+                        * Switch to raw mode here to avoid this
+                        * behavior. What the host sends gets put on the wire.
+                        */
+                       if (txop == BG_OP_IN_CRC_OUT_CRC) {
+                               txop = BG_OP_RAW_MODE;
+                               rxop = BG_OP_RAW_MODE;
+                       }
+               }
+
+
+               if (scsi_prot_flagged(sc, SCSI_PROT_REF_CHECK))
+                       bf_set(lpfc_sli4_sge_dif_re, diseed, checking);
+               else
+                       bf_set(lpfc_sli4_sge_dif_re, diseed, 0);
+
                /* setup DISEED with the rest of the info */
                bf_set(lpfc_sli4_sge_dif_optx, diseed, txop);
                bf_set(lpfc_sli4_sge_dif_oprx, diseed, rxop);
-               bf_set(lpfc_sli4_sge_dif_ce, diseed, checking);
-               bf_set(lpfc_sli4_sge_dif_re, diseed, checking);
+
                bf_set(lpfc_sli4_sge_dif_ai, diseed, 1);
                bf_set(lpfc_sli4_sge_dif_me, diseed, 0);
 
@@ -2556,6 +2683,10 @@ lpfc_bg_setup_sgl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc,
                pgdone = 0;
                subtotal = 0; /* total bytes processed for current prot grp */
                while (!pgdone) {
+                       /* Check to see if we ran out of space */
+                       if (num_sge >= phba->cfg_total_seg_cnt)
+                               return num_sge + 1;
+
                        if (!sgde) {
                                lpfc_printf_log(phba, KERN_ERR, LOG_BG,
                                        "9086 BLKGRD:%s Invalid data segment\n",
@@ -2669,6 +2800,47 @@ lpfc_prot_group_type(struct lpfc_hba *phba, struct scsi_cmnd *sc)
        return ret;
 }
 
+/**
+ * lpfc_bg_scsi_adjust_dl - Adjust SCSI data length for BlockGuard
+ * @phba: The Hba for which this call is being executed.
+ * @lpfc_cmd: The scsi buffer which is going to be adjusted.
+ *
+ * Adjust the data length to account for how much data
+ * is actually on the wire.
+ *
+ * returns the adjusted data length
+ **/
+static int
+lpfc_bg_scsi_adjust_dl(struct lpfc_hba *phba,
+                      struct lpfc_scsi_buf *lpfc_cmd)
+{
+       struct scsi_cmnd *sc = lpfc_cmd->pCmd;
+       int fcpdl;
+
+       fcpdl = scsi_bufflen(sc);
+
+       /* Check if there is protection data on the wire */
+       if (sc->sc_data_direction == DMA_FROM_DEVICE) {
+               /* Read */
+               if (scsi_get_prot_op(sc) ==  SCSI_PROT_READ_INSERT)
+                       return fcpdl;
+
+       } else {
+               /* Write */
+               if (scsi_get_prot_op(sc) ==  SCSI_PROT_WRITE_STRIP)
+                       return fcpdl;
+       }
+
+       /*
+        * If we are in DIF Type 1 mode every data block has a 8 byte
+        * DIF (trailer) attached to it. Must ajust FCP data length.
+        */
+       if (scsi_prot_flagged(sc, SCSI_PROT_TRANSFER_PI))
+               fcpdl += (fcpdl / lpfc_cmd_blksize(sc)) * 8;
+
+       return fcpdl;
+}
+
 /**
  * lpfc_bg_scsi_prep_dma_buf_s3 - DMA mapping for scsi buffer to SLI3 IF spec
  * @phba: The Hba for which this call is being executed.
@@ -2689,8 +2861,7 @@ lpfc_bg_scsi_prep_dma_buf_s3(struct lpfc_hba *phba,
        uint32_t num_bde = 0;
        int datasegcnt, protsegcnt, datadir = scsi_cmnd->sc_data_direction;
        int prot_group_type = 0;
-       int diflen, fcpdl;
-       unsigned blksize;
+       int fcpdl;
 
        /*
         * Start the lpfc command prep by bumping the bpl beyond fcp_cmnd
@@ -2711,28 +2882,28 @@ lpfc_bg_scsi_prep_dma_buf_s3(struct lpfc_hba *phba,
                        return 1;
 
                lpfc_cmd->seg_cnt = datasegcnt;
-               if (lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt) {
-                       lpfc_printf_log(phba, KERN_ERR, LOG_BG,
-                                       "9067 BLKGRD: %s: Too many sg segments"
-                                       " from dma_map_sg.  Config %d, seg_cnt"
-                                       " %d\n",
-                                       __func__, phba->cfg_sg_seg_cnt,
-                                       lpfc_cmd->seg_cnt);
-                       scsi_dma_unmap(scsi_cmnd);
-                       return 1;
-               }
+
+               /* First check if data segment count from SCSI Layer is good */
+               if (lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt)
+                       goto err;
 
                prot_group_type = lpfc_prot_group_type(phba, scsi_cmnd);
 
                switch (prot_group_type) {
                case LPFC_PG_TYPE_NO_DIF:
+
+                       /* Here we need to add a PDE5 and PDE6 to the count */
+                       if ((lpfc_cmd->seg_cnt + 2) > phba->cfg_total_seg_cnt)
+                               goto err;
+
                        num_bde = lpfc_bg_setup_bpl(phba, scsi_cmnd, bpl,
                                        datasegcnt);
                        /* we should have 2 or more entries in buffer list */
                        if (num_bde < 2)
                                goto err;
                        break;
-               case LPFC_PG_TYPE_DIF_BUF:{
+
+               case LPFC_PG_TYPE_DIF_BUF:
                        /*
                         * This type indicates that protection buffers are
                         * passed to the driver, so that needs to be prepared
@@ -2747,31 +2918,28 @@ lpfc_bg_scsi_prep_dma_buf_s3(struct lpfc_hba *phba,
                        }
 
                        lpfc_cmd->prot_seg_cnt = protsegcnt;
-                       if (lpfc_cmd->prot_seg_cnt
-                           > phba->cfg_prot_sg_seg_cnt) {
-                               lpfc_printf_log(phba, KERN_ERR, LOG_BG,
-                                       "9068 BLKGRD: %s: Too many prot sg "
-                                       "segments from dma_map_sg.  Config %d,"
-                                               "prot_seg_cnt %d\n", __func__,
-                                               phba->cfg_prot_sg_seg_cnt,
-                                               lpfc_cmd->prot_seg_cnt);
-                               dma_unmap_sg(&phba->pcidev->dev,
-                                            scsi_prot_sglist(scsi_cmnd),
-                                            scsi_prot_sg_count(scsi_cmnd),
-                                            datadir);
-                               scsi_dma_unmap(scsi_cmnd);
-                               return 1;
-                       }
+
+                       /*
+                        * There is a minimun of 4 BPLs used for every
+                        * protection data segment.
+                        */
+                       if ((lpfc_cmd->prot_seg_cnt * 4) >
+                           (phba->cfg_total_seg_cnt - 2))
+                               goto err;
 
                        num_bde = lpfc_bg_setup_bpl_prot(phba, scsi_cmnd, bpl,
                                        datasegcnt, protsegcnt);
                        /* we should have 3 or more entries in buffer list */
-                       if (num_bde < 3)
+                       if ((num_bde < 3) ||
+                           (num_bde > phba->cfg_total_seg_cnt))
                                goto err;
                        break;
-               }
+
                case LPFC_PG_TYPE_INVALID:
                default:
+                       scsi_dma_unmap(scsi_cmnd);
+                       lpfc_cmd->seg_cnt = 0;
+
                        lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
                                        "9022 Unexpected protection group %i\n",
                                        prot_group_type);
@@ -2790,18 +2958,7 @@ lpfc_bg_scsi_prep_dma_buf_s3(struct lpfc_hba *phba,
        iocb_cmd->ulpBdeCount = 1;
        iocb_cmd->ulpLe = 1;
 
-       fcpdl = scsi_bufflen(scsi_cmnd);
-
-       if (scsi_get_prot_type(scsi_cmnd) == SCSI_PROT_DIF_TYPE1) {
-               /*
-                * We are in DIF Type 1 mode
-                * Every data block has a 8 byte DIF (trailer)
-                * attached to it.  Must ajust FCP data length
-                */
-               blksize = lpfc_cmd_blksize(scsi_cmnd);
-               diflen = (fcpdl / blksize) * 8;
-               fcpdl += diflen;
-       }
+       fcpdl = lpfc_bg_scsi_adjust_dl(phba, lpfc_cmd);
        fcp_cmnd->fcpDl = be32_to_cpu(fcpdl);
 
        /*
@@ -2812,13 +2969,233 @@ lpfc_bg_scsi_prep_dma_buf_s3(struct lpfc_hba *phba,
 
        return 0;
 err:
+       if (lpfc_cmd->seg_cnt)
+               scsi_dma_unmap(scsi_cmnd);
+       if (lpfc_cmd->prot_seg_cnt)
+               dma_unmap_sg(&phba->pcidev->dev, scsi_prot_sglist(scsi_cmnd),
+                            scsi_prot_sg_count(scsi_cmnd),
+                            scsi_cmnd->sc_data_direction);
+
        lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
-                       "9023 Could not setup all needed BDE's"
-                       "prot_group_type=%d, num_bde=%d\n",
+                       "9023 Cannot setup S/G List for HBA"
+                       "IO segs %d/%d BPL %d SCSI %d: %d %d\n",
+                       lpfc_cmd->seg_cnt, lpfc_cmd->prot_seg_cnt,
+                       phba->cfg_total_seg_cnt, phba->cfg_sg_seg_cnt,
                        prot_group_type, num_bde);
+
+       lpfc_cmd->seg_cnt = 0;
+       lpfc_cmd->prot_seg_cnt = 0;
        return 1;
 }
 
+/*
+ * This function calcuates the T10 DIF guard tag
+ * on the specified data using a CRC algorithmn
+ * using crc_t10dif.
+ */
+uint16_t
+lpfc_bg_crc(uint8_t *data, int count)
+{
+       uint16_t crc = 0;
+       uint16_t x;
+
+       crc = crc_t10dif(data, count);
+       x = cpu_to_be16(crc);
+       return x;
+}
+
+/*
+ * This function calcuates the T10 DIF guard tag
+ * on the specified data using a CSUM algorithmn
+ * using ip_compute_csum.
+ */
+uint16_t
+lpfc_bg_csum(uint8_t *data, int count)
+{
+       uint16_t ret;
+
+       ret = ip_compute_csum(data, count);
+       return ret;
+}
+
+/*
+ * This function examines the protection data to try to determine
+ * what type of T10-DIF error occurred.
+ */
+void
+lpfc_calc_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)
+{
+       struct scatterlist *sgpe; /* s/g prot entry */
+       struct scatterlist *sgde; /* s/g data entry */
+       struct scsi_cmnd *cmd = lpfc_cmd->pCmd;
+       struct scsi_dif_tuple *src = NULL;
+       uint8_t *data_src = NULL;
+       uint16_t guard_tag, guard_type;
+       uint16_t start_app_tag, app_tag;
+       uint32_t start_ref_tag, ref_tag;
+       int prot, protsegcnt;
+       int err_type, len, data_len;
+       int chk_ref, chk_app, chk_guard;
+       uint16_t sum;
+       unsigned blksize;
+
+       err_type = BGS_GUARD_ERR_MASK;
+       sum = 0;
+       guard_tag = 0;
+
+       /* First check to see if there is protection data to examine */
+       prot = scsi_get_prot_op(cmd);
+       if ((prot == SCSI_PROT_READ_STRIP) ||
+           (prot == SCSI_PROT_WRITE_INSERT) ||
+           (prot == SCSI_PROT_NORMAL))
+               goto out;
+
+       /* Currently the driver just supports ref_tag and guard_tag checking */
+       chk_ref = 1;
+       chk_app = 0;
+       chk_guard = 0;
+
+       /* Setup a ptr to the protection data provided by the SCSI host */
+       sgpe = scsi_prot_sglist(cmd);
+       protsegcnt = lpfc_cmd->prot_seg_cnt;
+
+       if (sgpe && protsegcnt) {
+
+               /*
+                * We will only try to verify guard tag if the segment
+                * data length is a multiple of the blksize.
+                */
+               sgde = scsi_sglist(cmd);
+               blksize = lpfc_cmd_blksize(cmd);
+               data_src = (uint8_t *)sg_virt(sgde);
+               data_len = sgde->length;
+               if ((data_len & (blksize - 1)) == 0)
+                       chk_guard = 1;
+               guard_type = scsi_host_get_guard(cmd->device->host);
+
+               start_ref_tag = (uint32_t)scsi_get_lba(cmd); /* Truncate LBA */
+               start_app_tag = src->app_tag;
+               src = (struct scsi_dif_tuple *)sg_virt(sgpe);
+               len = sgpe->length;
+               while (src && protsegcnt) {
+                       while (len) {
+
+                               /*
+                                * First check to see if a protection data
+                                * check is valid
+                                */
+                               if ((src->ref_tag == 0xffffffff) ||
+                                   (src->app_tag == 0xffff)) {
+                                       start_ref_tag++;
+                                       goto skipit;
+                               }
+
+                               /* App Tag checking */
+                               app_tag = src->app_tag;
+                               if (chk_app && (app_tag != start_app_tag)) {
+                                       err_type = BGS_APPTAG_ERR_MASK;
+                                       goto out;
+                               }
+
+                               /* Reference Tag checking */
+                               ref_tag = be32_to_cpu(src->ref_tag);
+                               if (chk_ref && (ref_tag != start_ref_tag)) {
+                                       err_type = BGS_REFTAG_ERR_MASK;
+                                       goto out;
+                               }
+                               start_ref_tag++;
+
+                               /* Guard Tag checking */
+                               if (chk_guard) {
+                                       guard_tag = src->guard_tag;
+                                       if (guard_type == SHOST_DIX_GUARD_IP)
+                                               sum = lpfc_bg_csum(data_src,
+                                                                  blksize);
+                                       else
+                                               sum = lpfc_bg_crc(data_src,
+                                                                 blksize);
+                                       if ((guard_tag != sum)) {
+                                               err_type = BGS_GUARD_ERR_MASK;
+                                               goto out;
+                                       }
+                               }
+skipit:
+                               len -= sizeof(struct scsi_dif_tuple);
+                               if (len < 0)
+                                       len = 0;
+                               src++;
+
+                               data_src += blksize;
+                               data_len -= blksize;
+
+                               /*
+                                * Are we at the end of the Data segment?
+                                * The data segment is only used for Guard
+                                * tag checking.
+                                */
+                               if (chk_guard && (data_len == 0)) {
+                                       chk_guard = 0;
+                                       sgde = sg_next(sgde);
+                                       if (!sgde)
+                                               goto out;
+
+                                       data_src = (uint8_t *)sg_virt(sgde);
+                                       data_len = sgde->length;
+                                       if ((data_len & (blksize - 1)) == 0)
+                                               chk_guard = 1;
+                               }
+                       }
+
+                       /* Goto the next Protection data segment */
+                       sgpe = sg_next(sgpe);
+                       if (sgpe) {
+                               src = (struct scsi_dif_tuple *)sg_virt(sgpe);
+                               len = sgpe->length;
+                       } else {
+                               src = NULL;
+                       }
+                       protsegcnt--;
+               }
+       }
+out:
+       if (err_type == BGS_GUARD_ERR_MASK) {
+               scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST,
+                                       0x10, 0x1);
+               cmd->result = DRIVER_SENSE << 24
+                       | ScsiResult(DID_ABORT, SAM_STAT_CHECK_CONDITION);
+               phba->bg_guard_err_cnt++;
+               lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG,
+                               "9069 BLKGRD: LBA %lx grd_tag error %x != %x\n",
+                               (unsigned long)scsi_get_lba(cmd),
+                               sum, guard_tag);
+
+       } else if (err_type == BGS_REFTAG_ERR_MASK) {
+               scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST,
+                                       0x10, 0x3);
+               cmd->result = DRIVER_SENSE << 24
+                       | ScsiResult(DID_ABORT, SAM_STAT_CHECK_CONDITION);
+
+               phba->bg_reftag_err_cnt++;
+               lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG,
+                               "9066 BLKGRD: LBA %lx ref_tag error %x != %x\n",
+                               (unsigned long)scsi_get_lba(cmd),
+                               ref_tag, start_ref_tag);
+
+       } else if (err_type == BGS_APPTAG_ERR_MASK) {
+               scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST,
+                                       0x10, 0x2);
+               cmd->result = DRIVER_SENSE << 24
+                       | ScsiResult(DID_ABORT, SAM_STAT_CHECK_CONDITION);
+
+               phba->bg_apptag_err_cnt++;
+               lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG,
+                               "9041 BLKGRD: LBA %lx app_tag error %x != %x\n",
+                               (unsigned long)scsi_get_lba(cmd),
+                               app_tag, start_app_tag);
+       }
+}
+
+
 /*
  * This function checks for BlockGuard errors detected by
  * the HBA.  In case of errors, the ASC/ASCQ fields in the
@@ -2842,12 +3219,6 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd,
        uint32_t bgstat = bgf->bgstat;
        uint64_t failing_sector = 0;
 
-       lpfc_printf_log(phba, KERN_ERR, LOG_BG, "9069 BLKGRD: BG ERROR in cmd"
-                       " 0x%x lba 0x%llx blk cnt 0x%x "
-                       "bgstat=0x%x bghm=0x%x\n",
-                       cmd->cmnd[0], (unsigned long long)scsi_get_lba(cmd),
-                       blk_rq_sectors(cmd->request), bgstat, bghm);
-
        spin_lock(&_dump_buf_lock);
        if (!_dump_buf_done) {
                lpfc_printf_log(phba, KERN_ERR, LOG_BG,  "9070 BLKGRD: Saving"
@@ -2870,18 +3241,24 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd,
 
        if (lpfc_bgs_get_invalid_prof(bgstat)) {
                cmd->result = ScsiResult(DID_ERROR, 0);
-               lpfc_printf_log(phba, KERN_ERR, LOG_BG, "9072 BLKGRD: Invalid"
-                       " BlockGuard profile. bgstat:0x%x\n",
-                       bgstat);
+               lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG,
+                               "9072 BLKGRD: Invalid BG Profile in cmd"
+                               " 0x%x lba 0x%llx blk cnt 0x%x "
+                               "bgstat=x%x bghm=x%x\n", cmd->cmnd[0],
+                               (unsigned long long)scsi_get_lba(cmd),
+                               blk_rq_sectors(cmd->request), bgstat, bghm);
                ret = (-1);
                goto out;
        }
 
        if (lpfc_bgs_get_uninit_dif_block(bgstat)) {
                cmd->result = ScsiResult(DID_ERROR, 0);
-               lpfc_printf_log(phba, KERN_ERR, LOG_BG, "9073 BLKGRD: "
-                               "Invalid BlockGuard DIF Block. bgstat:0x%x\n",
-                               bgstat);
+               lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG,
+                               "9073 BLKGRD: Invalid BG PDIF Block in cmd"
+                               " 0x%x lba 0x%llx blk cnt 0x%x "
+                               "bgstat=x%x bghm=x%x\n", cmd->cmnd[0],
+                               (unsigned long long)scsi_get_lba(cmd),
+                               blk_rq_sectors(cmd->request), bgstat, bghm);
                ret = (-1);
                goto out;
        }
@@ -2894,8 +3271,12 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd,
                cmd->result = DRIVER_SENSE << 24
                        | ScsiResult(DID_ABORT, SAM_STAT_CHECK_CONDITION);
                phba->bg_guard_err_cnt++;
-               lpfc_printf_log(phba, KERN_ERR, LOG_BG,
-                       "9055 BLKGRD: guard_tag error\n");
+               lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG,
+                               "9055 BLKGRD: Guard Tag error in cmd"
+                               " 0x%x lba 0x%llx blk cnt 0x%x "
+                               "bgstat=x%x bghm=x%x\n", cmd->cmnd[0],
+                               (unsigned long long)scsi_get_lba(cmd),
+                               blk_rq_sectors(cmd->request), bgstat, bghm);
        }
 
        if (lpfc_bgs_get_reftag_err(bgstat)) {
@@ -2907,8 +3288,12 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd,
                        | ScsiResult(DID_ABORT, SAM_STAT_CHECK_CONDITION);
 
                phba->bg_reftag_err_cnt++;
-               lpfc_printf_log(phba, KERN_ERR, LOG_BG,
-                       "9056 BLKGRD: ref_tag error\n");
+               lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG,
+                               "9056 BLKGRD: Ref Tag error in cmd"
+                               " 0x%x lba 0x%llx blk cnt 0x%x "
+                               "bgstat=x%x bghm=x%x\n", cmd->cmnd[0],
+                               (unsigned long long)scsi_get_lba(cmd),
+                               blk_rq_sectors(cmd->request), bgstat, bghm);
        }
 
        if (lpfc_bgs_get_apptag_err(bgstat)) {
@@ -2920,8 +3305,12 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd,
                        | ScsiResult(DID_ABORT, SAM_STAT_CHECK_CONDITION);
 
                phba->bg_apptag_err_cnt++;
-               lpfc_printf_log(phba, KERN_ERR, LOG_BG,
-                       "9061 BLKGRD: app_tag error\n");
+               lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG,
+                               "9061 BLKGRD: App Tag error in cmd"
+                               " 0x%x lba 0x%llx blk cnt 0x%x "
+                               "bgstat=x%x bghm=x%x\n", cmd->cmnd[0],
+                               (unsigned long long)scsi_get_lba(cmd),
+                               blk_rq_sectors(cmd->request), bgstat, bghm);
        }
 
        if (lpfc_bgs_get_hi_water_mark_present(bgstat)) {
@@ -2960,11 +3349,16 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd,
 
        if (!ret) {
                /* No error was reported - problem in FW? */
-               cmd->result = ScsiResult(DID_ERROR, 0);
-               lpfc_printf_log(phba, KERN_ERR, LOG_BG,
-                       "9057 BLKGRD: Unknown error reported!\n");
+               lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG,
+                               "9057 BLKGRD: Unknown error in cmd"
+                               " 0x%x lba 0x%llx blk cnt 0x%x "
+                               "bgstat=x%x bghm=x%x\n", cmd->cmnd[0],
+                               (unsigned long long)scsi_get_lba(cmd),
+                               blk_rq_sectors(cmd->request), bgstat, bghm);
+
+               /* Calcuate what type of error it was */
+               lpfc_calc_bg_err(phba, lpfc_cmd);
        }
-
 out:
        return ret;
 }
@@ -3028,6 +3422,7 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)
                                "dma_map_sg.  Config %d, seg_cnt %d\n",
                                __func__, phba->cfg_sg_seg_cnt,
                               lpfc_cmd->seg_cnt);
+                       lpfc_cmd->seg_cnt = 0;
                        scsi_dma_unmap(scsi_cmnd);
                        return 1;
                }
@@ -3093,45 +3488,6 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)
        return 0;
 }
 
-/**
- * lpfc_bg_scsi_adjust_dl - Adjust SCSI data length for BlockGuard
- * @phba: The Hba for which this call is being executed.
- * @lpfc_cmd: The scsi buffer which is going to be adjusted.
- *
- * Adjust the data length to account for how much data
- * is actually on the wire.
- *
- * returns the adjusted data length
- **/
-static int
-lpfc_bg_scsi_adjust_dl(struct lpfc_hba *phba,
-               struct lpfc_scsi_buf *lpfc_cmd)
-{
-       struct scsi_cmnd *sc = lpfc_cmd->pCmd;
-       int diflen, fcpdl;
-       unsigned blksize;
-
-       fcpdl = scsi_bufflen(sc);
-
-       /* Check if there is protection data on the wire */
-       if (sc->sc_data_direction == DMA_FROM_DEVICE) {
-               /* Read */
-               if (scsi_get_prot_op(sc) ==  SCSI_PROT_READ_INSERT)
-                       return fcpdl;
-
-       } else {
-               /* Write */
-               if (scsi_get_prot_op(sc) ==  SCSI_PROT_WRITE_STRIP)
-                       return fcpdl;
-       }
-
-       /* If protection data on the wire, adjust the count accordingly */
-       blksize = lpfc_cmd_blksize(sc);
-       diflen = (fcpdl / blksize) * 8;
-       fcpdl += diflen;
-       return fcpdl;
-}
-
 /**
  * lpfc_bg_scsi_prep_dma_buf_s4 - DMA mapping for scsi buffer to SLI4 IF spec
  * @phba: The Hba for which this call is being executed.
@@ -3149,14 +3505,14 @@ lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc_hba *phba,
        struct fcp_cmnd *fcp_cmnd = lpfc_cmd->fcp_cmnd;
        struct sli4_sge *sgl = (struct sli4_sge *)(lpfc_cmd->fcp_bpl);
        IOCB_t *iocb_cmd = &lpfc_cmd->cur_iocbq.iocb;
-       uint32_t num_bde = 0;
+       uint32_t num_sge = 0;
        int datasegcnt, protsegcnt, datadir = scsi_cmnd->sc_data_direction;
        int prot_group_type = 0;
        int fcpdl;
 
        /*
         * Start the lpfc command prep by bumping the sgl beyond fcp_cmnd
-        *  fcp_rsp regions to the first data bde entry
+        *  fcp_rsp regions to the first data sge entry
         */
        if (scsi_sg_count(scsi_cmnd)) {
                /*
@@ -3179,28 +3535,28 @@ lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc_hba *phba,
 
                sgl += 1;
                lpfc_cmd->seg_cnt = datasegcnt;
-               if (lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt) {
-                       lpfc_printf_log(phba, KERN_ERR, LOG_BG,
-                                       "9087 BLKGRD: %s: Too many sg segments"
-                                       " from dma_map_sg.  Config %d, seg_cnt"
-                                       " %d\n",
-                                       __func__, phba->cfg_sg_seg_cnt,
-                                       lpfc_cmd->seg_cnt);
-                       scsi_dma_unmap(scsi_cmnd);
-                       return 1;
-               }
+
+               /* First check if data segment count from SCSI Layer is good */
+               if (lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt)
+                       goto err;
 
                prot_group_type = lpfc_prot_group_type(phba, scsi_cmnd);
 
                switch (prot_group_type) {
                case LPFC_PG_TYPE_NO_DIF:
-                       num_bde = lpfc_bg_setup_sgl(phba, scsi_cmnd, sgl,
+                       /* Here we need to add a DISEED to the count */
+                       if ((lpfc_cmd->seg_cnt + 1) > phba->cfg_total_seg_cnt)
+                               goto err;
+
+                       num_sge = lpfc_bg_setup_sgl(phba, scsi_cmnd, sgl,
                                        datasegcnt);
+
                        /* we should have 2 or more entries in buffer list */
-                       if (num_bde < 2)
+                       if (num_sge < 2)
                                goto err;
                        break;
-               case LPFC_PG_TYPE_DIF_BUF:{
+
+               case LPFC_PG_TYPE_DIF_BUF:
                        /*
                         * This type indicates that protection buffers are
                         * passed to the driver, so that needs to be prepared
@@ -3215,31 +3571,28 @@ lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc_hba *phba,
                        }
 
                        lpfc_cmd->prot_seg_cnt = protsegcnt;
-                       if (lpfc_cmd->prot_seg_cnt
-                           > phba->cfg_prot_sg_seg_cnt) {
-                               lpfc_printf_log(phba, KERN_ERR, LOG_BG,
-                                       "9088 BLKGRD: %s: Too many prot sg "
-                                       "segments from dma_map_sg.  Config %d,"
-                                               "prot_seg_cnt %d\n", __func__,
-                                               phba->cfg_prot_sg_seg_cnt,
-                                               lpfc_cmd->prot_seg_cnt);
-                               dma_unmap_sg(&phba->pcidev->dev,
-                                            scsi_prot_sglist(scsi_cmnd),
-                                            scsi_prot_sg_count(scsi_cmnd),
-                                            datadir);
-                               scsi_dma_unmap(scsi_cmnd);
-                               return 1;
-                       }
+                       /*
+                        * There is a minimun of 3 SGEs used for every
+                        * protection data segment.
+                        */
+                       if ((lpfc_cmd->prot_seg_cnt * 3) >
+                           (phba->cfg_total_seg_cnt - 2))
+                               goto err;
 
-                       num_bde = lpfc_bg_setup_sgl_prot(phba, scsi_cmnd, sgl,
+                       num_sge = lpfc_bg_setup_sgl_prot(phba, scsi_cmnd, sgl,
                                        datasegcnt, protsegcnt);
+
                        /* we should have 3 or more entries in buffer list */
-                       if (num_bde < 3)
+                       if ((num_sge < 3) ||
+                           (num_sge > phba->cfg_total_seg_cnt))
                                goto err;
                        break;
-               }
+
                case LPFC_PG_TYPE_INVALID:
                default:
+                       scsi_dma_unmap(scsi_cmnd);
+                       lpfc_cmd->seg_cnt = 0;
+
                        lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
                                        "9083 Unexpected protection group %i\n",
                                        prot_group_type);
@@ -3263,7 +3616,6 @@ lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc_hba *phba,
        }
 
        fcpdl = lpfc_bg_scsi_adjust_dl(phba, lpfc_cmd);
-
        fcp_cmnd->fcpDl = be32_to_cpu(fcpdl);
 
        /*
@@ -3274,10 +3626,22 @@ lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc_hba *phba,
 
        return 0;
 err:
+       if (lpfc_cmd->seg_cnt)
+               scsi_dma_unmap(scsi_cmnd);
+       if (lpfc_cmd->prot_seg_cnt)
+               dma_unmap_sg(&phba->pcidev->dev, scsi_prot_sglist(scsi_cmnd),
+                            scsi_prot_sg_count(scsi_cmnd),
+                            scsi_cmnd->sc_data_direction);
+
        lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
-                       "9084 Could not setup all needed BDE's"
-                       "prot_group_type=%d, num_bde=%d\n",
-                       prot_group_type, num_bde);
+                       "9084 Cannot setup S/G List for HBA"
+                       "IO segs %d/%d SGL %d SCSI %d: %d %d\n",
+                       lpfc_cmd->seg_cnt, lpfc_cmd->prot_seg_cnt,
+                       phba->cfg_total_seg_cnt, phba->cfg_sg_seg_cnt,
+                       prot_group_type, num_sge);
+
+       lpfc_cmd->seg_cnt = 0;
+       lpfc_cmd->prot_seg_cnt = 0;
        return 1;
 }
 
@@ -4357,7 +4721,8 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd)
 
        if (scsi_get_prot_op(cmnd) != SCSI_PROT_NORMAL) {
                if (vport->phba->cfg_enable_bg) {
-                       lpfc_printf_vlog(vport, KERN_INFO, LOG_BG,
+                       lpfc_printf_vlog(vport,
+                                        KERN_INFO, LOG_SCSI_CMD,
                                         "9033 BLKGRD: rcvd %s cmd:x%x "
                                         "sector x%llx cnt %u pt %x\n",
                                         dif_op_str[scsi_get_prot_op(cmnd)],
@@ -4369,7 +4734,8 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd)
                err = lpfc_bg_scsi_prep_dma_buf(phba, lpfc_cmd);
        } else {
                if (vport->phba->cfg_enable_bg) {
-                       lpfc_printf_vlog(vport, KERN_INFO, LOG_BG,
+                       lpfc_printf_vlog(vport,
+                                        KERN_INFO, LOG_SCSI_CMD,
                                         "9038 BLKGRD: rcvd PROT_NORMAL cmd: "
                                         "x%x sector x%llx cnt %u pt %x\n",
                                         cmnd->cmnd[0],
@@ -4542,7 +4908,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
        /* Wait for abort to complete */
        wait_event_timeout(waitq,
                          (lpfc_cmd->pCmd != cmnd),
-                          (2*vport->cfg_devloss_tmo*HZ));
+                          msecs_to_jiffies(2*vport->cfg_devloss_tmo*1000));
        lpfc_cmd->waitq = NULL;
 
        if (lpfc_cmd->pCmd == cmnd) {
@@ -5012,16 +5378,24 @@ lpfc_host_reset_handler(struct scsi_cmnd *cmnd)
        struct lpfc_hba *phba = vport->phba;
        int rc, ret = SUCCESS;
 
+       lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
+                        "3172 SCSI layer issued Host Reset Data:\n");
+
        lpfc_offline_prep(phba, LPFC_MBX_WAIT);
        lpfc_offline(phba);
        rc = lpfc_sli_brdrestart(phba);
        if (rc)
                ret = FAILED;
-       lpfc_online(phba);
+       rc = lpfc_online(phba);
+       if (rc)
+               ret = FAILED;
        lpfc_unblock_mgmt_io(phba);
 
-       lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
-                       "3172 SCSI layer issued Host Reset Data: x%x\n", ret);
+       if (ret == FAILED) {
+               lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
+                                "3323 Failed host reset, bring it offline\n");
+               lpfc_sli4_offline_eratt(phba);
+       }
        return ret;
 }
 
@@ -5088,11 +5462,11 @@ lpfc_slave_alloc(struct scsi_device *sdev)
        }
        num_allocated = lpfc_new_scsi_buf(vport, num_to_alloc);
        if (num_to_alloc != num_allocated) {
-                       lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP,
-                                "0708 Allocation request of %d "
-                                "command buffers did not succeed.  "
-                                "Allocated %d buffers.\n",
-                                num_to_alloc, num_allocated);
+                       lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
+                                        "0708 Allocation request of %d "
+                                        "command buffers did not succeed.  "
+                                        "Allocated %d buffers.\n",
+                                        num_to_alloc, num_allocated);
        }
        if (num_allocated > 0)
                phba->total_scsi_bufs += num_allocated;
index 35dd17e..572579f 100644 (file)
@@ -667,7 +667,7 @@ lpfc_handle_rrq_active(struct lpfc_hba *phba)
 
        spin_lock_irqsave(&phba->hbalock, iflags);
        phba->hba_flag &= ~HBA_RRQ_ACTIVE;
-       next_time = jiffies + HZ * (phba->fc_ratov + 1);
+       next_time = jiffies + msecs_to_jiffies(1000 * (phba->fc_ratov + 1));
        list_for_each_entry_safe(rrq, nextrrq,
                                 &phba->active_rrq_list, list) {
                if (time_after(jiffies, rrq->rrq_stop_time))
@@ -782,7 +782,7 @@ lpfc_cleanup_wt_rrqs(struct lpfc_hba *phba)
                return;
        spin_lock_irqsave(&phba->hbalock, iflags);
        phba->hba_flag &= ~HBA_RRQ_ACTIVE;
-       next_time = jiffies + HZ * (phba->fc_ratov * 2);
+       next_time = jiffies + msecs_to_jiffies(1000 * (phba->fc_ratov * 2));
        list_splice_init(&phba->active_rrq_list, &rrq_list);
        spin_unlock_irqrestore(&phba->hbalock, iflags);
 
@@ -878,7 +878,8 @@ lpfc_set_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
        else
                rrq->send_rrq = 0;
        rrq->xritag = xritag;
-       rrq->rrq_stop_time = jiffies + HZ * (phba->fc_ratov + 1);
+       rrq->rrq_stop_time = jiffies +
+                               msecs_to_jiffies(1000 * (phba->fc_ratov + 1));
        rrq->ndlp = ndlp;
        rrq->nlp_DID = ndlp->nlp_DID;
        rrq->vport = ndlp->vport;
@@ -926,8 +927,7 @@ __lpfc_sli_get_sglq(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq)
        } else  if ((piocbq->iocb.ulpCommand == CMD_GEN_REQUEST64_CR) &&
                        !(piocbq->iocb_flag & LPFC_IO_LIBDFC))
                ndlp = piocbq->context_un.ndlp;
-       else  if ((piocbq->iocb.ulpCommand == CMD_ELS_REQUEST64_CR) &&
-                       (piocbq->iocb_flag & LPFC_IO_LIBDFC))
+       else  if (piocbq->iocb_flag & LPFC_IO_LIBDFC)
                ndlp = piocbq->context_un.ndlp;
        else
                ndlp = piocbq->context1;
@@ -1339,7 +1339,8 @@ lpfc_sli_ringtxcmpl_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
                        BUG();
                else
                        mod_timer(&piocb->vport->els_tmofunc,
-                                 jiffies + HZ * (phba->fc_ratov << 1));
+                               jiffies +
+                               msecs_to_jiffies(1000 * (phba->fc_ratov << 1)));
        }
 
 
@@ -2340,7 +2341,8 @@ lpfc_sli_handle_mb_event(struct lpfc_hba *phba)
                /* Mailbox cmd <cmd> Cmpl <cmpl> */
                lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI,
                                "(%d):0307 Mailbox cmd x%x (x%x/x%x) Cmpl x%p "
-                               "Data: x%x x%x x%x x%x x%x x%x x%x x%x x%x\n",
+                               "Data: x%x x%x x%x x%x x%x x%x x%x x%x x%x "
+                               "x%x x%x x%x\n",
                                pmb->vport ? pmb->vport->vpi : 0,
                                pmbox->mbxCommand,
                                lpfc_sli_config_mbox_subsys_get(phba, pmb),
@@ -2354,7 +2356,10 @@ lpfc_sli_handle_mb_event(struct lpfc_hba *phba)
                                pmbox->un.varWords[4],
                                pmbox->un.varWords[5],
                                pmbox->un.varWords[6],
-                               pmbox->un.varWords[7]);
+                               pmbox->un.varWords[7],
+                               pmbox->un.varWords[8],
+                               pmbox->un.varWords[9],
+                               pmbox->un.varWords[10]);
 
                if (pmb->mbox_cmpl)
                        pmb->mbox_cmpl(phba,pmb);
@@ -2908,8 +2913,9 @@ void lpfc_poll_eratt(unsigned long ptr)
                lpfc_worker_wake_up(phba);
        else
                /* Restart the timer for next eratt poll */
-               mod_timer(&phba->eratt_poll, jiffies +
-                                       HZ * LPFC_ERATT_POLL_INTERVAL);
+               mod_timer(&phba->eratt_poll,
+                         jiffies +
+                         msecs_to_jiffies(1000 * LPFC_ERATT_POLL_INTERVAL));
        return;
 }
 
@@ -5511,6 +5517,7 @@ lpfc_sli4_dealloc_extent(struct lpfc_hba *phba, uint16_t type)
                        list_del_init(&rsrc_blk->list);
                        kfree(rsrc_blk);
                }
+               phba->sli4_hba.max_cfg_param.vpi_used = 0;
                break;
        case LPFC_RSC_TYPE_FCOE_XRI:
                kfree(phba->sli4_hba.xri_bmask);
@@ -5811,6 +5818,7 @@ lpfc_sli4_dealloc_resource_identifiers(struct lpfc_hba *phba)
                lpfc_sli4_dealloc_extent(phba, LPFC_RSC_TYPE_FCOE_VFI);
        } else {
                kfree(phba->vpi_bmask);
+               phba->sli4_hba.max_cfg_param.vpi_used = 0;
                kfree(phba->vpi_ids);
                bf_set(lpfc_vpi_rsrc_rdy, &phba->sli4_hba.sli4_flags, 0);
                kfree(phba->sli4_hba.xri_bmask);
@@ -5992,7 +6000,7 @@ lpfc_sli4_repost_els_sgl_list(struct lpfc_hba *phba)
        struct lpfc_sglq *sglq_entry = NULL;
        struct lpfc_sglq *sglq_entry_next = NULL;
        struct lpfc_sglq *sglq_entry_first = NULL;
-       int status, post_cnt = 0, num_posted = 0, block_cnt = 0;
+       int status, total_cnt, post_cnt = 0, num_posted = 0, block_cnt = 0;
        int last_xritag = NO_XRI;
        LIST_HEAD(prep_sgl_list);
        LIST_HEAD(blck_sgl_list);
@@ -6004,6 +6012,7 @@ lpfc_sli4_repost_els_sgl_list(struct lpfc_hba *phba)
        list_splice_init(&phba->sli4_hba.lpfc_sgl_list, &allc_sgl_list);
        spin_unlock_irq(&phba->hbalock);
 
+       total_cnt = phba->sli4_hba.els_xri_cnt;
        list_for_each_entry_safe(sglq_entry, sglq_entry_next,
                                 &allc_sgl_list, list) {
                list_del_init(&sglq_entry->list);
@@ -6055,9 +6064,7 @@ lpfc_sli4_repost_els_sgl_list(struct lpfc_hba *phba)
                                                sglq_entry->sli4_xritag);
                                        list_add_tail(&sglq_entry->list,
                                                      &free_sgl_list);
-                                       spin_lock_irq(&phba->hbalock);
-                                       phba->sli4_hba.els_xri_cnt--;
-                                       spin_unlock_irq(&phba->hbalock);
+                                       total_cnt--;
                                }
                        }
                }
@@ -6085,9 +6092,7 @@ lpfc_sli4_repost_els_sgl_list(struct lpfc_hba *phba)
                                        (sglq_entry_first->sli4_xritag +
                                         post_cnt - 1));
                        list_splice_init(&blck_sgl_list, &free_sgl_list);
-                       spin_lock_irq(&phba->hbalock);
-                       phba->sli4_hba.els_xri_cnt -= post_cnt;
-                       spin_unlock_irq(&phba->hbalock);
+                       total_cnt -= post_cnt;
                }
 
                /* don't reset xirtag due to hole in xri block */
@@ -6097,6 +6102,8 @@ lpfc_sli4_repost_els_sgl_list(struct lpfc_hba *phba)
                /* reset els sgl post count for next round of posting */
                post_cnt = 0;
        }
+       /* update the number of XRIs posted for ELS */
+       phba->sli4_hba.els_xri_cnt = total_cnt;
 
        /* free the els sgls failed to post */
        lpfc_free_sgl_list(phba, &free_sgl_list);
@@ -6446,16 +6453,17 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
 
        /* Start the ELS watchdog timer */
        mod_timer(&vport->els_tmofunc,
-                 jiffies + HZ * (phba->fc_ratov * 2));
+                 jiffies + msecs_to_jiffies(1000 * (phba->fc_ratov * 2)));
 
        /* Start heart beat timer */
        mod_timer(&phba->hb_tmofunc,
-                 jiffies + HZ * LPFC_HB_MBOX_INTERVAL);
+                 jiffies + msecs_to_jiffies(1000 * LPFC_HB_MBOX_INTERVAL));
        phba->hb_outstanding = 0;
        phba->last_completion_time = jiffies;
 
        /* Start error attention (ERATT) polling timer */
-       mod_timer(&phba->eratt_poll, jiffies + HZ * LPFC_ERATT_POLL_INTERVAL);
+       mod_timer(&phba->eratt_poll,
+                 jiffies + msecs_to_jiffies(1000 * LPFC_ERATT_POLL_INTERVAL));
 
        /* Enable PCIe device Advanced Error Reporting (AER) if configured */
        if (phba->cfg_aer_support == 1 && !(phba->hba_flag & HBA_AER_ENABLED)) {
@@ -6822,8 +6830,9 @@ lpfc_sli_issue_mbox_s3(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox,
                        goto out_not_finished;
                }
                /* timeout active mbox command */
-               mod_timer(&psli->mbox_tmo, (jiffies +
-                              (HZ * lpfc_mbox_tmo_val(phba, pmbox))));
+               timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba, pmbox) *
+                                          1000);
+               mod_timer(&psli->mbox_tmo, jiffies + timeout);
        }
 
        /* Mailbox cmd <cmd> issue */
@@ -7496,7 +7505,7 @@ lpfc_sli4_post_async_mbox(struct lpfc_hba *phba)
 
        /* Start timer for the mbox_tmo and log some mailbox post messages */
        mod_timer(&psli->mbox_tmo, (jiffies +
-                 (HZ * lpfc_mbox_tmo_val(phba, mboxq))));
+                 msecs_to_jiffies(1000 * lpfc_mbox_tmo_val(phba, mboxq))));
 
        lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI,
                        "(%d):0355 Mailbox cmd x%x (x%x/x%x) issue Data: "
@@ -7914,15 +7923,21 @@ lpfc_sli4_bpl2sgl(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq,
 static inline uint32_t
 lpfc_sli4_scmd_to_wqidx_distr(struct lpfc_hba *phba)
 {
-       int i;
-
-       if (phba->cfg_fcp_io_sched == LPFC_FCP_SCHED_BY_CPU)
-               i = smp_processor_id();
-       else
-               i = atomic_add_return(1, &phba->fcp_qidx);
+       struct lpfc_vector_map_info *cpup;
+       int chann, cpu;
 
-       i = (i % phba->cfg_fcp_io_channel);
-       return i;
+       if (phba->cfg_fcp_io_sched == LPFC_FCP_SCHED_BY_CPU) {
+               cpu = smp_processor_id();
+               if (cpu < phba->sli4_hba.num_present_cpu) {
+                       cpup = phba->sli4_hba.cpu_map;
+                       cpup += cpu;
+                       return cpup->channel_id;
+               }
+               chann = cpu;
+       }
+       chann = atomic_add_return(1, &phba->fcp_qidx);
+       chann = (chann % phba->cfg_fcp_io_channel);
+       return chann;
 }
 
 /**
@@ -8444,10 +8459,14 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number,
 
        if ((piocb->iocb_flag & LPFC_IO_FCP) ||
                (piocb->iocb_flag & LPFC_USE_FCPWQIDX)) {
+               if (unlikely(!phba->sli4_hba.fcp_wq))
+                       return IOCB_ERROR;
                if (lpfc_sli4_wq_put(phba->sli4_hba.fcp_wq[piocb->fcp_wqidx],
                                     &wqe))
                        return IOCB_ERROR;
        } else {
+               if (unlikely(!phba->sli4_hba.els_wq))
+                       return IOCB_ERROR;
                if (lpfc_sli4_wq_put(phba->sli4_hba.els_wq, &wqe))
                        return IOCB_ERROR;
        }
@@ -10003,7 +10022,7 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba,
        retval = lpfc_sli_issue_iocb(phba, ring_number, piocb,
                                     SLI_IOCB_RET_IOCB);
        if (retval == IOCB_SUCCESS) {
-               timeout_req = timeout * HZ;
+               timeout_req = msecs_to_jiffies(timeout * 1000);
                timeleft = wait_event_timeout(done_q,
                                lpfc_chk_iocb_flg(phba, piocb, LPFC_IO_WAKE),
                                timeout_req);
@@ -10108,7 +10127,7 @@ lpfc_sli_issue_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq,
        if (retval == MBX_BUSY || retval == MBX_SUCCESS) {
                wait_event_interruptible_timeout(done_q,
                                pmboxq->mbox_flag & LPFC_MBX_WAKE,
-                               timeout * HZ);
+                               msecs_to_jiffies(timeout * 1000));
 
                spin_lock_irqsave(&phba->hbalock, flag);
                pmboxq->context1 = NULL;
@@ -12899,8 +12918,9 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq,
                }
                wq->db_regaddr = bar_memmap_p + db_offset;
                lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
-                               "3264 WQ[%d]: barset:x%x, offset:x%x\n",
-                               wq->queue_id, pci_barset, db_offset);
+                               "3264 WQ[%d]: barset:x%x, offset:x%x, "
+                               "format:x%x\n", wq->queue_id, pci_barset,
+                               db_offset, wq->db_format);
        } else {
                wq->db_format = LPFC_DB_LIST_FORMAT;
                wq->db_regaddr = phba->sli4_hba.WQDBregaddr;
@@ -13120,8 +13140,9 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq,
                }
                hrq->db_regaddr = bar_memmap_p + db_offset;
                lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
-                               "3266 RQ[qid:%d]: barset:x%x, offset:x%x\n",
-                               hrq->queue_id, pci_barset, db_offset);
+                               "3266 RQ[qid:%d]: barset:x%x, offset:x%x, "
+                               "format:x%x\n", hrq->queue_id, pci_barset,
+                               db_offset, hrq->db_format);
        } else {
                hrq->db_format = LPFC_DB_RING_FORMAT;
                hrq->db_regaddr = phba->sli4_hba.RQDBregaddr;
@@ -13971,13 +13992,14 @@ lpfc_fc_frame_check(struct lpfc_hba *phba, struct fc_frame_header *fc_hdr)
        }
 
        lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
-                       "2538 Received frame rctl:%s type:%s "
-                       "Frame Data:%08x %08x %08x %08x %08x %08x\n",
-                       rctl_names[fc_hdr->fh_r_ctl],
-                       type_names[fc_hdr->fh_type],
+                       "2538 Received frame rctl:%s (x%x), type:%s (x%x), "
+                       "frame Data:%08x %08x %08x %08x %08x %08x %08x\n",
+                       rctl_names[fc_hdr->fh_r_ctl], fc_hdr->fh_r_ctl,
+                       type_names[fc_hdr->fh_type], fc_hdr->fh_type,
                        be32_to_cpu(header[0]), be32_to_cpu(header[1]),
                        be32_to_cpu(header[2]), be32_to_cpu(header[3]),
-                       be32_to_cpu(header[4]), be32_to_cpu(header[5]));
+                       be32_to_cpu(header[4]), be32_to_cpu(header[5]),
+                       be32_to_cpu(header[6]));
        return 0;
 drop:
        lpfc_printf_log(phba, KERN_WARNING, LOG_ELS,
index be02b59..67af460 100644 (file)
@@ -346,11 +346,6 @@ struct lpfc_bmbx {
 #define SLI4_CT_VFI 2
 #define SLI4_CT_FCFI 3
 
-#define LPFC_SLI4_FL1_MAX_SEGMENT_SIZE 0x10000
-#define LPFC_SLI4_FL1_MAX_BUF_SIZE     0X2000
-#define LPFC_SLI4_MIN_BUF_SIZE         0x400
-#define LPFC_SLI4_MAX_BUF_SIZE         0x20000
-
 /*
  * SLI4 specific data structures
  */
@@ -440,6 +435,17 @@ struct lpfc_sli4_lnk_info {
 
 #define LPFC_SLI4_HANDLER_NAME_SZ      16
 
+/* Used for IRQ vector to CPU mapping */
+struct lpfc_vector_map_info {
+       uint16_t        phys_id;
+       uint16_t        core_id;
+       uint16_t        irq;
+       uint16_t        channel_id;
+       struct cpumask  maskbits;
+};
+#define LPFC_VECTOR_MAP_EMPTY  0xffff
+#define LPFC_MAX_CPU           256
+
 /* SLI4 HBA data structure entries */
 struct lpfc_sli4_hba {
        void __iomem *conf_regs_memmap_p; /* Kernel memory mapped address for
@@ -573,6 +579,11 @@ struct lpfc_sli4_hba {
        struct lpfc_iov iov;
        spinlock_t abts_scsi_buf_list_lock; /* list of aborted SCSI IOs */
        spinlock_t abts_sgl_list_lock; /* list of aborted els IOs */
+
+       /* CPU to vector mapping information */
+       struct lpfc_vector_map_info *cpu_map;
+       uint16_t num_online_cpu;
+       uint16_t num_present_cpu;
 };
 
 enum lpfc_sge_type {
index 664cd04..a38dc3b 100644 (file)
@@ -18,7 +18,7 @@
  * included with this package.                                     *
  *******************************************************************/
 
-#define LPFC_DRIVER_VERSION "8.3.38"
+#define LPFC_DRIVER_VERSION "8.3.39"
 #define LPFC_DRIVER_NAME               "lpfc"
 
 /* Used for SLI 2/3 */
index 0fe188e..e28e431 100644 (file)
@@ -80,7 +80,7 @@ inline void lpfc_vport_set_state(struct lpfc_vport *vport,
        }
 }
 
-static int
+int
 lpfc_alloc_vpi(struct lpfc_hba *phba)
 {
        unsigned long vpi;
@@ -568,6 +568,7 @@ lpfc_vport_delete(struct fc_vport *fc_vport)
        struct lpfc_vport *vport = *(struct lpfc_vport **)fc_vport->dd_data;
        struct lpfc_hba   *phba = vport->phba;
        long timeout;
+       bool ns_ndlp_referenced = false;
 
        if (vport->port_type == LPFC_PHYSICAL_PORT) {
                lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT,
@@ -628,6 +629,18 @@ lpfc_vport_delete(struct fc_vport *fc_vport)
 
        lpfc_debugfs_terminate(vport);
 
+       /*
+        * The call to fc_remove_host might release the NameServer ndlp. Since
+        * we might need to use the ndlp to send the DA_ID CT command,
+        * increment the reference for the NameServer ndlp to prevent it from
+        * being released.
+        */
+       ndlp = lpfc_findnode_did(vport, NameServer_DID);
+       if (ndlp && NLP_CHK_NODE_ACT(ndlp)) {
+               lpfc_nlp_get(ndlp);
+               ns_ndlp_referenced = true;
+       }
+
        /* Remove FC host and then SCSI host with the vport */
        fc_remove_host(lpfc_shost_from_vport(vport));
        scsi_remove_host(lpfc_shost_from_vport(vport));
@@ -734,6 +747,16 @@ lpfc_vport_delete(struct fc_vport *fc_vport)
                lpfc_discovery_wait(vport);
 
 skip_logo:
+
+       /*
+        * If the NameServer ndlp has been incremented to allow the DA_ID CT
+        * command to be sent, decrement the ndlp now.
+        */
+       if (ns_ndlp_referenced) {
+               ndlp = lpfc_findnode_did(vport, NameServer_DID);
+               lpfc_nlp_put(ndlp);
+       }
+
        lpfc_cleanup(vport);
        lpfc_sli_host_down(vport);
 
index 9082834..6b2c94e 100644 (file)
@@ -90,6 +90,7 @@ int lpfc_vport_getinfo(struct Scsi_Host *, struct vport_info *);
 int lpfc_vport_tgt_remove(struct Scsi_Host *, uint, uint);
 struct lpfc_vport **lpfc_create_vport_work_array(struct lpfc_hba *);
 void lpfc_destroy_vport_work_array(struct lpfc_hba *, struct lpfc_vport **);
+int lpfc_alloc_vpi(struct lpfc_hba *phba);
 
 /*
  *  queuecommand  VPORT-specific return codes. Specified in  the host byte code.
index 7c90d57..3a9ddae 100644 (file)
@@ -4931,11 +4931,12 @@ static int megasas_mgmt_ioctl_fw(struct file *file, unsigned long arg)
                printk(KERN_ERR "megaraid_sas: timed out while"
                        "waiting for HBA to recover\n");
                error = -ENODEV;
-               goto out_kfree_ioc;
+               goto out_up;
        }
        spin_unlock_irqrestore(&instance->hba_lock, flags);
 
        error = megasas_mgmt_fw_ioctl(instance, user_ioc, ioc);
+      out_up:
        up(&instance->ioctl_sem);
 
       out_kfree_ioc:
index 7455092..7b7381d 100644 (file)
@@ -254,7 +254,7 @@ static int mvs_alloc(struct mvs_info *mvi, struct Scsi_Host *shost)
        }
        for (i = 0; i < MVS_MAX_DEVICES; i++) {
                mvi->devices[i].taskfileset = MVS_ID_NOT_MAPPED;
-               mvi->devices[i].dev_type = NO_DEVICE;
+               mvi->devices[i].dev_type = SAS_PHY_UNUSED;
                mvi->devices[i].device_id = i;
                mvi->devices[i].dev_status = MVS_DEV_NORMAL;
                init_timer(&mvi->devices[i].timer);
index 532110f..c9e2449 100644 (file)
@@ -706,7 +706,7 @@ static int mvs_task_prep_ssp(struct mvs_info *mvi,
        return 0;
 }
 
-#define        DEV_IS_GONE(mvi_dev)    ((!mvi_dev || (mvi_dev->dev_type == NO_DEVICE)))
+#define        DEV_IS_GONE(mvi_dev)    ((!mvi_dev || (mvi_dev->dev_type == SAS_PHY_UNUSED)))
 static int mvs_task_prep(struct sas_task *task, struct mvs_info *mvi, int is_tmf,
                                struct mvs_tmf_task *tmf, int *pass)
 {
@@ -726,7 +726,7 @@ static int mvs_task_prep(struct sas_task *task, struct mvs_info *mvi, int is_tmf
                 * libsas will use dev->port, should
                 * not call task_done for sata
                 */
-               if (dev->dev_type != SATA_DEV)
+               if (dev->dev_type != SAS_SATA_DEV)
                        task->task_done(task);
                return rc;
        }
@@ -1159,10 +1159,10 @@ void mvs_update_phyinfo(struct mvs_info *mvi, int i, int get_st)
                        phy->identify.device_type =
                                phy->att_dev_info & PORT_DEV_TYPE_MASK;
 
-                       if (phy->identify.device_type == SAS_END_DEV)
+                       if (phy->identify.device_type == SAS_END_DEVICE)
                                phy->identify.target_port_protocols =
                                                        SAS_PROTOCOL_SSP;
-                       else if (phy->identify.device_type != NO_DEVICE)
+                       else if (phy->identify.device_type != SAS_PHY_UNUSED)
                                phy->identify.target_port_protocols =
                                                        SAS_PROTOCOL_SMP;
                        if (oob_done)
@@ -1260,7 +1260,7 @@ struct mvs_device *mvs_alloc_dev(struct mvs_info *mvi)
 {
        u32 dev;
        for (dev = 0; dev < MVS_MAX_DEVICES; dev++) {
-               if (mvi->devices[dev].dev_type == NO_DEVICE) {
+               if (mvi->devices[dev].dev_type == SAS_PHY_UNUSED) {
                        mvi->devices[dev].device_id = dev;
                        return &mvi->devices[dev];
                }
@@ -1278,7 +1278,7 @@ void mvs_free_dev(struct mvs_device *mvi_dev)
        u32 id = mvi_dev->device_id;
        memset(mvi_dev, 0, sizeof(*mvi_dev));
        mvi_dev->device_id = id;
-       mvi_dev->dev_type = NO_DEVICE;
+       mvi_dev->dev_type = SAS_PHY_UNUSED;
        mvi_dev->dev_status = MVS_DEV_NORMAL;
        mvi_dev->taskfileset = MVS_ID_NOT_MAPPED;
 }
@@ -1480,7 +1480,7 @@ static int mvs_debug_I_T_nexus_reset(struct domain_device *dev)
 {
        int rc;
        struct sas_phy *phy = sas_get_local_phy(dev);
-       int reset_type = (dev->dev_type == SATA_DEV ||
+       int reset_type = (dev->dev_type == SAS_SATA_DEV ||
                        (dev->tproto & SAS_PROTOCOL_STP)) ? 0 : 1;
        rc = sas_phy_reset(phy, reset_type);
        sas_put_local_phy(phy);
@@ -1629,7 +1629,7 @@ int mvs_abort_task(struct sas_task *task)
 
        } else if (task->task_proto & SAS_PROTOCOL_SATA ||
                task->task_proto & SAS_PROTOCOL_STP) {
-               if (SATA_DEV == dev->dev_type) {
+               if (SAS_SATA_DEV == dev->dev_type) {
                        struct mvs_slot_info *slot = task->lldd_task;
                        u32 slot_idx = (u32)(slot - mvi->slot_info);
                        mv_dprintk("mvs_abort_task() mvi=%p task=%p "
index 9f3cc13..60e2fb7 100644 (file)
@@ -67,7 +67,7 @@ extern const struct mvs_dispatch mvs_94xx_dispatch;
 extern struct kmem_cache *mvs_task_list_cache;
 
 #define DEV_IS_EXPANDER(type)  \
-       ((type == EDGE_DEV) || (type == FANOUT_DEV))
+       ((type == SAS_EDGE_EXPANDER_DEVICE) || (type == SAS_FANOUT_EXPANDER_DEVICE))
 
 #define bit(n) ((u64)1 << n)
 
@@ -241,7 +241,7 @@ struct mvs_phy {
 
 struct mvs_device {
        struct list_head                dev_entry;
-       enum sas_dev_type dev_type;
+       enum sas_device_type dev_type;
        struct mvs_info *mvi_info;
        struct domain_device *sas_device;
        struct timer_list timer;
index 52f0429..ce4cd87 100644 (file)
@@ -4,9 +4,10 @@
 # Copyright (C) 2008-2009  USI Co., Ltd.
 
 
-obj-$(CONFIG_SCSI_PM8001) += pm8001.o
-pm8001-y += pm8001_init.o \
+obj-$(CONFIG_SCSI_PM8001) += pm80xx.o
+pm80xx-y += pm8001_init.o \
                pm8001_sas.o  \
                pm8001_ctl.o  \
-               pm8001_hwi.o
+               pm8001_hwi.o  \
+               pm80xx_hwi.o
 
index 45bc197..d99f41c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * PMC-Sierra SPC 8001 SAS/SATA based host adapters driver
+ * PMC-Sierra 8001/8081/8088/8089 SAS/SATA based host adapters driver
  *
  * Copyright (c) 2008-2009 USI Co., Ltd.
  * All rights reserved.
@@ -58,8 +58,13 @@ static ssize_t pm8001_ctl_mpi_interface_rev_show(struct device *cdev,
        struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
        struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
 
-       return snprintf(buf, PAGE_SIZE, "%d\n",
-               pm8001_ha->main_cfg_tbl.interface_rev);
+       if (pm8001_ha->chip_id == chip_8001) {
+               return snprintf(buf, PAGE_SIZE, "%d\n",
+                       pm8001_ha->main_cfg_tbl.pm8001_tbl.interface_rev);
+       } else {
+               return snprintf(buf, PAGE_SIZE, "%d\n",
+                       pm8001_ha->main_cfg_tbl.pm80xx_tbl.interface_rev);
+       }
 }
 static
 DEVICE_ATTR(interface_rev, S_IRUGO, pm8001_ctl_mpi_interface_rev_show, NULL);
@@ -78,11 +83,19 @@ static ssize_t pm8001_ctl_fw_version_show(struct device *cdev,
        struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
        struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
 
-       return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n",
-                      (u8)(pm8001_ha->main_cfg_tbl.firmware_rev >> 24),
-                      (u8)(pm8001_ha->main_cfg_tbl.firmware_rev >> 16),
-                      (u8)(pm8001_ha->main_cfg_tbl.firmware_rev >> 8),
-                      (u8)(pm8001_ha->main_cfg_tbl.firmware_rev));
+       if (pm8001_ha->chip_id == chip_8001) {
+               return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n",
+               (u8)(pm8001_ha->main_cfg_tbl.pm8001_tbl.firmware_rev >> 24),
+               (u8)(pm8001_ha->main_cfg_tbl.pm8001_tbl.firmware_rev >> 16),
+               (u8)(pm8001_ha->main_cfg_tbl.pm8001_tbl.firmware_rev >> 8),
+               (u8)(pm8001_ha->main_cfg_tbl.pm8001_tbl.firmware_rev));
+       } else {
+               return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n",
+               (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.firmware_rev >> 24),
+               (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.firmware_rev >> 16),
+               (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.firmware_rev >> 8),
+               (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.firmware_rev));
+       }
 }
 static DEVICE_ATTR(fw_version, S_IRUGO, pm8001_ctl_fw_version_show, NULL);
 /**
@@ -99,8 +112,13 @@ static ssize_t pm8001_ctl_max_out_io_show(struct device *cdev,
        struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
        struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
 
-       return snprintf(buf, PAGE_SIZE, "%d\n",
-                       pm8001_ha->main_cfg_tbl.max_out_io);
+       if (pm8001_ha->chip_id == chip_8001) {
+               return snprintf(buf, PAGE_SIZE, "%d\n",
+                       pm8001_ha->main_cfg_tbl.pm8001_tbl.max_out_io);
+       } else {
+               return snprintf(buf, PAGE_SIZE, "%d\n",
+                       pm8001_ha->main_cfg_tbl.pm80xx_tbl.max_out_io);
+       }
 }
 static DEVICE_ATTR(max_out_io, S_IRUGO, pm8001_ctl_max_out_io_show, NULL);
 /**
@@ -117,8 +135,15 @@ static ssize_t pm8001_ctl_max_devices_show(struct device *cdev,
        struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
        struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
 
-       return snprintf(buf, PAGE_SIZE, "%04d\n",
-                       (u16)(pm8001_ha->main_cfg_tbl.max_sgl >> 16));
+       if (pm8001_ha->chip_id == chip_8001) {
+               return snprintf(buf, PAGE_SIZE, "%04d\n",
+                       (u16)(pm8001_ha->main_cfg_tbl.pm8001_tbl.max_sgl >> 16)
+                       );
+       } else {
+               return snprintf(buf, PAGE_SIZE, "%04d\n",
+                       (u16)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.max_sgl >> 16)
+                       );
+       }
 }
 static DEVICE_ATTR(max_devices, S_IRUGO, pm8001_ctl_max_devices_show, NULL);
 /**
@@ -136,8 +161,15 @@ static ssize_t pm8001_ctl_max_sg_list_show(struct device *cdev,
        struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
        struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
 
-       return snprintf(buf, PAGE_SIZE, "%04d\n",
-                       pm8001_ha->main_cfg_tbl.max_sgl & 0x0000FFFF);
+       if (pm8001_ha->chip_id == chip_8001) {
+               return snprintf(buf, PAGE_SIZE, "%04d\n",
+                       pm8001_ha->main_cfg_tbl.pm8001_tbl.max_sgl & 0x0000FFFF
+                       );
+       } else {
+               return snprintf(buf, PAGE_SIZE, "%04d\n",
+                       pm8001_ha->main_cfg_tbl.pm80xx_tbl.max_sgl & 0x0000FFFF
+                       );
+       }
 }
 static DEVICE_ATTR(max_sg_list, S_IRUGO, pm8001_ctl_max_sg_list_show, NULL);
 
@@ -173,7 +205,14 @@ static ssize_t pm8001_ctl_sas_spec_support_show(struct device *cdev,
        struct Scsi_Host *shost = class_to_shost(cdev);
        struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
        struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
-       mode = (pm8001_ha->main_cfg_tbl.ctrl_cap_flag & 0xfe000000)>>25;
+       /* fe000000 means supports SAS2.1 */
+       if (pm8001_ha->chip_id == chip_8001)
+               mode = (pm8001_ha->main_cfg_tbl.pm8001_tbl.ctrl_cap_flag &
+                                                       0xfe000000)>>25;
+       else
+               /* fe000000 means supports SAS2.1 */
+               mode = (pm8001_ha->main_cfg_tbl.pm80xx_tbl.ctrl_cap_flag &
+                                                       0xfe000000)>>25;
        return show_sas_spec_support_status(mode, buf);
 }
 static DEVICE_ATTR(sas_spec_support, S_IRUGO,
@@ -361,10 +400,11 @@ static int pm8001_set_nvmd(struct pm8001_hba_info *pm8001_ha)
                goto out;
        }
        payload = (struct pm8001_ioctl_payload *)ioctlbuffer;
-       memcpy((u8 *)payload->func_specific, (u8 *)pm8001_ha->fw_image->data,
+       memcpy((u8 *)&payload->func_specific, (u8 *)pm8001_ha->fw_image->data,
                                pm8001_ha->fw_image->size);
        payload->length = pm8001_ha->fw_image->size;
        payload->id = 0;
+       payload->minor_function = 0x1;
        pm8001_ha->nvmd_completion = &completion;
        ret = PM8001_CHIP_DISP->set_nvmd_req(pm8001_ha, payload);
        wait_for_completion(&completion);
@@ -411,7 +451,7 @@ static int pm8001_update_flash(struct pm8001_hba_info *pm8001_ha)
                        payload->length = 1024*16;
                        payload->id = 0;
                        fwControl =
-                             (struct fw_control_info *)payload->func_specific;
+                             (struct fw_control_info *)&payload->func_specific;
                        fwControl->len = IOCTL_BUF_SIZE;   /* IN */
                        fwControl->size = partitionSize + HEADER_LEN;/* IN */
                        fwControl->retcode = 0;/* OUT */
index c3d20c8..479c5a7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * PMC-Sierra SPC 8001 SAS/SATA based host adapters driver
+ * PMC-Sierra 8001/8081/8088/8089 SAS/SATA based host adapters driver
  *
  * Copyright (c) 2008-2009 USI Co., Ltd.
  * All rights reserved.
 
 enum chip_flavors {
        chip_8001,
+       chip_8008,
+       chip_8009,
+       chip_8018,
+       chip_8019
 };
-#define USI_MAX_MEMCNT                 9
-#define PM8001_MAX_DMA_SG              SG_ALL
+
 enum phy_speed {
        PHY_SPEED_15 = 0x01,
        PHY_SPEED_30 = 0x02,
@@ -69,23 +72,34 @@ enum port_type {
 #define PM8001_MPI_QUEUE         1024   /* maximum mpi queue entries */
 #define        PM8001_MAX_INB_NUM       1
 #define        PM8001_MAX_OUTB_NUM      1
+#define        PM8001_MAX_SPCV_INB_NUM         1
+#define        PM8001_MAX_SPCV_OUTB_NUM        4
 #define        PM8001_CAN_QUEUE         508    /* SCSI Queue depth */
 
+/* Inbound/Outbound queue size */
+#define IOMB_SIZE_SPC          64
+#define IOMB_SIZE_SPCV         128
+
 /* unchangeable hardware details */
-#define        PM8001_MAX_PHYS          8      /* max. possible phys */
-#define        PM8001_MAX_PORTS         8      /* max. possible ports */
-#define        PM8001_MAX_DEVICES       1024   /* max supported device */
+#define        PM8001_MAX_PHYS          16     /* max. possible phys */
+#define        PM8001_MAX_PORTS         16     /* max. possible ports */
+#define        PM8001_MAX_DEVICES       2048   /* max supported device */
+#define        PM8001_MAX_MSIX_VEC      64     /* max msi-x int for spcv/ve */
 
+#define USI_MAX_MEMCNT_BASE    5
+#define IB                     (USI_MAX_MEMCNT_BASE + 1)
+#define CI                     (IB + PM8001_MAX_SPCV_INB_NUM)
+#define OB                     (CI + PM8001_MAX_SPCV_INB_NUM)
+#define PI                     (OB + PM8001_MAX_SPCV_OUTB_NUM)
+#define USI_MAX_MEMCNT         (PI + PM8001_MAX_SPCV_OUTB_NUM)
+#define PM8001_MAX_DMA_SG      SG_ALL
 enum memory_region_num {
        AAP1 = 0x0, /* application acceleration processor */
        IOP,        /* IO processor */
-       CI,         /* consumer index */
-       PI,         /* producer index */
-       IB,         /* inbound queue */
-       OB,         /* outbound queue */
        NVMD,       /* NVM device */
        DEV_MEM,    /* memory for devices */
        CCB_MEM,    /* memory for command control block */
+       FW_FLASH    /* memory for fw flash update */
 };
 #define        PM8001_EVENT_LOG_SIZE    (128 * 1024)
 
index b8dd050..69dd49c 100644 (file)
 static void read_main_config_table(struct pm8001_hba_info *pm8001_ha)
 {
        void __iomem *address = pm8001_ha->main_cfg_tbl_addr;
-       pm8001_ha->main_cfg_tbl.signature       = pm8001_mr32(address, 0x00);
-       pm8001_ha->main_cfg_tbl.interface_rev   = pm8001_mr32(address, 0x04);
-       pm8001_ha->main_cfg_tbl.firmware_rev    = pm8001_mr32(address, 0x08);
-       pm8001_ha->main_cfg_tbl.max_out_io      = pm8001_mr32(address, 0x0C);
-       pm8001_ha->main_cfg_tbl.max_sgl         = pm8001_mr32(address, 0x10);
-       pm8001_ha->main_cfg_tbl.ctrl_cap_flag   = pm8001_mr32(address, 0x14);
-       pm8001_ha->main_cfg_tbl.gst_offset      = pm8001_mr32(address, 0x18);
-       pm8001_ha->main_cfg_tbl.inbound_queue_offset =
+       pm8001_ha->main_cfg_tbl.pm8001_tbl.signature    =
+                               pm8001_mr32(address, 0x00);
+       pm8001_ha->main_cfg_tbl.pm8001_tbl.interface_rev =
+                               pm8001_mr32(address, 0x04);
+       pm8001_ha->main_cfg_tbl.pm8001_tbl.firmware_rev =
+                               pm8001_mr32(address, 0x08);
+       pm8001_ha->main_cfg_tbl.pm8001_tbl.max_out_io   =
+                               pm8001_mr32(address, 0x0C);
+       pm8001_ha->main_cfg_tbl.pm8001_tbl.max_sgl      =
+                               pm8001_mr32(address, 0x10);
+       pm8001_ha->main_cfg_tbl.pm8001_tbl.ctrl_cap_flag =
+                               pm8001_mr32(address, 0x14);
+       pm8001_ha->main_cfg_tbl.pm8001_tbl.gst_offset   =
+                               pm8001_mr32(address, 0x18);
+       pm8001_ha->main_cfg_tbl.pm8001_tbl.inbound_queue_offset =
                pm8001_mr32(address, MAIN_IBQ_OFFSET);
-       pm8001_ha->main_cfg_tbl.outbound_queue_offset =
+       pm8001_ha->main_cfg_tbl.pm8001_tbl.outbound_queue_offset =
                pm8001_mr32(address, MAIN_OBQ_OFFSET);
-       pm8001_ha->main_cfg_tbl.hda_mode_flag   =
+       pm8001_ha->main_cfg_tbl.pm8001_tbl.hda_mode_flag        =
                pm8001_mr32(address, MAIN_HDA_FLAGS_OFFSET);
 
        /* read analog Setting offset from the configuration table */
-       pm8001_ha->main_cfg_tbl.anolog_setup_table_offset =
+       pm8001_ha->main_cfg_tbl.pm8001_tbl.anolog_setup_table_offset =
                pm8001_mr32(address, MAIN_ANALOG_SETUP_OFFSET);
 
        /* read Error Dump Offset and Length */
-       pm8001_ha->main_cfg_tbl.fatal_err_dump_offset0 =
+       pm8001_ha->main_cfg_tbl.pm8001_tbl.fatal_err_dump_offset0 =
                pm8001_mr32(address, MAIN_FATAL_ERROR_RDUMP0_OFFSET);
-       pm8001_ha->main_cfg_tbl.fatal_err_dump_length0 =
+       pm8001_ha->main_cfg_tbl.pm8001_tbl.fatal_err_dump_length0 =
                pm8001_mr32(address, MAIN_FATAL_ERROR_RDUMP0_LENGTH);
-       pm8001_ha->main_cfg_tbl.fatal_err_dump_offset1 =
+       pm8001_ha->main_cfg_tbl.pm8001_tbl.fatal_err_dump_offset1 =
                pm8001_mr32(address, MAIN_FATAL_ERROR_RDUMP1_OFFSET);
-       pm8001_ha->main_cfg_tbl.fatal_err_dump_length1 =
+       pm8001_ha->main_cfg_tbl.pm8001_tbl.fatal_err_dump_length1 =
                pm8001_mr32(address, MAIN_FATAL_ERROR_RDUMP1_LENGTH);
 }
 
@@ -86,31 +93,56 @@ static void read_main_config_table(struct pm8001_hba_info *pm8001_ha)
 static void read_general_status_table(struct pm8001_hba_info *pm8001_ha)
 {
        void __iomem *address = pm8001_ha->general_stat_tbl_addr;
-       pm8001_ha->gs_tbl.gst_len_mpistate      = pm8001_mr32(address, 0x00);
-       pm8001_ha->gs_tbl.iq_freeze_state0      = pm8001_mr32(address, 0x04);
-       pm8001_ha->gs_tbl.iq_freeze_state1      = pm8001_mr32(address, 0x08);
-       pm8001_ha->gs_tbl.msgu_tcnt             = pm8001_mr32(address, 0x0C);
-       pm8001_ha->gs_tbl.iop_tcnt              = pm8001_mr32(address, 0x10);
-       pm8001_ha->gs_tbl.reserved              = pm8001_mr32(address, 0x14);
-       pm8001_ha->gs_tbl.phy_state[0]  = pm8001_mr32(address, 0x18);
-       pm8001_ha->gs_tbl.phy_state[1]  = pm8001_mr32(address, 0x1C);
-       pm8001_ha->gs_tbl.phy_state[2]  = pm8001_mr32(address, 0x20);
-       pm8001_ha->gs_tbl.phy_state[3]  = pm8001_mr32(address, 0x24);
-       pm8001_ha->gs_tbl.phy_state[4]  = pm8001_mr32(address, 0x28);
-       pm8001_ha->gs_tbl.phy_state[5]  = pm8001_mr32(address, 0x2C);
-       pm8001_ha->gs_tbl.phy_state[6]  = pm8001_mr32(address, 0x30);
-       pm8001_ha->gs_tbl.phy_state[7]  = pm8001_mr32(address, 0x34);
-       pm8001_ha->gs_tbl.reserved1             = pm8001_mr32(address, 0x38);
-       pm8001_ha->gs_tbl.reserved2             = pm8001_mr32(address, 0x3C);
-       pm8001_ha->gs_tbl.reserved3             = pm8001_mr32(address, 0x40);
-       pm8001_ha->gs_tbl.recover_err_info[0]   = pm8001_mr32(address, 0x44);
-       pm8001_ha->gs_tbl.recover_err_info[1]   = pm8001_mr32(address, 0x48);
-       pm8001_ha->gs_tbl.recover_err_info[2]   = pm8001_mr32(address, 0x4C);
-       pm8001_ha->gs_tbl.recover_err_info[3]   = pm8001_mr32(address, 0x50);
-       pm8001_ha->gs_tbl.recover_err_info[4]   = pm8001_mr32(address, 0x54);
-       pm8001_ha->gs_tbl.recover_err_info[5]   = pm8001_mr32(address, 0x58);
-       pm8001_ha->gs_tbl.recover_err_info[6]   = pm8001_mr32(address, 0x5C);
-       pm8001_ha->gs_tbl.recover_err_info[7]   = pm8001_mr32(address, 0x60);
+       pm8001_ha->gs_tbl.pm8001_tbl.gst_len_mpistate   =
+                               pm8001_mr32(address, 0x00);
+       pm8001_ha->gs_tbl.pm8001_tbl.iq_freeze_state0   =
+                               pm8001_mr32(address, 0x04);
+       pm8001_ha->gs_tbl.pm8001_tbl.iq_freeze_state1   =
+                               pm8001_mr32(address, 0x08);
+       pm8001_ha->gs_tbl.pm8001_tbl.msgu_tcnt          =
+                               pm8001_mr32(address, 0x0C);
+       pm8001_ha->gs_tbl.pm8001_tbl.iop_tcnt           =
+                               pm8001_mr32(address, 0x10);
+       pm8001_ha->gs_tbl.pm8001_tbl.rsvd               =
+                               pm8001_mr32(address, 0x14);
+       pm8001_ha->gs_tbl.pm8001_tbl.phy_state[0]       =
+                               pm8001_mr32(address, 0x18);
+       pm8001_ha->gs_tbl.pm8001_tbl.phy_state[1]       =
+                               pm8001_mr32(address, 0x1C);
+       pm8001_ha->gs_tbl.pm8001_tbl.phy_state[2]       =
+                               pm8001_mr32(address, 0x20);
+       pm8001_ha->gs_tbl.pm8001_tbl.phy_state[3]       =
+                               pm8001_mr32(address, 0x24);
+       pm8001_ha->gs_tbl.pm8001_tbl.phy_state[4]       =
+                               pm8001_mr32(address, 0x28);
+       pm8001_ha->gs_tbl.pm8001_tbl.phy_state[5]       =
+                               pm8001_mr32(address, 0x2C);
+       pm8001_ha->gs_tbl.pm8001_tbl.phy_state[6]       =
+                               pm8001_mr32(address, 0x30);
+       pm8001_ha->gs_tbl.pm8001_tbl.phy_state[7]       =
+                               pm8001_mr32(address, 0x34);
+       pm8001_ha->gs_tbl.pm8001_tbl.gpio_input_val     =
+                               pm8001_mr32(address, 0x38);
+       pm8001_ha->gs_tbl.pm8001_tbl.rsvd1[0]           =
+                               pm8001_mr32(address, 0x3C);
+       pm8001_ha->gs_tbl.pm8001_tbl.rsvd1[1]           =
+                               pm8001_mr32(address, 0x40);
+       pm8001_ha->gs_tbl.pm8001_tbl.recover_err_info[0]        =
+                               pm8001_mr32(address, 0x44);
+       pm8001_ha->gs_tbl.pm8001_tbl.recover_err_info[1]        =
+                               pm8001_mr32(address, 0x48);
+       pm8001_ha->gs_tbl.pm8001_tbl.recover_err_info[2]        =
+                               pm8001_mr32(address, 0x4C);
+       pm8001_ha->gs_tbl.pm8001_tbl.recover_err_info[3]        =
+                               pm8001_mr32(address, 0x50);
+       pm8001_ha->gs_tbl.pm8001_tbl.recover_err_info[4]        =
+                               pm8001_mr32(address, 0x54);
+       pm8001_ha->gs_tbl.pm8001_tbl.recover_err_info[5]        =
+                               pm8001_mr32(address, 0x58);
+       pm8001_ha->gs_tbl.pm8001_tbl.recover_err_info[6]        =
+                               pm8001_mr32(address, 0x5C);
+       pm8001_ha->gs_tbl.pm8001_tbl.recover_err_info[7]        =
+                               pm8001_mr32(address, 0x60);
 }
 
 /**
@@ -119,10 +151,9 @@ static void read_general_status_table(struct pm8001_hba_info *pm8001_ha)
  */
 static void read_inbnd_queue_table(struct pm8001_hba_info *pm8001_ha)
 {
-       int inbQ_num = 1;
        int i;
        void __iomem *address = pm8001_ha->inbnd_q_tbl_addr;
-       for (i = 0; i < inbQ_num; i++) {
+       for (i = 0; i < PM8001_MAX_INB_NUM; i++) {
                u32 offset = i * 0x20;
                pm8001_ha->inbnd_q_tbl[i].pi_pci_bar =
                      get_pci_bar_index(pm8001_mr32(address, (offset + 0x14)));
@@ -137,10 +168,9 @@ static void read_inbnd_queue_table(struct pm8001_hba_info *pm8001_ha)
  */
 static void read_outbnd_queue_table(struct pm8001_hba_info *pm8001_ha)
 {
-       int outbQ_num = 1;
        int i;
        void __iomem *address = pm8001_ha->outbnd_q_tbl_addr;
-       for (i = 0; i < outbQ_num; i++) {
+       for (i = 0; i < PM8001_MAX_OUTB_NUM; i++) {
                u32 offset = i * 0x24;
                pm8001_ha->outbnd_q_tbl[i].ci_pci_bar =
                      get_pci_bar_index(pm8001_mr32(address, (offset + 0x14)));
@@ -155,54 +185,57 @@ static void read_outbnd_queue_table(struct pm8001_hba_info *pm8001_ha)
  */
 static void init_default_table_values(struct pm8001_hba_info *pm8001_ha)
 {
-       int qn = 1;
        int i;
        u32 offsetib, offsetob;
        void __iomem *addressib = pm8001_ha->inbnd_q_tbl_addr;
        void __iomem *addressob = pm8001_ha->outbnd_q_tbl_addr;
 
-       pm8001_ha->main_cfg_tbl.inbound_q_nppd_hppd                     = 0;
-       pm8001_ha->main_cfg_tbl.outbound_hw_event_pid0_3                = 0;
-       pm8001_ha->main_cfg_tbl.outbound_hw_event_pid4_7                = 0;
-       pm8001_ha->main_cfg_tbl.outbound_ncq_event_pid0_3               = 0;
-       pm8001_ha->main_cfg_tbl.outbound_ncq_event_pid4_7               = 0;
-       pm8001_ha->main_cfg_tbl.outbound_tgt_ITNexus_event_pid0_3       = 0;
-       pm8001_ha->main_cfg_tbl.outbound_tgt_ITNexus_event_pid4_7       = 0;
-       pm8001_ha->main_cfg_tbl.outbound_tgt_ssp_event_pid0_3   = 0;
-       pm8001_ha->main_cfg_tbl.outbound_tgt_ssp_event_pid4_7   = 0;
-       pm8001_ha->main_cfg_tbl.outbound_tgt_smp_event_pid0_3   = 0;
-       pm8001_ha->main_cfg_tbl.outbound_tgt_smp_event_pid4_7   = 0;
-
-       pm8001_ha->main_cfg_tbl.upper_event_log_addr            =
+       pm8001_ha->main_cfg_tbl.pm8001_tbl.inbound_q_nppd_hppd          = 0;
+       pm8001_ha->main_cfg_tbl.pm8001_tbl.outbound_hw_event_pid0_3     = 0;
+       pm8001_ha->main_cfg_tbl.pm8001_tbl.outbound_hw_event_pid4_7     = 0;
+       pm8001_ha->main_cfg_tbl.pm8001_tbl.outbound_ncq_event_pid0_3    = 0;
+       pm8001_ha->main_cfg_tbl.pm8001_tbl.outbound_ncq_event_pid4_7    = 0;
+       pm8001_ha->main_cfg_tbl.pm8001_tbl.outbound_tgt_ITNexus_event_pid0_3 =
+                                                                        0;
+       pm8001_ha->main_cfg_tbl.pm8001_tbl.outbound_tgt_ITNexus_event_pid4_7 =
+                                                                        0;
+       pm8001_ha->main_cfg_tbl.pm8001_tbl.outbound_tgt_ssp_event_pid0_3 = 0;
+       pm8001_ha->main_cfg_tbl.pm8001_tbl.outbound_tgt_ssp_event_pid4_7 = 0;
+       pm8001_ha->main_cfg_tbl.pm8001_tbl.outbound_tgt_smp_event_pid0_3 = 0;
+       pm8001_ha->main_cfg_tbl.pm8001_tbl.outbound_tgt_smp_event_pid4_7 = 0;
+
+       pm8001_ha->main_cfg_tbl.pm8001_tbl.upper_event_log_addr         =
                pm8001_ha->memoryMap.region[AAP1].phys_addr_hi;
-       pm8001_ha->main_cfg_tbl.lower_event_log_addr            =
+       pm8001_ha->main_cfg_tbl.pm8001_tbl.lower_event_log_addr         =
                pm8001_ha->memoryMap.region[AAP1].phys_addr_lo;
-       pm8001_ha->main_cfg_tbl.event_log_size  = PM8001_EVENT_LOG_SIZE;
-       pm8001_ha->main_cfg_tbl.event_log_option                = 0x01;
-       pm8001_ha->main_cfg_tbl.upper_iop_event_log_addr        =
+       pm8001_ha->main_cfg_tbl.pm8001_tbl.event_log_size               =
+               PM8001_EVENT_LOG_SIZE;
+       pm8001_ha->main_cfg_tbl.pm8001_tbl.event_log_option             = 0x01;
+       pm8001_ha->main_cfg_tbl.pm8001_tbl.upper_iop_event_log_addr     =
                pm8001_ha->memoryMap.region[IOP].phys_addr_hi;
-       pm8001_ha->main_cfg_tbl.lower_iop_event_log_addr        =
+       pm8001_ha->main_cfg_tbl.pm8001_tbl.lower_iop_event_log_addr     =
                pm8001_ha->memoryMap.region[IOP].phys_addr_lo;
-       pm8001_ha->main_cfg_tbl.iop_event_log_size      = PM8001_EVENT_LOG_SIZE;
-       pm8001_ha->main_cfg_tbl.iop_event_log_option            = 0x01;
-       pm8001_ha->main_cfg_tbl.fatal_err_interrupt             = 0x01;
-       for (i = 0; i < qn; i++) {
+       pm8001_ha->main_cfg_tbl.pm8001_tbl.iop_event_log_size           =
+               PM8001_EVENT_LOG_SIZE;
+       pm8001_ha->main_cfg_tbl.pm8001_tbl.iop_event_log_option         = 0x01;
+       pm8001_ha->main_cfg_tbl.pm8001_tbl.fatal_err_interrupt          = 0x01;
+       for (i = 0; i < PM8001_MAX_INB_NUM; i++) {
                pm8001_ha->inbnd_q_tbl[i].element_pri_size_cnt  =
                        PM8001_MPI_QUEUE | (64 << 16) | (0x00<<30);
                pm8001_ha->inbnd_q_tbl[i].upper_base_addr       =
-                       pm8001_ha->memoryMap.region[IB].phys_addr_hi;
+                       pm8001_ha->memoryMap.region[IB + i].phys_addr_hi;
                pm8001_ha->inbnd_q_tbl[i].lower_base_addr       =
-               pm8001_ha->memoryMap.region[IB].phys_addr_lo;
+               pm8001_ha->memoryMap.region[IB + i].phys_addr_lo;
                pm8001_ha->inbnd_q_tbl[i].base_virt             =
-                       (u8 *)pm8001_ha->memoryMap.region[IB].virt_ptr;
+                       (u8 *)pm8001_ha->memoryMap.region[IB + i].virt_ptr;
                pm8001_ha->inbnd_q_tbl[i].total_length          =
-                       pm8001_ha->memoryMap.region[IB].total_len;
+                       pm8001_ha->memoryMap.region[IB + i].total_len;
                pm8001_ha->inbnd_q_tbl[i].ci_upper_base_addr    =
-                       pm8001_ha->memoryMap.region[CI].phys_addr_hi;
+                       pm8001_ha->memoryMap.region[CI + i].phys_addr_hi;
                pm8001_ha->inbnd_q_tbl[i].ci_lower_base_addr    =
-                       pm8001_ha->memoryMap.region[CI].phys_addr_lo;
+                       pm8001_ha->memoryMap.region[CI + i].phys_addr_lo;
                pm8001_ha->inbnd_q_tbl[i].ci_virt               =
-                       pm8001_ha->memoryMap.region[CI].virt_ptr;
+                       pm8001_ha->memoryMap.region[CI + i].virt_ptr;
                offsetib = i * 0x20;
                pm8001_ha->inbnd_q_tbl[i].pi_pci_bar            =
                        get_pci_bar_index(pm8001_mr32(addressib,
@@ -212,25 +245,25 @@ static void init_default_table_values(struct pm8001_hba_info *pm8001_ha)
                pm8001_ha->inbnd_q_tbl[i].producer_idx          = 0;
                pm8001_ha->inbnd_q_tbl[i].consumer_index        = 0;
        }
-       for (i = 0; i < qn; i++) {
+       for (i = 0; i < PM8001_MAX_OUTB_NUM; i++) {
                pm8001_ha->outbnd_q_tbl[i].element_size_cnt     =
                        PM8001_MPI_QUEUE | (64 << 16) | (0x01<<30);
                pm8001_ha->outbnd_q_tbl[i].upper_base_addr      =
-                       pm8001_ha->memoryMap.region[OB].phys_addr_hi;
+                       pm8001_ha->memoryMap.region[OB + i].phys_addr_hi;
                pm8001_ha->outbnd_q_tbl[i].lower_base_addr      =
-                       pm8001_ha->memoryMap.region[OB].phys_addr_lo;
+                       pm8001_ha->memoryMap.region[OB + i].phys_addr_lo;
                pm8001_ha->outbnd_q_tbl[i].base_virt            =
-                       (u8 *)pm8001_ha->memoryMap.region[OB].virt_ptr;
+                       (u8 *)pm8001_ha->memoryMap.region[OB + i].virt_ptr;
                pm8001_ha->outbnd_q_tbl[i].total_length         =
-                       pm8001_ha->memoryMap.region[OB].total_len;
+                       pm8001_ha->memoryMap.region[OB + i].total_len;
                pm8001_ha->outbnd_q_tbl[i].pi_upper_base_addr   =
-                       pm8001_ha->memoryMap.region[PI].phys_addr_hi;
+                       pm8001_ha->memoryMap.region[PI + i].phys_addr_hi;
                pm8001_ha->outbnd_q_tbl[i].pi_lower_base_addr   =
-                       pm8001_ha->memoryMap.region[PI].phys_addr_lo;
+                       pm8001_ha->memoryMap.region[PI + i].phys_addr_lo;
                pm8001_ha->outbnd_q_tbl[i].interrup_vec_cnt_delay       =
-                       0 | (10 << 16) | (0 << 24);
+                       0 | (10 << 16) | (i << 24);
                pm8001_ha->outbnd_q_tbl[i].pi_virt              =
-                       pm8001_ha->memoryMap.region[PI].virt_ptr;
+                       pm8001_ha->memoryMap.region[PI + i].virt_ptr;
                offsetob = i * 0x24;
                pm8001_ha->outbnd_q_tbl[i].ci_pci_bar           =
                        get_pci_bar_index(pm8001_mr32(addressob,
@@ -250,42 +283,51 @@ static void update_main_config_table(struct pm8001_hba_info *pm8001_ha)
 {
        void __iomem *address = pm8001_ha->main_cfg_tbl_addr;
        pm8001_mw32(address, 0x24,
-               pm8001_ha->main_cfg_tbl.inbound_q_nppd_hppd);
+               pm8001_ha->main_cfg_tbl.pm8001_tbl.inbound_q_nppd_hppd);
        pm8001_mw32(address, 0x28,
-               pm8001_ha->main_cfg_tbl.outbound_hw_event_pid0_3);
+               pm8001_ha->main_cfg_tbl.pm8001_tbl.outbound_hw_event_pid0_3);
        pm8001_mw32(address, 0x2C,
-               pm8001_ha->main_cfg_tbl.outbound_hw_event_pid4_7);
+               pm8001_ha->main_cfg_tbl.pm8001_tbl.outbound_hw_event_pid4_7);
        pm8001_mw32(address, 0x30,
-               pm8001_ha->main_cfg_tbl.outbound_ncq_event_pid0_3);
+               pm8001_ha->main_cfg_tbl.pm8001_tbl.outbound_ncq_event_pid0_3);
        pm8001_mw32(address, 0x34,
-               pm8001_ha->main_cfg_tbl.outbound_ncq_event_pid4_7);
+               pm8001_ha->main_cfg_tbl.pm8001_tbl.outbound_ncq_event_pid4_7);
        pm8001_mw32(address, 0x38,
-               pm8001_ha->main_cfg_tbl.outbound_tgt_ITNexus_event_pid0_3);
+               pm8001_ha->main_cfg_tbl.pm8001_tbl.
+                                       outbound_tgt_ITNexus_event_pid0_3);
        pm8001_mw32(address, 0x3C,
-               pm8001_ha->main_cfg_tbl.outbound_tgt_ITNexus_event_pid4_7);
+               pm8001_ha->main_cfg_tbl.pm8001_tbl.
+                                       outbound_tgt_ITNexus_event_pid4_7);
        pm8001_mw32(address, 0x40,
-               pm8001_ha->main_cfg_tbl.outbound_tgt_ssp_event_pid0_3);
+               pm8001_ha->main_cfg_tbl.pm8001_tbl.
+                                       outbound_tgt_ssp_event_pid0_3);
        pm8001_mw32(address, 0x44,
-               pm8001_ha->main_cfg_tbl.outbound_tgt_ssp_event_pid4_7);
+               pm8001_ha->main_cfg_tbl.pm8001_tbl.
+                                       outbound_tgt_ssp_event_pid4_7);
        pm8001_mw32(address, 0x48,
-               pm8001_ha->main_cfg_tbl.outbound_tgt_smp_event_pid0_3);
+               pm8001_ha->main_cfg_tbl.pm8001_tbl.
+                                       outbound_tgt_smp_event_pid0_3);
        pm8001_mw32(address, 0x4C,
-               pm8001_ha->main_cfg_tbl.outbound_tgt_smp_event_pid4_7);
+               pm8001_ha->main_cfg_tbl.pm8001_tbl.
+                                       outbound_tgt_smp_event_pid4_7);
        pm8001_mw32(address, 0x50,
-               pm8001_ha->main_cfg_tbl.upper_event_log_addr);
+               pm8001_ha->main_cfg_tbl.pm8001_tbl.upper_event_log_addr);
        pm8001_mw32(address, 0x54,
-               pm8001_ha->main_cfg_tbl.lower_event_log_addr);
-       pm8001_mw32(address, 0x58, pm8001_ha->main_cfg_tbl.event_log_size);
-       pm8001_mw32(address, 0x5C, pm8001_ha->main_cfg_tbl.event_log_option);
+               pm8001_ha->main_cfg_tbl.pm8001_tbl.lower_event_log_addr);
+       pm8001_mw32(address, 0x58,
+               pm8001_ha->main_cfg_tbl.pm8001_tbl.event_log_size);
+       pm8001_mw32(address, 0x5C,
+               pm8001_ha->main_cfg_tbl.pm8001_tbl.event_log_option);
        pm8001_mw32(address, 0x60,
-               pm8001_ha->main_cfg_tbl.upper_iop_event_log_addr);
+               pm8001_ha->main_cfg_tbl.pm8001_tbl.upper_iop_event_log_addr);
        pm8001_mw32(address, 0x64,
-               pm8001_ha->main_cfg_tbl.lower_iop_event_log_addr);
-       pm8001_mw32(address, 0x68, pm8001_ha->main_cfg_tbl.iop_event_log_size);
+               pm8001_ha->main_cfg_tbl.pm8001_tbl.lower_iop_event_log_addr);
+       pm8001_mw32(address, 0x68,
+               pm8001_ha->main_cfg_tbl.pm8001_tbl.iop_event_log_size);
        pm8001_mw32(address, 0x6C,
-               pm8001_ha->main_cfg_tbl.iop_event_log_option);
+               pm8001_ha->main_cfg_tbl.pm8001_tbl.iop_event_log_option);
        pm8001_mw32(address, 0x70,
-               pm8001_ha->main_cfg_tbl.fatal_err_interrupt);
+               pm8001_ha->main_cfg_tbl.pm8001_tbl.fatal_err_interrupt);
 }
 
 /**
@@ -597,6 +639,19 @@ static void init_pci_device_addresses(struct pm8001_hba_info *pm8001_ha)
  */
 static int pm8001_chip_init(struct pm8001_hba_info *pm8001_ha)
 {
+       u8 i = 0;
+       u16 deviceid;
+       pci_read_config_word(pm8001_ha->pdev, PCI_DEVICE_ID, &deviceid);
+       /* 8081 controllers need BAR shift to access MPI space
+       * as this is shared with BIOS data */
+       if (deviceid == 0x8081) {
+               if (-1 == pm8001_bar4_shift(pm8001_ha, GSM_SM_BASE)) {
+                       PM8001_FAIL_DBG(pm8001_ha,
+                               pm8001_printk("Shift Bar4 to 0x%x failed\n",
+                                       GSM_SM_BASE));
+                       return -1;
+               }
+       }
        /* check the firmware status */
        if (-1 == check_fw_ready(pm8001_ha)) {
                PM8001_FAIL_DBG(pm8001_ha,
@@ -613,11 +668,16 @@ static int pm8001_chip_init(struct pm8001_hba_info *pm8001_ha)
        read_outbnd_queue_table(pm8001_ha);
        /* update main config table ,inbound table and outbound table */
        update_main_config_table(pm8001_ha);
-       update_inbnd_queue_table(pm8001_ha, 0);
-       update_outbnd_queue_table(pm8001_ha, 0);
-       mpi_set_phys_g3_with_ssc(pm8001_ha, 0);
-       /* 7->130ms, 34->500ms, 119->1.5s */
-       mpi_set_open_retry_interval_reg(pm8001_ha, 119);
+       for (i = 0; i < PM8001_MAX_INB_NUM; i++)
+               update_inbnd_queue_table(pm8001_ha, i);
+       for (i = 0; i < PM8001_MAX_OUTB_NUM; i++)
+               update_outbnd_queue_table(pm8001_ha, i);
+       /* 8081 controller donot require these operations */
+       if (deviceid != 0x8081) {
+               mpi_set_phys_g3_with_ssc(pm8001_ha, 0);
+               /* 7->130ms, 34->500ms, 119->1.5s */
+               mpi_set_open_retry_interval_reg(pm8001_ha, 119);
+       }
        /* notify firmware update finished and check initialization status */
        if (0 == mpi_init_check(pm8001_ha)) {
                PM8001_INIT_DBG(pm8001_ha,
@@ -639,6 +699,16 @@ static int mpi_uninit_check(struct pm8001_hba_info *pm8001_ha)
        u32 max_wait_count;
        u32 value;
        u32 gst_len_mpistate;
+       u16 deviceid;
+       pci_read_config_word(pm8001_ha->pdev, PCI_DEVICE_ID, &deviceid);
+       if (deviceid == 0x8081) {
+               if (-1 == pm8001_bar4_shift(pm8001_ha, GSM_SM_BASE)) {
+                       PM8001_FAIL_DBG(pm8001_ha,
+                               pm8001_printk("Shift Bar4 to 0x%x failed\n",
+                                       GSM_SM_BASE));
+                       return -1;
+               }
+       }
        init_pci_device_addresses(pm8001_ha);
        /* Write bit1=1 to Inbound DoorBell Register to tell the SPC FW the
        table is stop */
@@ -740,14 +810,14 @@ static u32 soft_reset_ready_check(struct pm8001_hba_info *pm8001_ha)
  * pm8001_chip_soft_rst - soft reset the PM8001 chip, so that the clear all
  * the FW register status to the originated status.
  * @pm8001_ha: our hba card information
- * @signature: signature in host scratch pad0 register.
  */
 static int
-pm8001_chip_soft_rst(struct pm8001_hba_info *pm8001_ha, u32 signature)
+pm8001_chip_soft_rst(struct pm8001_hba_info *pm8001_ha)
 {
        u32     regVal, toggleVal;
        u32     max_wait_count;
        u32     regVal1, regVal2, regVal3;
+       u32     signature = 0x252acbcd; /* for host scratch pad0 */
        unsigned long flags;
 
        /* step1: Check FW is ready for soft reset */
@@ -1113,7 +1183,7 @@ static void pm8001_hw_chip_rst(struct pm8001_hba_info *pm8001_ha)
  * pm8001_chip_iounmap - which maped when initialized.
  * @pm8001_ha: our hba card information
  */
-static void pm8001_chip_iounmap(struct pm8001_hba_info *pm8001_ha)
+void pm8001_chip_iounmap(struct pm8001_hba_info *pm8001_ha)
 {
        s8 bar, logical = 0;
        for (bar = 0; bar < 6; bar++) {
@@ -1192,7 +1262,7 @@ pm8001_chip_msix_interrupt_disable(struct pm8001_hba_info *pm8001_ha,
  * @pm8001_ha: our hba card information
  */
 static void
-pm8001_chip_interrupt_enable(struct pm8001_hba_info *pm8001_ha)
+pm8001_chip_interrupt_enable(struct pm8001_hba_info *pm8001_ha, u8 vec)
 {
 #ifdef PM8001_USE_MSIX
        pm8001_chip_msix_interrupt_enable(pm8001_ha, 0);
@@ -1207,7 +1277,7 @@ pm8001_chip_interrupt_enable(struct pm8001_hba_info *pm8001_ha)
  * @pm8001_ha: our hba card information
  */
 static void
-pm8001_chip_interrupt_disable(struct pm8001_hba_info *pm8001_ha)
+pm8001_chip_interrupt_disable(struct pm8001_hba_info *pm8001_ha, u8 vec)
 {
 #ifdef PM8001_USE_MSIX
        pm8001_chip_msix_interrupt_disable(pm8001_ha, 0);
@@ -1218,12 +1288,13 @@ pm8001_chip_interrupt_disable(struct pm8001_hba_info *pm8001_ha)
 }
 
 /**
- * mpi_msg_free_get- get the free message buffer for transfer inbound queue.
+ * pm8001_mpi_msg_free_get - get the free message buffer for transfer
+ * inbound queue.
  * @circularQ: the inbound queue  we want to transfer to HBA.
  * @messageSize: the message size of this transfer, normally it is 64 bytes
  * @messagePtr: the pointer to message.
  */
-static int mpi_msg_free_get(struct inbound_queue_table *circularQ,
+int pm8001_mpi_msg_free_get(struct inbound_queue_table *circularQ,
                            u16 messageSize, void **messagePtr)
 {
        u32 offset, consumer_index;
@@ -1231,7 +1302,7 @@ static int mpi_msg_free_get(struct inbound_queue_table *circularQ,
        u8 bcCount = 1; /* only support single buffer */
 
        /* Checks is the requested message size can be allocated in this queue*/
-       if (messageSize > 64) {
+       if (messageSize > IOMB_SIZE_SPCV) {
                *messagePtr = NULL;
                return -1;
        }
@@ -1245,7 +1316,7 @@ static int mpi_msg_free_get(struct inbound_queue_table *circularQ,
                return -1;
        }
        /* get memory IOMB buffer address */
-       offset = circularQ->producer_idx * 64;
+       offset = circularQ->producer_idx * messageSize;
        /* increment to next bcCount element */
        circularQ->producer_idx = (circularQ->producer_idx + bcCount)
                                % PM8001_MPI_QUEUE;
@@ -1257,29 +1328,30 @@ static int mpi_msg_free_get(struct inbound_queue_table *circularQ,
 }
 
 /**
- * mpi_build_cmd- build the message queue for transfer, update the PI to FW
- * to tell the fw to get this message from IOMB.
+ * pm8001_mpi_build_cmd- build the message queue for transfer, update the PI to
+ * FW to tell the fw to get this message from IOMB.
  * @pm8001_ha: our hba card information
  * @circularQ: the inbound queue we want to transfer to HBA.
  * @opCode: the operation code represents commands which LLDD and fw recognized.
  * @payload: the command payload of each operation command.
  */
-static int mpi_build_cmd(struct pm8001_hba_info *pm8001_ha,
+int pm8001_mpi_build_cmd(struct pm8001_hba_info *pm8001_ha,
                         struct inbound_queue_table *circularQ,
-                        u32 opCode, void *payload)
+                        u32 opCode, void *payload, u32 responseQueue)
 {
        u32 Header = 0, hpriority = 0, bc = 1, category = 0x02;
-       u32 responseQueue = 0;
        void *pMessage;
 
-       if (mpi_msg_free_get(circularQ, 64, &pMessage) < 0) {
+       if (pm8001_mpi_msg_free_get(circularQ, pm8001_ha->iomb_size,
+               &pMessage) < 0) {
                PM8001_IO_DBG(pm8001_ha,
                        pm8001_printk("No free mpi buffer\n"));
                return -1;
        }
        BUG_ON(!payload);
        /*Copy to the payload*/
-       memcpy(pMessage, payload, (64 - sizeof(struct mpi_msg_hdr)));
+       memcpy(pMessage, payload, (pm8001_ha->iomb_size -
+                               sizeof(struct mpi_msg_hdr)));
 
        /*Build the header*/
        Header = ((1 << 31) | (hpriority << 30) | ((bc & 0x1f) << 24)
@@ -1291,12 +1363,13 @@ static int mpi_build_cmd(struct pm8001_hba_info *pm8001_ha,
        pm8001_cw32(pm8001_ha, circularQ->pi_pci_bar,
                circularQ->pi_offset, circularQ->producer_idx);
        PM8001_IO_DBG(pm8001_ha,
-               pm8001_printk("after PI= %d CI= %d\n", circularQ->producer_idx,
-               circularQ->consumer_index));
+               pm8001_printk("INB Q %x OPCODE:%x , UPDATED PI=%d CI=%d\n",
+                       responseQueue, opCode, circularQ->producer_idx,
+                       circularQ->consumer_index));
        return 0;
 }
 
-static u32 mpi_msg_free_set(struct pm8001_hba_info *pm8001_ha, void *pMsg,
+u32 pm8001_mpi_msg_free_set(struct pm8001_hba_info *pm8001_ha, void *pMsg,
                            struct outbound_queue_table *circularQ, u8 bc)
 {
        u32 producer_index;
@@ -1305,7 +1378,7 @@ static u32 mpi_msg_free_set(struct pm8001_hba_info *pm8001_ha, void *pMsg,
 
        msgHeader = (struct mpi_msg_hdr *)(pMsg - sizeof(struct mpi_msg_hdr));
        pOutBoundMsgHeader = (struct mpi_msg_hdr *)(circularQ->base_virt +
-                               circularQ->consumer_idx * 64);
+                               circularQ->consumer_idx * pm8001_ha->iomb_size);
        if (pOutBoundMsgHeader != msgHeader) {
                PM8001_FAIL_DBG(pm8001_ha,
                        pm8001_printk("consumer_idx = %d msgHeader = %p\n",
@@ -1336,13 +1409,14 @@ static u32 mpi_msg_free_set(struct pm8001_hba_info *pm8001_ha, void *pMsg,
 }
 
 /**
- * mpi_msg_consume- get the MPI message from  outbound queue message table.
+ * pm8001_mpi_msg_consume- get the MPI message from outbound queue
+ * message table.
  * @pm8001_ha: our hba card information
  * @circularQ: the outbound queue  table.
  * @messagePtr1: the message contents of this outbound message.
  * @pBC: the message size.
  */
-static u32 mpi_msg_consume(struct pm8001_hba_info *pm8001_ha,
+u32 pm8001_mpi_msg_consume(struct pm8001_hba_info *pm8001_ha,
                           struct outbound_queue_table *circularQ,
                           void **messagePtr1, u8 *pBC)
 {
@@ -1356,7 +1430,7 @@ static u32 mpi_msg_consume(struct pm8001_hba_info *pm8001_ha,
                        /*Get the pointer to the circular queue buffer element*/
                        msgHeader = (struct mpi_msg_hdr *)
                                (circularQ->base_virt +
-                               circularQ->consumer_idx * 64);
+                               circularQ->consumer_idx * pm8001_ha->iomb_size);
                        /* read header */
                        header_tmp = pm8001_read_32(msgHeader);
                        msgHeader_tmp = cpu_to_le32(header_tmp);
@@ -1416,7 +1490,7 @@ static u32 mpi_msg_consume(struct pm8001_hba_info *pm8001_ha,
        return MPI_IO_STATUS_BUSY;
 }
 
-static void pm8001_work_fn(struct work_struct *work)
+void pm8001_work_fn(struct work_struct *work)
 {
        struct pm8001_work *pw = container_of(work, struct pm8001_work, work);
        struct pm8001_device *pm8001_dev;
@@ -1431,7 +1505,7 @@ static void pm8001_work_fn(struct work_struct *work)
        pm8001_dev = pw->data; /* Most stash device structure */
        if ((pm8001_dev == NULL)
         || ((pw->handler != IO_XFER_ERROR_BREAK)
-         && (pm8001_dev->dev_type == NO_DEVICE))) {
+         && (pm8001_dev->dev_type == SAS_PHY_UNUSED))) {
                kfree(pw);
                return;
        }
@@ -1596,7 +1670,7 @@ static void pm8001_work_fn(struct work_struct *work)
        }       break;
        case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS:
                dev = pm8001_dev->sas_device;
-               pm8001_I_T_nexus_reset(dev);
+               pm8001_I_T_nexus_event_handler(dev);
                break;
        case IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY:
                dev = pm8001_dev->sas_device;
@@ -1614,7 +1688,7 @@ static void pm8001_work_fn(struct work_struct *work)
        kfree(pw);
 }
 
-static int pm8001_handle_event(struct pm8001_hba_info *pm8001_ha, void *data,
+int pm8001_handle_event(struct pm8001_hba_info *pm8001_ha, void *data,
                               int handler)
 {
        struct pm8001_work *pw;
@@ -1633,6 +1707,123 @@ static int pm8001_handle_event(struct pm8001_hba_info *pm8001_ha, void *data,
        return ret;
 }
 
+static void pm8001_send_abort_all(struct pm8001_hba_info *pm8001_ha,
+               struct pm8001_device *pm8001_ha_dev)
+{
+       int res;
+       u32 ccb_tag;
+       struct pm8001_ccb_info *ccb;
+       struct sas_task *task = NULL;
+       struct task_abort_req task_abort;
+       struct inbound_queue_table *circularQ;
+       u32 opc = OPC_INB_SATA_ABORT;
+       int ret;
+
+       if (!pm8001_ha_dev) {
+               PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("dev is null\n"));
+               return;
+       }
+
+       task = sas_alloc_slow_task(GFP_ATOMIC);
+
+       if (!task) {
+               PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("cannot "
+                                               "allocate task\n"));
+               return;
+       }
+
+       task->task_done = pm8001_task_done;
+
+       res = pm8001_tag_alloc(pm8001_ha, &ccb_tag);
+       if (res)
+               return;
+
+       ccb = &pm8001_ha->ccb_info[ccb_tag];
+       ccb->device = pm8001_ha_dev;
+       ccb->ccb_tag = ccb_tag;
+       ccb->task = task;
+
+       circularQ = &pm8001_ha->inbnd_q_tbl[0];
+
+       memset(&task_abort, 0, sizeof(task_abort));
+       task_abort.abort_all = cpu_to_le32(1);
+       task_abort.device_id = cpu_to_le32(pm8001_ha_dev->device_id);
+       task_abort.tag = cpu_to_le32(ccb_tag);
+
+       ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort, 0);
+
+}
+
+static void pm8001_send_read_log(struct pm8001_hba_info *pm8001_ha,
+               struct pm8001_device *pm8001_ha_dev)
+{
+       struct sata_start_req sata_cmd;
+       int res;
+       u32 ccb_tag;
+       struct pm8001_ccb_info *ccb;
+       struct sas_task *task = NULL;
+       struct host_to_dev_fis fis;
+       struct domain_device *dev;
+       struct inbound_queue_table *circularQ;
+       u32 opc = OPC_INB_SATA_HOST_OPSTART;
+
+       task = sas_alloc_slow_task(GFP_ATOMIC);
+
+       if (!task) {
+               PM8001_FAIL_DBG(pm8001_ha,
+                       pm8001_printk("cannot allocate task !!!\n"));
+               return;
+       }
+       task->task_done = pm8001_task_done;
+
+       res = pm8001_tag_alloc(pm8001_ha, &ccb_tag);
+       if (res) {
+               PM8001_FAIL_DBG(pm8001_ha,
+                       pm8001_printk("cannot allocate tag !!!\n"));
+               return;
+       }
+
+       /* allocate domain device by ourselves as libsas
+        * is not going to provide any
+       */
+       dev = kzalloc(sizeof(struct domain_device), GFP_ATOMIC);
+       if (!dev) {
+               PM8001_FAIL_DBG(pm8001_ha,
+                       pm8001_printk("Domain device cannot be allocated\n"));
+               sas_free_task(task);
+               return;
+       } else {
+               task->dev = dev;
+               task->dev->lldd_dev = pm8001_ha_dev;
+       }
+
+       ccb = &pm8001_ha->ccb_info[ccb_tag];
+       ccb->device = pm8001_ha_dev;
+       ccb->ccb_tag = ccb_tag;
+       ccb->task = task;
+       pm8001_ha_dev->id |= NCQ_READ_LOG_FLAG;
+       pm8001_ha_dev->id |= NCQ_2ND_RLE_FLAG;
+
+       memset(&sata_cmd, 0, sizeof(sata_cmd));
+       circularQ = &pm8001_ha->inbnd_q_tbl[0];
+
+       /* construct read log FIS */
+       memset(&fis, 0, sizeof(struct host_to_dev_fis));
+       fis.fis_type = 0x27;
+       fis.flags = 0x80;
+       fis.command = ATA_CMD_READ_LOG_EXT;
+       fis.lbal = 0x10;
+       fis.sector_count = 0x1;
+
+       sata_cmd.tag = cpu_to_le32(ccb_tag);
+       sata_cmd.device_id = cpu_to_le32(pm8001_ha_dev->device_id);
+       sata_cmd.ncqtag_atap_dir_m |= ((0x1 << 7) | (0x5 << 9));
+       memcpy(&sata_cmd.sata_fis, &fis, sizeof(struct host_to_dev_fis));
+
+       res = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd, 0);
+
+}
+
 /**
  * mpi_ssp_completion- process the event that FW response to the SSP request.
  * @pm8001_ha: our hba card information
@@ -1867,7 +2058,7 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
                break;
        }
        PM8001_IO_DBG(pm8001_ha,
-               pm8001_printk("scsi_status = %x \n ",
+               pm8001_printk("scsi_status = %x\n ",
                psspPayload->ssp_resp_iu.status));
        spin_lock_irqsave(&t->task_state_lock, flags);
        t->task_state_flags &= ~SAS_TASK_STATE_PENDING;
@@ -2096,16 +2287,44 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
        status = le32_to_cpu(psataPayload->status);
        tag = le32_to_cpu(psataPayload->tag);
 
+       if (!tag) {
+               PM8001_FAIL_DBG(pm8001_ha,
+                       pm8001_printk("tag null\n"));
+               return;
+       }
        ccb = &pm8001_ha->ccb_info[tag];
        param = le32_to_cpu(psataPayload->param);
-       t = ccb->task;
+       if (ccb) {
+               t = ccb->task;
+               pm8001_dev = ccb->device;
+       } else {
+               PM8001_FAIL_DBG(pm8001_ha,
+                       pm8001_printk("ccb null\n"));
+               return;
+       }
+
+       if (t) {
+               if (t->dev && (t->dev->lldd_dev))
+                       pm8001_dev = t->dev->lldd_dev;
+       } else {
+               PM8001_FAIL_DBG(pm8001_ha,
+                       pm8001_printk("task null\n"));
+               return;
+       }
+
+       if ((pm8001_dev && !(pm8001_dev->id & NCQ_READ_LOG_FLAG))
+               && unlikely(!t || !t->lldd_task || !t->dev)) {
+               PM8001_FAIL_DBG(pm8001_ha,
+                       pm8001_printk("task or dev null\n"));
+               return;
+       }
+
        ts = &t->task_status;
-       pm8001_dev = ccb->device;
-       if (status)
+       if (!ts) {
                PM8001_FAIL_DBG(pm8001_ha,
-                       pm8001_printk("sata IO status 0x%x\n", status));
-       if (unlikely(!t || !t->lldd_task || !t->dev))
+                       pm8001_printk("ts null\n"));
                return;
+       }
 
        switch (status) {
        case IO_SUCCESS:
@@ -2113,6 +2332,19 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
                if (param == 0) {
                        ts->resp = SAS_TASK_COMPLETE;
                        ts->stat = SAM_STAT_GOOD;
+                       /* check if response is for SEND READ LOG */
+                       if (pm8001_dev &&
+                               (pm8001_dev->id & NCQ_READ_LOG_FLAG)) {
+                               /* set new bit for abort_all */
+                               pm8001_dev->id |= NCQ_ABORT_ALL_FLAG;
+                               /* clear bit for read log */
+                               pm8001_dev->id = pm8001_dev->id & 0x7FFFFFFF;
+                               pm8001_send_abort_all(pm8001_ha, pm8001_dev);
+                               /* Free the tag */
+                               pm8001_tag_free(pm8001_ha, tag);
+                               sas_free_task(t);
+                               return;
+                       }
                } else {
                        u8 len;
                        ts->resp = SAS_TASK_COMPLETE;
@@ -2423,6 +2655,29 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb)
        u32 dev_id = le32_to_cpu(psataPayload->device_id);
        unsigned long flags;
 
+       ccb = &pm8001_ha->ccb_info[tag];
+
+       if (ccb) {
+               t = ccb->task;
+               pm8001_dev = ccb->device;
+       } else {
+               PM8001_FAIL_DBG(pm8001_ha,
+                       pm8001_printk("No CCB !!!. returning\n"));
+       }
+       if (event)
+               PM8001_FAIL_DBG(pm8001_ha,
+                       pm8001_printk("SATA EVENT 0x%x\n", event));
+
+       /* Check if this is NCQ error */
+       if (event == IO_XFER_ERROR_ABORTED_NCQ_MODE) {
+               /* find device using device id */
+               pm8001_dev = pm8001_find_dev(pm8001_ha, dev_id);
+               /* send read log extension */
+               if (pm8001_dev)
+                       pm8001_send_read_log(pm8001_ha, pm8001_dev);
+               return;
+       }
+
        ccb = &pm8001_ha->ccb_info[tag];
        t = ccb->task;
        pm8001_dev = ccb->device;
@@ -2432,9 +2687,9 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb)
        if (unlikely(!t || !t->lldd_task || !t->dev))
                return;
        ts = &t->task_status;
-       PM8001_IO_DBG(pm8001_ha,
-               pm8001_printk("port_id = %x,device_id = %x\n",
-               port_id, dev_id));
+       PM8001_IO_DBG(pm8001_ha, pm8001_printk(
+               "port_id:0x%x, device_id:0x%x, tag:0x%x, event:0x%x\n",
+               port_id, dev_id, tag, event));
        switch (event) {
        case IO_OVERFLOW:
                PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_UNDERFLOW\n"));
@@ -2822,8 +3077,8 @@ mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
        }
 }
 
-static void
-mpi_set_dev_state_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
+void pm8001_mpi_set_dev_state_resp(struct pm8001_hba_info *pm8001_ha,
+               void *piomb)
 {
        struct set_dev_state_resp *pPayload =
                (struct set_dev_state_resp *)(piomb + 4);
@@ -2843,8 +3098,7 @@ mpi_set_dev_state_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
        pm8001_ccb_free(pm8001_ha, tag);
 }
 
-static void
-mpi_set_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
+void pm8001_mpi_set_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
 {
        struct get_nvm_data_resp *pPayload =
                (struct get_nvm_data_resp *)(piomb + 4);
@@ -2863,8 +3117,8 @@ mpi_set_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
        pm8001_ccb_free(pm8001_ha, tag);
 }
 
-static void
-mpi_get_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
+void
+pm8001_mpi_get_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
 {
        struct fw_control_ex    *fw_control_context;
        struct get_nvm_data_resp *pPayload =
@@ -2925,7 +3179,7 @@ mpi_get_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
        pm8001_ccb_free(pm8001_ha, tag);
 }
 
-static int mpi_local_phy_ctl(struct pm8001_hba_info *pm8001_ha, void *piomb)
+int pm8001_mpi_local_phy_ctl(struct pm8001_hba_info *pm8001_ha, void *piomb)
 {
        struct local_phy_ctl_resp *pPayload =
                (struct local_phy_ctl_resp *)(piomb + 4);
@@ -2954,7 +3208,7 @@ static int mpi_local_phy_ctl(struct pm8001_hba_info *pm8001_ha, void *piomb)
  * while receive a broadcast(change) primitive just tell the sas
  * layer to discover the changed domain rather than the whole domain.
  */
-static void pm8001_bytes_dmaed(struct pm8001_hba_info *pm8001_ha, int i)
+void pm8001_bytes_dmaed(struct pm8001_hba_info *pm8001_ha, int i)
 {
        struct pm8001_phy *phy = &pm8001_ha->phy[i];
        struct asd_sas_phy *sas_phy = &phy->sas_phy;
@@ -2988,7 +3242,7 @@ static void pm8001_bytes_dmaed(struct pm8001_hba_info *pm8001_ha, int i)
 }
 
 /* Get the link rate speed  */
-static void get_lrate_mode(struct pm8001_phy *phy, u8 link_rate)
+void pm8001_get_lrate_mode(struct pm8001_phy *phy, u8 link_rate)
 {
        struct sas_phy *sas_phy = phy->sas_phy.phy;
 
@@ -3025,7 +3279,7 @@ static void get_lrate_mode(struct pm8001_phy *phy, u8 link_rate)
  * LOCKING: the frame_rcvd_lock needs to be held since this parses the frame
  * buffer.
  */
-static void pm8001_get_attached_sas_addr(struct pm8001_phy *phy,
+void pm8001_get_attached_sas_addr(struct pm8001_phy *phy,
        u8 *sas_addr)
 {
        if (phy->sas_phy.frame_rcvd[0] == 0x34
@@ -3067,7 +3321,7 @@ static void pm8001_hw_event_ack_req(struct pm8001_hba_info *pm8001_ha,
                ((phyId & 0x0F) << 4) | (port_id & 0x0F));
        payload.param0 = cpu_to_le32(param0);
        payload.param1 = cpu_to_le32(param1);
-       mpi_build_cmd(pm8001_ha, circularQ, opc, &payload);
+       pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
 }
 
 static int pm8001_chip_phy_ctl_req(struct pm8001_hba_info *pm8001_ha,
@@ -3112,19 +3366,19 @@ hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)
                pm8001_chip_phy_ctl_req(pm8001_ha, phy_id,
                        PHY_NOTIFY_ENABLE_SPINUP);
                port->port_attached = 1;
-               get_lrate_mode(phy, link_rate);
+               pm8001_get_lrate_mode(phy, link_rate);
                break;
        case SAS_EDGE_EXPANDER_DEVICE:
                PM8001_MSG_DBG(pm8001_ha,
                        pm8001_printk("expander device.\n"));
                port->port_attached = 1;
-               get_lrate_mode(phy, link_rate);
+               pm8001_get_lrate_mode(phy, link_rate);
                break;
        case SAS_FANOUT_EXPANDER_DEVICE:
                PM8001_MSG_DBG(pm8001_ha,
                        pm8001_printk("fanout expander device.\n"));
                port->port_attached = 1;
-               get_lrate_mode(phy, link_rate);
+               pm8001_get_lrate_mode(phy, link_rate);
                break;
        default:
                PM8001_MSG_DBG(pm8001_ha,
@@ -3179,7 +3433,7 @@ hw_event_sata_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)
                " phy id = %d\n", port_id, phy_id));
        port->port_state =  portstate;
        port->port_attached = 1;
-       get_lrate_mode(phy, link_rate);
+       pm8001_get_lrate_mode(phy, link_rate);
        phy->phy_type |= PORT_TYPE_SATA;
        phy->phy_attached = 1;
        phy->sas_phy.oob_mode = SATA_OOB_MODE;
@@ -3189,7 +3443,7 @@ hw_event_sata_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)
                sizeof(struct dev_to_host_fis));
        phy->frame_rcvd_size = sizeof(struct dev_to_host_fis);
        phy->identify.target_port_protocols = SAS_PROTOCOL_SATA;
-       phy->identify.device_type = SATA_DEV;
+       phy->identify.device_type = SAS_SATA_DEV;
        pm8001_get_attached_sas_addr(phy, phy->sas_phy.attached_sas_addr);
        spin_unlock_irqrestore(&phy->sas_phy.frame_rcvd_lock, flags);
        pm8001_bytes_dmaed(pm8001_ha, phy_id);
@@ -3260,7 +3514,7 @@ hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void *piomb)
 }
 
 /**
- * mpi_reg_resp -process register device ID response.
+ * pm8001_mpi_reg_resp -process register device ID response.
  * @pm8001_ha: our hba card information
  * @piomb: IO message buffer
  *
@@ -3269,7 +3523,7 @@ hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void *piomb)
  * has assigned, from now,inter-communication with FW is no longer using the
  * SAS address, use device ID which FW assigned.
  */
-static int mpi_reg_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
+int pm8001_mpi_reg_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
 {
        u32 status;
        u32 device_id;
@@ -3331,7 +3585,7 @@ static int mpi_reg_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
        return 0;
 }
 
-static int mpi_dereg_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
+int pm8001_mpi_dereg_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
 {
        u32 status;
        u32 device_id;
@@ -3347,8 +3601,13 @@ static int mpi_dereg_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
        return 0;
 }
 
-static int
-mpi_fw_flash_update_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
+/**
+ * fw_flash_update_resp - Response from FW for flash update command.
+ * @pm8001_ha: our hba card information
+ * @piomb: IO message buffer
+ */
+int pm8001_mpi_fw_flash_update_resp(struct pm8001_hba_info *pm8001_ha,
+               void *piomb)
 {
        u32 status;
        struct fw_control_ex    fw_control_context;
@@ -3403,10 +3662,6 @@ mpi_fw_flash_update_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
                break;
        }
        ccb->fw_control_context->fw_control->retcode = status;
-       pci_free_consistent(pm8001_ha->pdev,
-                       fw_control_context.len,
-                       fw_control_context.virtAddr,
-                       fw_control_context.phys_addr);
        complete(pm8001_ha->nvmd_completion);
        ccb->task = NULL;
        ccb->ccb_tag = 0xFFFFFFFF;
@@ -3414,8 +3669,7 @@ mpi_fw_flash_update_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
        return 0;
 }
 
-static int
-mpi_general_event(struct pm8001_hba_info *pm8001_ha , void *piomb)
+int pm8001_mpi_general_event(struct pm8001_hba_info *pm8001_ha , void *piomb)
 {
        u32 status;
        int i;
@@ -3431,8 +3685,7 @@ mpi_general_event(struct pm8001_hba_info *pm8001_ha , void *piomb)
        return 0;
 }
 
-static int
-mpi_task_abort_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
+int pm8001_mpi_task_abort_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
 {
        struct sas_task *t;
        struct pm8001_ccb_info *ccb;
@@ -3440,19 +3693,29 @@ mpi_task_abort_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
        u32 status ;
        u32 tag, scp;
        struct task_status_struct *ts;
+       struct pm8001_device *pm8001_dev;
 
        struct task_abort_resp *pPayload =
                (struct task_abort_resp *)(piomb + 4);
 
        status = le32_to_cpu(pPayload->status);
        tag = le32_to_cpu(pPayload->tag);
+       if (!tag) {
+               PM8001_FAIL_DBG(pm8001_ha,
+                       pm8001_printk(" TAG NULL. RETURNING !!!"));
+               return -1;
+       }
+
        scp = le32_to_cpu(pPayload->scp);
        ccb = &pm8001_ha->ccb_info[tag];
        t = ccb->task;
-       PM8001_IO_DBG(pm8001_ha,
-               pm8001_printk(" status = 0x%x\n", status));
-       if (t == NULL)
+       pm8001_dev = ccb->device; /* retrieve device */
+
+       if (!t) {
+               PM8001_FAIL_DBG(pm8001_ha,
+                       pm8001_printk(" TASK NULL. RETURNING !!!"));
                return -1;
+       }
        ts = &t->task_status;
        if (status != 0)
                PM8001_FAIL_DBG(pm8001_ha,
@@ -3476,7 +3739,15 @@ mpi_task_abort_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
        spin_unlock_irqrestore(&t->task_state_lock, flags);
        pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
        mb();
-       t->task_done(t);
+
+       if ((pm8001_dev->id & NCQ_ABORT_ALL_FLAG) && t) {
+               pm8001_tag_free(pm8001_ha, tag);
+               sas_free_task(t);
+               /* clear the flag */
+               pm8001_dev->id &= 0xBFFFFFFF;
+       } else
+               t->task_done(t);
+
        return 0;
 }
 
@@ -3727,17 +3998,17 @@ static void process_one_iomb(struct pm8001_hba_info *pm8001_ha, void *piomb)
        case OPC_OUB_LOCAL_PHY_CNTRL:
                PM8001_MSG_DBG(pm8001_ha,
                        pm8001_printk("OPC_OUB_LOCAL_PHY_CNTRL\n"));
-               mpi_local_phy_ctl(pm8001_ha, piomb);
+               pm8001_mpi_local_phy_ctl(pm8001_ha, piomb);
                break;
        case OPC_OUB_DEV_REGIST:
                PM8001_MSG_DBG(pm8001_ha,
                        pm8001_printk("OPC_OUB_DEV_REGIST\n"));
-               mpi_reg_resp(pm8001_ha, piomb);
+               pm8001_mpi_reg_resp(pm8001_ha, piomb);
                break;
        case OPC_OUB_DEREG_DEV:
                PM8001_MSG_DBG(pm8001_ha,
                        pm8001_printk("unregister the device\n"));
-               mpi_dereg_resp(pm8001_ha, piomb);
+               pm8001_mpi_dereg_resp(pm8001_ha, piomb);
                break;
        case OPC_OUB_GET_DEV_HANDLE:
                PM8001_MSG_DBG(pm8001_ha,
@@ -3775,7 +4046,7 @@ static void process_one_iomb(struct pm8001_hba_info *pm8001_ha, void *piomb)
        case OPC_OUB_FW_FLASH_UPDATE:
                PM8001_MSG_DBG(pm8001_ha,
                        pm8001_printk("OPC_OUB_FW_FLASH_UPDATE\n"));
-               mpi_fw_flash_update_resp(pm8001_ha, piomb);
+               pm8001_mpi_fw_flash_update_resp(pm8001_ha, piomb);
                break;
        case OPC_OUB_GPIO_RESPONSE:
                PM8001_MSG_DBG(pm8001_ha,
@@ -3788,17 +4059,17 @@ static void process_one_iomb(struct pm8001_hba_info *pm8001_ha, void *piomb)
        case OPC_OUB_GENERAL_EVENT:
                PM8001_MSG_DBG(pm8001_ha,
                        pm8001_printk("OPC_OUB_GENERAL_EVENT\n"));
-               mpi_general_event(pm8001_ha, piomb);
+               pm8001_mpi_general_event(pm8001_ha, piomb);
                break;
        case OPC_OUB_SSP_ABORT_RSP:
                PM8001_MSG_DBG(pm8001_ha,
                        pm8001_printk("OPC_OUB_SSP_ABORT_RSP\n"));
-               mpi_task_abort_resp(pm8001_ha, piomb);
+               pm8001_mpi_task_abort_resp(pm8001_ha, piomb);
                break;
        case OPC_OUB_SATA_ABORT_RSP:
                PM8001_MSG_DBG(pm8001_ha,
                        pm8001_printk("OPC_OUB_SATA_ABORT_RSP\n"));
-               mpi_task_abort_resp(pm8001_ha, piomb);
+               pm8001_mpi_task_abort_resp(pm8001_ha, piomb);
                break;
        case OPC_OUB_SAS_DIAG_MODE_START_END:
                PM8001_MSG_DBG(pm8001_ha,
@@ -3823,17 +4094,17 @@ static void process_one_iomb(struct pm8001_hba_info *pm8001_ha, void *piomb)
        case OPC_OUB_SMP_ABORT_RSP:
                PM8001_MSG_DBG(pm8001_ha,
                        pm8001_printk("OPC_OUB_SMP_ABORT_RSP\n"));
-               mpi_task_abort_resp(pm8001_ha, piomb);
+               pm8001_mpi_task_abort_resp(pm8001_ha, piomb);
                break;
        case OPC_OUB_GET_NVMD_DATA:
                PM8001_MSG_DBG(pm8001_ha,
                        pm8001_printk("OPC_OUB_GET_NVMD_DATA\n"));
-               mpi_get_nvmd_resp(pm8001_ha, piomb);
+               pm8001_mpi_get_nvmd_resp(pm8001_ha, piomb);
                break;
        case OPC_OUB_SET_NVMD_DATA:
                PM8001_MSG_DBG(pm8001_ha,
                        pm8001_printk("OPC_OUB_SET_NVMD_DATA\n"));
-               mpi_set_nvmd_resp(pm8001_ha, piomb);
+               pm8001_mpi_set_nvmd_resp(pm8001_ha, piomb);
                break;
        case OPC_OUB_DEVICE_HANDLE_REMOVAL:
                PM8001_MSG_DBG(pm8001_ha,
@@ -3842,7 +4113,7 @@ static void process_one_iomb(struct pm8001_hba_info *pm8001_ha, void *piomb)
        case OPC_OUB_SET_DEVICE_STATE:
                PM8001_MSG_DBG(pm8001_ha,
                        pm8001_printk("OPC_OUB_SET_DEVICE_STATE\n"));
-               mpi_set_dev_state_resp(pm8001_ha, piomb);
+               pm8001_mpi_set_dev_state_resp(pm8001_ha, piomb);
                break;
        case OPC_OUB_GET_DEVICE_STATE:
                PM8001_MSG_DBG(pm8001_ha,
@@ -3864,7 +4135,7 @@ static void process_one_iomb(struct pm8001_hba_info *pm8001_ha, void *piomb)
        }
 }
 
-static int process_oq(struct pm8001_hba_info *pm8001_ha)
+static int process_oq(struct pm8001_hba_info *pm8001_ha, u8 vec)
 {
        struct outbound_queue_table *circularQ;
        void *pMsg1 = NULL;
@@ -3873,14 +4144,15 @@ static int process_oq(struct pm8001_hba_info *pm8001_ha)
        unsigned long flags;
 
        spin_lock_irqsave(&pm8001_ha->lock, flags);
-       circularQ = &pm8001_ha->outbnd_q_tbl[0];
+       circularQ = &pm8001_ha->outbnd_q_tbl[vec];
        do {
-               ret = mpi_msg_consume(pm8001_ha, circularQ, &pMsg1, &bc);
+               ret = pm8001_mpi_msg_consume(pm8001_ha, circularQ, &pMsg1, &bc);
                if (MPI_IO_STATUS_SUCCESS == ret) {
                        /* process the outbound message */
                        process_one_iomb(pm8001_ha, (void *)(pMsg1 - 4));
                        /* free the message from the outbound circular buffer */
-                       mpi_msg_free_set(pm8001_ha, pMsg1, circularQ, bc);
+                       pm8001_mpi_msg_free_set(pm8001_ha, pMsg1,
+                                                       circularQ, bc);
                }
                if (MPI_IO_STATUS_BUSY == ret) {
                        /* Update the producer index from SPC */
@@ -3903,7 +4175,7 @@ static const u8 data_dir_flags[] = {
        [PCI_DMA_FROMDEVICE]    = DATA_DIR_IN,/* INBOUND */
        [PCI_DMA_NONE]          = DATA_DIR_NONE,/* NO TRANSFER */
 };
-static void
+void
 pm8001_chip_make_sg(struct scatterlist *scatter, int nr, void *prd)
 {
        int i;
@@ -3978,7 +4250,7 @@ static int pm8001_chip_smp_req(struct pm8001_hba_info *pm8001_ha,
        smp_cmd.long_smp_req.long_resp_size =
                cpu_to_le32((u32)sg_dma_len(&task->smp_task.smp_resp)-4);
        build_smp_cmd(pm8001_dev->device_id, smp_cmd.tag, &smp_cmd);
-       mpi_build_cmd(pm8001_ha, circularQ, opc, (u32 *)&smp_cmd);
+       pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, (u32 *)&smp_cmd, 0);
        return 0;
 
 err_out_2:
@@ -4042,7 +4314,7 @@ static int pm8001_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha,
                ssp_cmd.len = cpu_to_le32(task->total_xfer_len);
                ssp_cmd.esgl = 0;
        }
-       ret = mpi_build_cmd(pm8001_ha, circularQ, opc, &ssp_cmd);
+       ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &ssp_cmd, 0);
        return ret;
 }
 
@@ -4060,6 +4332,7 @@ static int pm8001_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
        u32 ATAP = 0x0;
        u32 dir;
        struct inbound_queue_table *circularQ;
+       unsigned long flags;
        u32  opc = OPC_INB_SATA_HOST_OPSTART;
        memset(&sata_cmd, 0, sizeof(sata_cmd));
        circularQ = &pm8001_ha->inbnd_q_tbl[0];
@@ -4080,8 +4353,10 @@ static int pm8001_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
                        PM8001_IO_DBG(pm8001_ha, pm8001_printk("FPDMA\n"));
                }
        }
-       if (task->ata_task.use_ncq && pm8001_get_ncq_tag(task, &hdr_tag))
+       if (task->ata_task.use_ncq && pm8001_get_ncq_tag(task, &hdr_tag)) {
+               task->ata_task.fis.sector_count |= (u8) (hdr_tag << 3);
                ncg_tag = hdr_tag;
+       }
        dir = data_dir_flags[task->data_dir] << 8;
        sata_cmd.tag = cpu_to_le32(tag);
        sata_cmd.device_id = cpu_to_le32(pm8001_ha_dev->device_id);
@@ -4112,7 +4387,55 @@ static int pm8001_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
                sata_cmd.len = cpu_to_le32(task->total_xfer_len);
                sata_cmd.esgl = 0;
        }
-       ret = mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd);
+
+       /* Check for read log for failed drive and return */
+       if (sata_cmd.sata_fis.command == 0x2f) {
+               if (pm8001_ha_dev && ((pm8001_ha_dev->id & NCQ_READ_LOG_FLAG) ||
+                       (pm8001_ha_dev->id & NCQ_ABORT_ALL_FLAG) ||
+                       (pm8001_ha_dev->id & NCQ_2ND_RLE_FLAG))) {
+                       struct task_status_struct *ts;
+
+                       pm8001_ha_dev->id &= 0xDFFFFFFF;
+                       ts = &task->task_status;
+
+                       spin_lock_irqsave(&task->task_state_lock, flags);
+                       ts->resp = SAS_TASK_COMPLETE;
+                       ts->stat = SAM_STAT_GOOD;
+                       task->task_state_flags &= ~SAS_TASK_STATE_PENDING;
+                       task->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
+                       task->task_state_flags |= SAS_TASK_STATE_DONE;
+                       if (unlikely((task->task_state_flags &
+                                       SAS_TASK_STATE_ABORTED))) {
+                               spin_unlock_irqrestore(&task->task_state_lock,
+                                                       flags);
+                               PM8001_FAIL_DBG(pm8001_ha,
+                                       pm8001_printk("task 0x%p resp 0x%x "
+                                       " stat 0x%x but aborted by upper layer "
+                                       "\n", task, ts->resp, ts->stat));
+                               pm8001_ccb_task_free(pm8001_ha, task, ccb, tag);
+                       } else if (task->uldd_task) {
+                               spin_unlock_irqrestore(&task->task_state_lock,
+                                                       flags);
+                               pm8001_ccb_task_free(pm8001_ha, task, ccb, tag);
+                               mb();/* ditto */
+                               spin_unlock_irq(&pm8001_ha->lock);
+                               task->task_done(task);
+                               spin_lock_irq(&pm8001_ha->lock);
+                               return 0;
+                       } else if (!task->uldd_task) {
+                               spin_unlock_irqrestore(&task->task_state_lock,
+                                                       flags);
+                               pm8001_ccb_task_free(pm8001_ha, task, ccb, tag);
+                               mb();/*ditto*/
+                               spin_unlock_irq(&pm8001_ha->lock);
+                               task->task_done(task);
+                               spin_lock_irq(&pm8001_ha->lock);
+                               return 0;
+                       }
+               }
+       }
+
+       ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd, 0);
        return ret;
 }
 
@@ -4142,12 +4465,12 @@ pm8001_chip_phy_start_req(struct pm8001_hba_info *pm8001_ha, u8 phy_id)
        payload.ase_sh_lm_slr_phyid = cpu_to_le32(SPINHOLD_DISABLE |
                LINKMODE_AUTO | LINKRATE_15 |
                LINKRATE_30 | LINKRATE_60 | phy_id);
-       payload.sas_identify.dev_type = SAS_END_DEV;
+       payload.sas_identify.dev_type = SAS_END_DEVICE;
        payload.sas_identify.initiator_bits = SAS_PROTOCOL_ALL;
        memcpy(payload.sas_identify.sas_addr,
                pm8001_ha->sas_addr, SAS_ADDR_SIZE);
        payload.sas_identify.phy_id = phy_id;
-       ret = mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload);
+       ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload, 0);
        return ret;
 }
 
@@ -4157,7 +4480,7 @@ pm8001_chip_phy_start_req(struct pm8001_hba_info *pm8001_ha, u8 phy_id)
  * @num: the inbound queue number
  * @phy_id: the phy id which we wanted to start up.
  */
-static int pm8001_chip_phy_stop_req(struct pm8001_hba_info *pm8001_ha,
+int pm8001_chip_phy_stop_req(struct pm8001_hba_info *pm8001_ha,
        u8 phy_id)
 {
        struct phy_stop_req payload;
@@ -4169,12 +4492,12 @@ static int pm8001_chip_phy_stop_req(struct pm8001_hba_info *pm8001_ha,
        memset(&payload, 0, sizeof(payload));
        payload.tag = cpu_to_le32(tag);
        payload.phy_id = cpu_to_le32(phy_id);
-       ret = mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload);
+       ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload, 0);
        return ret;
 }
 
 /**
- * see comments on mpi_reg_resp.
+ * see comments on pm8001_mpi_reg_resp.
  */
 static int pm8001_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha,
        struct pm8001_device *pm8001_dev, u32 flag)
@@ -4204,11 +4527,11 @@ static int pm8001_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha,
        if (flag == 1)
                stp_sspsmp_sata = 0x02; /*direct attached sata */
        else {
-               if (pm8001_dev->dev_type == SATA_DEV)
+               if (pm8001_dev->dev_type == SAS_SATA_DEV)
                        stp_sspsmp_sata = 0x00; /* stp*/
-               else if (pm8001_dev->dev_type == SAS_END_DEV ||
-                       pm8001_dev->dev_type == EDGE_DEV ||
-                       pm8001_dev->dev_type == FANOUT_DEV)
+               else if (pm8001_dev->dev_type == SAS_END_DEVICE ||
+                       pm8001_dev->dev_type == SAS_EDGE_EXPANDER_DEVICE ||
+                       pm8001_dev->dev_type == SAS_FANOUT_EXPANDER_DEVICE)
                        stp_sspsmp_sata = 0x01; /*ssp or smp*/
        }
        if (parent_dev && DEV_IS_EXPANDER(parent_dev->dev_type))
@@ -4228,14 +4551,14 @@ static int pm8001_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha,
                cpu_to_le32(ITNT | (firstBurstSize * 0x10000));
        memcpy(payload.sas_addr, pm8001_dev->sas_device->sas_addr,
                SAS_ADDR_SIZE);
-       rc = mpi_build_cmd(pm8001_ha, circularQ, opc, &payload);
+       rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
        return rc;
 }
 
 /**
- * see comments on mpi_reg_resp.
+ * see comments on pm8001_mpi_reg_resp.
  */
-static int pm8001_chip_dereg_dev_req(struct pm8001_hba_info *pm8001_ha,
+int pm8001_chip_dereg_dev_req(struct pm8001_hba_info *pm8001_ha,
        u32 device_id)
 {
        struct dereg_dev_req payload;
@@ -4249,7 +4572,7 @@ static int pm8001_chip_dereg_dev_req(struct pm8001_hba_info *pm8001_ha,
        payload.device_id = cpu_to_le32(device_id);
        PM8001_MSG_DBG(pm8001_ha,
                pm8001_printk("unregister device device_id = %d\n", device_id));
-       ret = mpi_build_cmd(pm8001_ha, circularQ, opc, &payload);
+       ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
        return ret;
 }
 
@@ -4272,7 +4595,7 @@ static int pm8001_chip_phy_ctl_req(struct pm8001_hba_info *pm8001_ha,
        payload.tag = cpu_to_le32(1);
        payload.phyop_phyid =
                cpu_to_le32(((phy_op & 0xff) << 8) | (phyId & 0x0F));
-       ret = mpi_build_cmd(pm8001_ha, circularQ, opc, &payload);
+       ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
        return ret;
 }
 
@@ -4296,11 +4619,11 @@ static u32 pm8001_chip_is_our_interupt(struct pm8001_hba_info *pm8001_ha)
  * @stat: stat.
  */
 static irqreturn_t
-pm8001_chip_isr(struct pm8001_hba_info *pm8001_ha)
+pm8001_chip_isr(struct pm8001_hba_info *pm8001_ha, u8 vec)
 {
-       pm8001_chip_interrupt_disable(pm8001_ha);
-       process_oq(pm8001_ha);
-       pm8001_chip_interrupt_enable(pm8001_ha);
+       pm8001_chip_interrupt_disable(pm8001_ha, vec);
+       process_oq(pm8001_ha, vec);
+       pm8001_chip_interrupt_enable(pm8001_ha, vec);
        return IRQ_HANDLED;
 }
 
@@ -4322,7 +4645,7 @@ static int send_task_abort(struct pm8001_hba_info *pm8001_ha, u32 opc,
                task_abort.device_id = cpu_to_le32(dev_id);
                task_abort.tag = cpu_to_le32(cmd_tag);
        }
-       ret = mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort);
+       ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort, 0);
        return ret;
 }
 
@@ -4331,16 +4654,17 @@ static int send_task_abort(struct pm8001_hba_info *pm8001_ha, u32 opc,
  * @task: the task we wanted to aborted.
  * @flag: the abort flag.
  */
-static int pm8001_chip_abort_task(struct pm8001_hba_info *pm8001_ha,
+int pm8001_chip_abort_task(struct pm8001_hba_info *pm8001_ha,
        struct pm8001_device *pm8001_dev, u8 flag, u32 task_tag, u32 cmd_tag)
 {
        u32 opc, device_id;
        int rc = TMF_RESP_FUNC_FAILED;
-       PM8001_EH_DBG(pm8001_ha, pm8001_printk("cmd_tag = %x, abort task tag"
-               " = %x", cmd_tag, task_tag));
-       if (pm8001_dev->dev_type == SAS_END_DEV)
+       PM8001_EH_DBG(pm8001_ha,
+               pm8001_printk("cmd_tag = %x, abort task tag = 0x%x",
+                       cmd_tag, task_tag));
+       if (pm8001_dev->dev_type == SAS_END_DEVICE)
                opc = OPC_INB_SSP_ABORT;
-       else if (pm8001_dev->dev_type == SATA_DEV)
+       else if (pm8001_dev->dev_type == SAS_SATA_DEV)
                opc = OPC_INB_SATA_ABORT;
        else
                opc = OPC_INB_SMP_ABORT;/* SMP */
@@ -4358,7 +4682,7 @@ static int pm8001_chip_abort_task(struct pm8001_hba_info *pm8001_ha,
  * @ccb: the ccb information.
  * @tmf: task management function.
  */
-static int pm8001_chip_ssp_tm_req(struct pm8001_hba_info *pm8001_ha,
+int pm8001_chip_ssp_tm_req(struct pm8001_hba_info *pm8001_ha,
        struct pm8001_ccb_info *ccb, struct pm8001_tmf_task *tmf)
 {
        struct sas_task *task = ccb->task;
@@ -4376,11 +4700,11 @@ static int pm8001_chip_ssp_tm_req(struct pm8001_hba_info *pm8001_ha,
        memcpy(sspTMCmd.lun, task->ssp_task.LUN, 8);
        sspTMCmd.tag = cpu_to_le32(ccb->ccb_tag);
        circularQ = &pm8001_ha->inbnd_q_tbl[0];
-       ret = mpi_build_cmd(pm8001_ha, circularQ, opc, &sspTMCmd);
+       ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sspTMCmd, 0);
        return ret;
 }
 
-static int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha,
+int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha,
        void *payload)
 {
        u32 opc = OPC_INB_GET_NVMD_DATA;
@@ -4397,7 +4721,7 @@ static int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha,
        fw_control_context = kzalloc(sizeof(struct fw_control_ex), GFP_KERNEL);
        if (!fw_control_context)
                return -ENOMEM;
-       fw_control_context->usrAddr = (u8 *)&ioctl_payload->func_specific[0];
+       fw_control_context->usrAddr = (u8 *)ioctl_payload->func_specific;
        fw_control_context->len = ioctl_payload->length;
        circularQ = &pm8001_ha->inbnd_q_tbl[0];
        memset(&nvmd_req, 0, sizeof(nvmd_req));
@@ -4456,11 +4780,11 @@ static int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha,
        default:
                break;
        }
-       rc = mpi_build_cmd(pm8001_ha, circularQ, opc, &nvmd_req);
+       rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &nvmd_req, 0);
        return rc;
 }
 
-static int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha,
+int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha,
        void *payload)
 {
        u32 opc = OPC_INB_SET_NVMD_DATA;
@@ -4479,7 +4803,7 @@ static int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha,
                return -ENOMEM;
        circularQ = &pm8001_ha->inbnd_q_tbl[0];
        memcpy(pm8001_ha->memoryMap.region[NVMD].virt_ptr,
-               ioctl_payload->func_specific,
+               &ioctl_payload->func_specific,
                ioctl_payload->length);
        memset(&nvmd_req, 0, sizeof(nvmd_req));
        rc = pm8001_tag_alloc(pm8001_ha, &tag);
@@ -4536,7 +4860,7 @@ static int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha,
        default:
                break;
        }
-       rc = mpi_build_cmd(pm8001_ha, circularQ, opc, &nvmd_req);
+       rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &nvmd_req, 0);
        return rc;
 }
 
@@ -4545,7 +4869,7 @@ static int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha,
  * @pm8001_ha: our hba card information.
  * @fw_flash_updata_info: firmware flash update param
  */
-static int
+int
 pm8001_chip_fw_flash_update_build(struct pm8001_hba_info *pm8001_ha,
        void *fw_flash_updata_info, u32 tag)
 {
@@ -4567,11 +4891,11 @@ pm8001_chip_fw_flash_update_build(struct pm8001_hba_info *pm8001_ha,
                cpu_to_le32(lower_32_bits(le64_to_cpu(info->sgl.addr)));
        payload.sgl_addr_hi =
                cpu_to_le32(upper_32_bits(le64_to_cpu(info->sgl.addr)));
-       ret = mpi_build_cmd(pm8001_ha, circularQ, opc, &payload);
+       ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
        return ret;
 }
 
-static int
+int
 pm8001_chip_fw_flash_update_req(struct pm8001_hba_info *pm8001_ha,
        void *payload)
 {
@@ -4581,29 +4905,14 @@ pm8001_chip_fw_flash_update_req(struct pm8001_hba_info *pm8001_ha,
        int rc;
        u32 tag;
        struct pm8001_ccb_info *ccb;
-       void *buffer = NULL;
-       dma_addr_t phys_addr;
-       u32 phys_addr_hi;
-       u32 phys_addr_lo;
+       void *buffer = pm8001_ha->memoryMap.region[FW_FLASH].virt_ptr;
+       dma_addr_t phys_addr = pm8001_ha->memoryMap.region[FW_FLASH].phys_addr;
        struct pm8001_ioctl_payload *ioctl_payload = payload;
 
        fw_control_context = kzalloc(sizeof(struct fw_control_ex), GFP_KERNEL);
        if (!fw_control_context)
                return -ENOMEM;
-       fw_control = (struct fw_control_info *)&ioctl_payload->func_specific[0];
-       if (fw_control->len != 0) {
-               if (pm8001_mem_alloc(pm8001_ha->pdev,
-                       (void **)&buffer,
-                       &phys_addr,
-                       &phys_addr_hi,
-                       &phys_addr_lo,
-                       fw_control->len, 0) != 0) {
-                               PM8001_FAIL_DBG(pm8001_ha,
-                                       pm8001_printk("Mem alloc failure\n"));
-                               kfree(fw_control_context);
-                               return -ENOMEM;
-               }
-       }
+       fw_control = (struct fw_control_info *)&ioctl_payload->func_specific;
        memcpy(buffer, fw_control->buffer, fw_control->len);
        flash_update_info.sgl.addr = cpu_to_le64(phys_addr);
        flash_update_info.sgl.im_len.len = cpu_to_le32(fw_control->len);
@@ -4613,6 +4922,7 @@ pm8001_chip_fw_flash_update_req(struct pm8001_hba_info *pm8001_ha,
        flash_update_info.total_image_len = fw_control->size;
        fw_control_context->fw_control = fw_control;
        fw_control_context->virtAddr = buffer;
+       fw_control_context->phys_addr = phys_addr;
        fw_control_context->len = fw_control->len;
        rc = pm8001_tag_alloc(pm8001_ha, &tag);
        if (rc) {
@@ -4627,7 +4937,7 @@ pm8001_chip_fw_flash_update_req(struct pm8001_hba_info *pm8001_ha,
        return rc;
 }
 
-static int
+int
 pm8001_chip_set_dev_state_req(struct pm8001_hba_info *pm8001_ha,
        struct pm8001_device *pm8001_dev, u32 state)
 {
@@ -4648,7 +4958,7 @@ pm8001_chip_set_dev_state_req(struct pm8001_hba_info *pm8001_ha,
        payload.tag = cpu_to_le32(tag);
        payload.device_id = cpu_to_le32(pm8001_dev->device_id);
        payload.nds = cpu_to_le32(state);
-       rc = mpi_build_cmd(pm8001_ha, circularQ, opc, &payload);
+       rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
        return rc;
 
 }
@@ -4673,7 +4983,7 @@ pm8001_chip_sas_re_initialization(struct pm8001_hba_info *pm8001_ha)
        payload.SSAHOLT = cpu_to_le32(0xd << 25);
        payload.sata_hol_tmo = cpu_to_le32(80);
        payload.open_reject_cmdretries_data_retries = cpu_to_le32(0xff00ff);
-       rc = mpi_build_cmd(pm8001_ha, circularQ, opc, &payload);
+       rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
        return rc;
 
 }
@@ -4706,4 +5016,3 @@ const struct pm8001_dispatch pm8001_8001_dispatch = {
        .set_dev_state_req      = pm8001_chip_set_dev_state_req,
        .sas_re_init_req        = pm8001_chip_sas_re_initialization,
 };
-
index d437309..d7c1e20 100644 (file)
 #define LINKRATE_30                    (0x02 << 8)
 #define LINKRATE_60                    (0x04 << 8)
 
+/* for new SPC controllers MEMBASE III is shared between BIOS and DATA */
+#define GSM_SM_BASE                    0x4F0000
 struct mpi_msg_hdr{
        __le32  header; /* Bits [11:0]  - Message operation code */
        /* Bits [15:12] - Message Category */
@@ -298,7 +300,7 @@ struct local_phy_ctl_resp {
 
 
 #define OP_BITS 0x0000FF00
-#define ID_BITS 0x0000000F
+#define ID_BITS 0x000000FF
 
 /*
  * brief the data structure of PORT Control Command
index 3d5e522..e4b9bc7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * PMC-Sierra SPC 8001 SAS/SATA based host adapters driver
+ * PMC-Sierra PM8001/8081/8088/8089 SAS/SATA based host adapters driver
  *
  * Copyright (c) 2008-2009 USI Co., Ltd.
  * All rights reserved.
 
 static struct scsi_transport_template *pm8001_stt;
 
+/**
+ * chip info structure to identify chip key functionality as
+ * encryption available/not, no of ports, hw specific function ref
+ */
 static const struct pm8001_chip_info pm8001_chips[] = {
-       [chip_8001] = {  8, &pm8001_8001_dispatch,},
+       [chip_8001] = {0,  8, &pm8001_8001_dispatch,},
+       [chip_8008] = {0,  8, &pm8001_80xx_dispatch,},
+       [chip_8009] = {1,  8, &pm8001_80xx_dispatch,},
+       [chip_8018] = {0,  16, &pm8001_80xx_dispatch,},
+       [chip_8019] = {1,  16, &pm8001_80xx_dispatch,},
 };
 static int pm8001_id;
 
@@ -155,37 +163,75 @@ static void pm8001_free(struct pm8001_hba_info *pm8001_ha)
 }
 
 #ifdef PM8001_USE_TASKLET
+
+/**
+ * tasklet for 64 msi-x interrupt handler
+ * @opaque: the passed general host adapter struct
+ * Note: pm8001_tasklet is common for pm8001 & pm80xx
+ */
 static void pm8001_tasklet(unsigned long opaque)
 {
        struct pm8001_hba_info *pm8001_ha;
+       u32 vec;
        pm8001_ha = (struct pm8001_hba_info *)opaque;
        if (unlikely(!pm8001_ha))
                BUG_ON(1);
-       PM8001_CHIP_DISP->isr(pm8001_ha);
+       vec = pm8001_ha->int_vector;
+       PM8001_CHIP_DISP->isr(pm8001_ha, vec);
+}
+#endif
+
+static struct  pm8001_hba_info *outq_to_hba(u8 *outq)
+{
+       return container_of((outq - *outq), struct pm8001_hba_info, outq[0]);
 }
+
+/**
+ * pm8001_interrupt_handler_msix - main MSIX interrupt handler.
+ * It obtains the vector number and calls the equivalent bottom
+ * half or services directly.
+ * @opaque: the passed outbound queue/vector. Host structure is
+ * retrieved from the same.
+ */
+static irqreturn_t pm8001_interrupt_handler_msix(int irq, void *opaque)
+{
+       struct pm8001_hba_info *pm8001_ha = outq_to_hba(opaque);
+       u8 outq = *(u8 *)opaque;
+       irqreturn_t ret = IRQ_HANDLED;
+       if (unlikely(!pm8001_ha))
+               return IRQ_NONE;
+       if (!PM8001_CHIP_DISP->is_our_interupt(pm8001_ha))
+               return IRQ_NONE;
+       pm8001_ha->int_vector = outq;
+#ifdef PM8001_USE_TASKLET
+       tasklet_schedule(&pm8001_ha->tasklet);
+#else
+       ret = PM8001_CHIP_DISP->isr(pm8001_ha, outq);
 #endif
+       return ret;
+}
 
+/**
+ * pm8001_interrupt_handler_intx - main INTx interrupt handler.
+ * @dev_id: sas_ha structure. The HBA is retrieved from sas_has structure.
+ */
 
- /**
-  * pm8001_interrupt - when HBA originate a interrupt,we should invoke this
-  * dispatcher to handle each case.
-  * @irq: irq number.
-  * @opaque: the passed general host adapter struct
-  */
-static irqreturn_t pm8001_interrupt(int irq, void *opaque)
+static irqreturn_t pm8001_interrupt_handler_intx(int irq, void *dev_id)
 {
        struct pm8001_hba_info *pm8001_ha;
        irqreturn_t ret = IRQ_HANDLED;
-       struct sas_ha_struct *sha = opaque;
+       struct sas_ha_struct *sha = dev_id;
        pm8001_ha = sha->lldd_ha;
        if (unlikely(!pm8001_ha))
                return IRQ_NONE;
        if (!PM8001_CHIP_DISP->is_our_interupt(pm8001_ha))
                return IRQ_NONE;
+
+       pm8001_ha->int_vector = 0;
 #ifdef PM8001_USE_TASKLET
        tasklet_schedule(&pm8001_ha->tasklet);
 #else
-       ret = PM8001_CHIP_DISP->isr(pm8001_ha);
+       ret = PM8001_CHIP_DISP->isr(pm8001_ha, 0);
 #endif
        return ret;
 }
@@ -195,10 +241,14 @@ static irqreturn_t pm8001_interrupt(int irq, void *opaque)
  * @pm8001_ha:our hba structure.
  *
  */
-static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha)
+static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha,
+                       const struct pci_device_id *ent)
 {
        int i;
        spin_lock_init(&pm8001_ha->lock);
+       PM8001_INIT_DBG(pm8001_ha,
+               pm8001_printk("pm8001_alloc: PHY:%x\n",
+                               pm8001_ha->chip->n_phy));
        for (i = 0; i < pm8001_ha->chip->n_phy; i++) {
                pm8001_phy_init(pm8001_ha, i);
                pm8001_ha->port[i].wide_port_phymap = 0;
@@ -222,30 +272,57 @@ static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha)
        pm8001_ha->memoryMap.region[IOP].total_len = PM8001_EVENT_LOG_SIZE;
        pm8001_ha->memoryMap.region[IOP].alignment = 32;
 
-       /* MPI Memory region 3 for consumer Index of inbound queues */
-       pm8001_ha->memoryMap.region[CI].num_elements = 1;
-       pm8001_ha->memoryMap.region[CI].element_size = 4;
-       pm8001_ha->memoryMap.region[CI].total_len = 4;
-       pm8001_ha->memoryMap.region[CI].alignment = 4;
-
-       /* MPI Memory region 4 for producer Index of outbound queues */
-       pm8001_ha->memoryMap.region[PI].num_elements = 1;
-       pm8001_ha->memoryMap.region[PI].element_size = 4;
-       pm8001_ha->memoryMap.region[PI].total_len = 4;
-       pm8001_ha->memoryMap.region[PI].alignment = 4;
-
-       /* MPI Memory region 5 inbound queues */
-       pm8001_ha->memoryMap.region[IB].num_elements = PM8001_MPI_QUEUE;
-       pm8001_ha->memoryMap.region[IB].element_size = 64;
-       pm8001_ha->memoryMap.region[IB].total_len = PM8001_MPI_QUEUE * 64;
-       pm8001_ha->memoryMap.region[IB].alignment = 64;
-
-       /* MPI Memory region 6 outbound queues */
-       pm8001_ha->memoryMap.region[OB].num_elements = PM8001_MPI_QUEUE;
-       pm8001_ha->memoryMap.region[OB].element_size = 64;
-       pm8001_ha->memoryMap.region[OB].total_len = PM8001_MPI_QUEUE * 64;
-       pm8001_ha->memoryMap.region[OB].alignment = 64;
+       for (i = 0; i < PM8001_MAX_SPCV_INB_NUM; i++) {
+               /* MPI Memory region 3 for consumer Index of inbound queues */
+               pm8001_ha->memoryMap.region[CI+i].num_elements = 1;
+               pm8001_ha->memoryMap.region[CI+i].element_size = 4;
+               pm8001_ha->memoryMap.region[CI+i].total_len = 4;
+               pm8001_ha->memoryMap.region[CI+i].alignment = 4;
+
+               if ((ent->driver_data) != chip_8001) {
+                       /* MPI Memory region 5 inbound queues */
+                       pm8001_ha->memoryMap.region[IB+i].num_elements =
+                                               PM8001_MPI_QUEUE;
+                       pm8001_ha->memoryMap.region[IB+i].element_size = 128;
+                       pm8001_ha->memoryMap.region[IB+i].total_len =
+                                               PM8001_MPI_QUEUE * 128;
+                       pm8001_ha->memoryMap.region[IB+i].alignment = 128;
+               } else {
+                       pm8001_ha->memoryMap.region[IB+i].num_elements =
+                                               PM8001_MPI_QUEUE;
+                       pm8001_ha->memoryMap.region[IB+i].element_size = 64;
+                       pm8001_ha->memoryMap.region[IB+i].total_len =
+                                               PM8001_MPI_QUEUE * 64;
+                       pm8001_ha->memoryMap.region[IB+i].alignment = 64;
+               }
+       }
+
+       for (i = 0; i < PM8001_MAX_SPCV_OUTB_NUM; i++) {
+               /* MPI Memory region 4 for producer Index of outbound queues */
+               pm8001_ha->memoryMap.region[PI+i].num_elements = 1;
+               pm8001_ha->memoryMap.region[PI+i].element_size = 4;
+               pm8001_ha->memoryMap.region[PI+i].total_len = 4;
+               pm8001_ha->memoryMap.region[PI+i].alignment = 4;
+
+               if (ent->driver_data != chip_8001) {
+                       /* MPI Memory region 6 Outbound queues */
+                       pm8001_ha->memoryMap.region[OB+i].num_elements =
+                                               PM8001_MPI_QUEUE;
+                       pm8001_ha->memoryMap.region[OB+i].element_size = 128;
+                       pm8001_ha->memoryMap.region[OB+i].total_len =
+                                               PM8001_MPI_QUEUE * 128;
+                       pm8001_ha->memoryMap.region[OB+i].alignment = 128;
+               } else {
+                       /* MPI Memory region 6 Outbound queues */
+                       pm8001_ha->memoryMap.region[OB+i].num_elements =
+                                               PM8001_MPI_QUEUE;
+                       pm8001_ha->memoryMap.region[OB+i].element_size = 64;
+                       pm8001_ha->memoryMap.region[OB+i].total_len =
+                                               PM8001_MPI_QUEUE * 64;
+                       pm8001_ha->memoryMap.region[OB+i].alignment = 64;
+               }
 
+       }
        /* Memory region write DMA*/
        pm8001_ha->memoryMap.region[NVMD].num_elements = 1;
        pm8001_ha->memoryMap.region[NVMD].element_size = 4096;
@@ -264,6 +341,9 @@ static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha)
        pm8001_ha->memoryMap.region[CCB_MEM].total_len = PM8001_MAX_CCB *
                sizeof(struct pm8001_ccb_info);
 
+       /* Memory region for fw flash */
+       pm8001_ha->memoryMap.region[FW_FLASH].total_len = 4096;
+
        for (i = 0; i < USI_MAX_MEMCNT; i++) {
                if (pm8001_mem_alloc(pm8001_ha->pdev,
                        &pm8001_ha->memoryMap.region[i].virt_ptr,
@@ -281,7 +361,7 @@ static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha)
 
        pm8001_ha->devices = pm8001_ha->memoryMap.region[DEV_MEM].virt_ptr;
        for (i = 0; i < PM8001_MAX_DEVICES; i++) {
-               pm8001_ha->devices[i].dev_type = NO_DEVICE;
+               pm8001_ha->devices[i].dev_type = SAS_PHY_UNUSED;
                pm8001_ha->devices[i].id = i;
                pm8001_ha->devices[i].device_id = PM8001_MAX_DEVICES;
                pm8001_ha->devices[i].running_req = 0;
@@ -339,10 +419,12 @@ static int pm8001_ioremap(struct pm8001_hba_info *pm8001_ha)
                                ioremap(pm8001_ha->io_mem[logicalBar].membase,
                                pm8001_ha->io_mem[logicalBar].memsize);
                        PM8001_INIT_DBG(pm8001_ha,
-                               pm8001_printk("PCI: bar %d, logicalBar %d "
-                               "virt_addr=%lx,len=%d\n", bar, logicalBar,
-                               (unsigned long)
-                               pm8001_ha->io_mem[logicalBar].memvirtaddr,
+                               pm8001_printk("PCI: bar %d, logicalBar %d ",
+                               bar, logicalBar));
+                       PM8001_INIT_DBG(pm8001_ha, pm8001_printk(
+                               "base addr %llx virt_addr=%llx len=%d\n",
+                               (u64)pm8001_ha->io_mem[logicalBar].membase,
+                               (u64)pm8001_ha->io_mem[logicalBar].memvirtaddr,
                                pm8001_ha->io_mem[logicalBar].memsize));
                } else {
                        pm8001_ha->io_mem[logicalBar].membase   = 0;
@@ -361,8 +443,9 @@ static int pm8001_ioremap(struct pm8001_hba_info *pm8001_ha)
  * @shost: scsi host struct which has been initialized before.
  */
 static struct pm8001_hba_info *pm8001_pci_alloc(struct pci_dev *pdev,
-                                               u32 chip_id,
-                                               struct Scsi_Host *shost)
+                                const struct pci_device_id *ent,
+                               struct Scsi_Host *shost)
+
 {
        struct pm8001_hba_info *pm8001_ha;
        struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
@@ -374,7 +457,7 @@ static struct pm8001_hba_info *pm8001_pci_alloc(struct pci_dev *pdev,
 
        pm8001_ha->pdev = pdev;
        pm8001_ha->dev = &pdev->dev;
-       pm8001_ha->chip_id = chip_id;
+       pm8001_ha->chip_id = ent->driver_data;
        pm8001_ha->chip = &pm8001_chips[pm8001_ha->chip_id];
        pm8001_ha->irq = pdev->irq;
        pm8001_ha->sas = sha;
@@ -382,12 +465,22 @@ static struct pm8001_hba_info *pm8001_pci_alloc(struct pci_dev *pdev,
        pm8001_ha->id = pm8001_id++;
        pm8001_ha->logging_level = 0x01;
        sprintf(pm8001_ha->name, "%s%d", DRV_NAME, pm8001_ha->id);
+       /* IOMB size is 128 for 8088/89 controllers */
+       if (pm8001_ha->chip_id != chip_8001)
+               pm8001_ha->iomb_size = IOMB_SIZE_SPCV;
+       else
+               pm8001_ha->iomb_size = IOMB_SIZE_SPC;
+
 #ifdef PM8001_USE_TASKLET
+       /**
+       * default tasklet for non msi-x interrupt handler/first msi-x
+       * interrupt handler
+       **/
        tasklet_init(&pm8001_ha->tasklet, pm8001_tasklet,
-               (unsigned long)pm8001_ha);
+                       (unsigned long)pm8001_ha);
 #endif
        pm8001_ioremap(pm8001_ha);
-       if (!pm8001_alloc(pm8001_ha))
+       if (!pm8001_alloc(pm8001_ha, ent))
                return pm8001_ha;
        pm8001_free(pm8001_ha);
        return NULL;
@@ -512,21 +605,50 @@ static void  pm8001_post_sas_ha_init(struct Scsi_Host *shost,
  */
 static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha)
 {
-       u8 i;
+       u8 i, j;
 #ifdef PM8001_READ_VPD
+       /* For new SPC controllers WWN is stored in flash vpd
+       *  For SPC/SPCve controllers WWN is stored in EEPROM
+       *  For Older SPC WWN is stored in NVMD
+       */
        DECLARE_COMPLETION_ONSTACK(completion);
        struct pm8001_ioctl_payload payload;
+       u16 deviceid;
+       pci_read_config_word(pm8001_ha->pdev, PCI_DEVICE_ID, &deviceid);
        pm8001_ha->nvmd_completion = &completion;
-       payload.minor_function = 0;
-       payload.length = 128;
-       payload.func_specific = kzalloc(128, GFP_KERNEL);
+
+       if (pm8001_ha->chip_id == chip_8001) {
+               if (deviceid == 0x8081) {
+                       payload.minor_function = 4;
+                       payload.length = 4096;
+               } else {
+                       payload.minor_function = 0;
+                       payload.length = 128;
+               }
+       } else {
+               payload.minor_function = 1;
+               payload.length = 4096;
+       }
+       payload.offset = 0;
+       payload.func_specific = kzalloc(payload.length, GFP_KERNEL);
        PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload);
        wait_for_completion(&completion);
+
+       for (i = 0, j = 0; i <= 7; i++, j++) {
+               if (pm8001_ha->chip_id == chip_8001) {
+                       if (deviceid == 0x8081)
+                               pm8001_ha->sas_addr[j] =
+                                       payload.func_specific[0x704 + i];
+               } else
+                       pm8001_ha->sas_addr[j] =
+                                       payload.func_specific[0x804 + i];
+       }
+
        for (i = 0; i < pm8001_ha->chip->n_phy; i++) {
-               memcpy(&pm8001_ha->phy[i].dev_sas_addr, pm8001_ha->sas_addr,
-                       SAS_ADDR_SIZE);
+               memcpy(&pm8001_ha->phy[i].dev_sas_addr,
+                       pm8001_ha->sas_addr, SAS_ADDR_SIZE);
                PM8001_INIT_DBG(pm8001_ha,
-                       pm8001_printk("phy %d sas_addr = %016llx \n", i,
+                       pm8001_printk("phy %d sas_addr = %016llx\n", i,
                        pm8001_ha->phy[i].dev_sas_addr));
        }
 #else
@@ -547,31 +669,50 @@ static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha)
  * @chip_info: our ha struct.
  * @irq_handler: irq_handler
  */
-static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha,
-       irq_handler_t irq_handler)
+static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha)
 {
        u32 i = 0, j = 0;
-       u32 number_of_intr = 1;
+       u32 number_of_intr;
        int flag = 0;
        u32 max_entry;
        int rc;
+       static char intr_drvname[PM8001_MAX_MSIX_VEC][sizeof(DRV_NAME)+3];
+
+       /* SPCv controllers supports 64 msi-x */
+       if (pm8001_ha->chip_id == chip_8001) {
+               number_of_intr = 1;
+               flag |= IRQF_DISABLED;
+       } else {
+               number_of_intr = PM8001_MAX_MSIX_VEC;
+               flag &= ~IRQF_SHARED;
+               flag |= IRQF_DISABLED;
+       }
+
        max_entry = sizeof(pm8001_ha->msix_entries) /
                sizeof(pm8001_ha->msix_entries[0]);
-       flag |= IRQF_DISABLED;
        for (i = 0; i < max_entry ; i++)
                pm8001_ha->msix_entries[i].entry = i;
        rc = pci_enable_msix(pm8001_ha->pdev, pm8001_ha->msix_entries,
                number_of_intr);
        pm8001_ha->number_of_intr = number_of_intr;
        if (!rc) {
+               PM8001_INIT_DBG(pm8001_ha, pm8001_printk(
+                       "pci_enable_msix request ret:%d no of intr %d\n",
+                                       rc, pm8001_ha->number_of_intr));
+
+               for (i = 0; i < number_of_intr; i++)
+                       pm8001_ha->outq[i] = i;
+
                for (i = 0; i < number_of_intr; i++) {
+                       snprintf(intr_drvname[i], sizeof(intr_drvname[0]),
+                                       DRV_NAME"%d", i);
                        if (request_irq(pm8001_ha->msix_entries[i].vector,
-                               irq_handler, flag, DRV_NAME,
-                               SHOST_TO_SAS_HA(pm8001_ha->shost))) {
+                               pm8001_interrupt_handler_msix, flag,
+                               intr_drvname[i], &pm8001_ha->outq[i])) {
                                for (j = 0; j < i; j++)
                                        free_irq(
                                        pm8001_ha->msix_entries[j].vector,
-                                       SHOST_TO_SAS_HA(pm8001_ha->shost));
+                                       &pm8001_ha->outq[j]);
                                pci_disable_msix(pm8001_ha->pdev);
                                break;
                        }
@@ -588,22 +729,24 @@ static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha,
 static u32 pm8001_request_irq(struct pm8001_hba_info *pm8001_ha)
 {
        struct pci_dev *pdev;
-       irq_handler_t irq_handler = pm8001_interrupt;
        int rc;
 
        pdev = pm8001_ha->pdev;
 
 #ifdef PM8001_USE_MSIX
        if (pci_find_capability(pdev, PCI_CAP_ID_MSIX))
-               return pm8001_setup_msix(pm8001_ha, irq_handler);
-       else
+               return pm8001_setup_msix(pm8001_ha);
+       else {
+               PM8001_INIT_DBG(pm8001_ha,
+                       pm8001_printk("MSIX not supported!!!\n"));
                goto intx;
+       }
 #endif
 
 intx:
        /* initialize the INT-X interrupt */
-       rc = request_irq(pdev->irq, irq_handler, IRQF_SHARED, DRV_NAME,
-               SHOST_TO_SAS_HA(pm8001_ha->shost));
+       rc = request_irq(pdev->irq, pm8001_interrupt_handler_intx, IRQF_SHARED,
+               DRV_NAME, SHOST_TO_SAS_HA(pm8001_ha->shost));
        return rc;
 }
 
@@ -621,12 +764,13 @@ static int pm8001_pci_probe(struct pci_dev *pdev,
 {
        unsigned int rc;
        u32     pci_reg;
+       u8      i = 0;
        struct pm8001_hba_info *pm8001_ha;
        struct Scsi_Host *shost = NULL;
        const struct pm8001_chip_info *chip;
 
        dev_printk(KERN_INFO, &pdev->dev,
-               "pm8001: driver version %s\n", DRV_VERSION);
+               "pm80xx: driver version %s\n", DRV_VERSION);
        rc = pci_enable_device(pdev);
        if (rc)
                goto err_out_enable;
@@ -665,25 +809,39 @@ static int pm8001_pci_probe(struct pci_dev *pdev,
                goto err_out_free;
        }
        pci_set_drvdata(pdev, SHOST_TO_SAS_HA(shost));
-       pm8001_ha = pm8001_pci_alloc(pdev, chip_8001, shost);
+       /* ent->driver variable is used to differentiate between controllers */
+       pm8001_ha = pm8001_pci_alloc(pdev, ent, shost);
        if (!pm8001_ha) {
                rc = -ENOMEM;
                goto err_out_free;
        }
        list_add_tail(&pm8001_ha->list, &hba_list);
-       PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha, 0x252acbcd);
+       PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha);
        rc = PM8001_CHIP_DISP->chip_init(pm8001_ha);
-       if (rc)
+       if (rc) {
+               PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
+                       "chip_init failed [ret: %d]\n", rc));
                goto err_out_ha_free;
+       }
 
        rc = scsi_add_host(shost, &pdev->dev);
        if (rc)
                goto err_out_ha_free;
        rc = pm8001_request_irq(pm8001_ha);
-       if (rc)
+       if (rc) {
+               PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
+                       "pm8001_request_irq failed [ret: %d]\n", rc));
                goto err_out_shost;
+       }
+
+       PM8001_CHIP_DISP->interrupt_enable(pm8001_ha, 0);
+       if (pm8001_ha->chip_id != chip_8001) {
+               for (i = 1; i < pm8001_ha->number_of_intr; i++)
+                       PM8001_CHIP_DISP->interrupt_enable(pm8001_ha, i);
+               /* setup thermal configuration. */
+               pm80xx_set_thermal_config(pm8001_ha);
+       }
 
-       PM8001_CHIP_DISP->interrupt_enable(pm8001_ha);
        pm8001_init_sas_add(pm8001_ha);
        pm8001_post_sas_ha_init(shost, chip);
        rc = sas_register_ha(SHOST_TO_SAS_HA(shost));
@@ -719,14 +877,15 @@ static void pm8001_pci_remove(struct pci_dev *pdev)
        sas_remove_host(pm8001_ha->shost);
        list_del(&pm8001_ha->list);
        scsi_remove_host(pm8001_ha->shost);
-       PM8001_CHIP_DISP->interrupt_disable(pm8001_ha);
-       PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha, 0x252acbcd);
+       PM8001_CHIP_DISP->interrupt_disable(pm8001_ha, 0xFF);
+       PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha);
 
 #ifdef PM8001_USE_MSIX
        for (i = 0; i < pm8001_ha->number_of_intr; i++)
                synchronize_irq(pm8001_ha->msix_entries[i].vector);
        for (i = 0; i < pm8001_ha->number_of_intr; i++)
-               free_irq(pm8001_ha->msix_entries[i].vector, sha);
+               free_irq(pm8001_ha->msix_entries[i].vector,
+                               &pm8001_ha->outq[i]);
        pci_disable_msix(pdev);
 #else
        free_irq(pm8001_ha->irq, sha);
@@ -763,13 +922,14 @@ static int pm8001_pci_suspend(struct pci_dev *pdev, pm_message_t state)
                printk(KERN_ERR " PCI PM not supported\n");
                return -ENODEV;
        }
-       PM8001_CHIP_DISP->interrupt_disable(pm8001_ha);
-       PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha, 0x252acbcd);
+       PM8001_CHIP_DISP->interrupt_disable(pm8001_ha, 0xFF);
+       PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha);
 #ifdef PM8001_USE_MSIX
        for (i = 0; i < pm8001_ha->number_of_intr; i++)
                synchronize_irq(pm8001_ha->msix_entries[i].vector);
        for (i = 0; i < pm8001_ha->number_of_intr; i++)
-               free_irq(pm8001_ha->msix_entries[i].vector, sha);
+               free_irq(pm8001_ha->msix_entries[i].vector,
+                               &pm8001_ha->outq[i]);
        pci_disable_msix(pdev);
 #else
        free_irq(pm8001_ha->irq, sha);
@@ -798,6 +958,7 @@ static int pm8001_pci_resume(struct pci_dev *pdev)
        struct sas_ha_struct *sha = pci_get_drvdata(pdev);
        struct pm8001_hba_info *pm8001_ha;
        int rc;
+       u8 i = 0;
        u32 device_state;
        pm8001_ha = sha->lldd_ha;
        device_state = pdev->current_state;
@@ -820,19 +981,33 @@ static int pm8001_pci_resume(struct pci_dev *pdev)
        if (rc)
                goto err_out_disable;
 
-       PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha, 0x252acbcd);
+       /* chip soft rst only for spc */
+       if (pm8001_ha->chip_id == chip_8001) {
+               PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha);
+               PM8001_INIT_DBG(pm8001_ha,
+                       pm8001_printk("chip soft reset successful\n"));
+       }
        rc = PM8001_CHIP_DISP->chip_init(pm8001_ha);
        if (rc)
                goto err_out_disable;
-       PM8001_CHIP_DISP->interrupt_disable(pm8001_ha);
+
+       /* disable all the interrupt bits */
+       PM8001_CHIP_DISP->interrupt_disable(pm8001_ha, 0xFF);
+
        rc = pm8001_request_irq(pm8001_ha);
        if (rc)
                goto err_out_disable;
-       #ifdef PM8001_USE_TASKLET
+#ifdef PM8001_USE_TASKLET
+       /* default tasklet for non msi-x interrupt handler/first msi-x
+       * interrupt handler */
        tasklet_init(&pm8001_ha->tasklet, pm8001_tasklet,
-                   (unsigned long)pm8001_ha);
-       #endif
-       PM8001_CHIP_DISP->interrupt_enable(pm8001_ha);
+                       (unsigned long)pm8001_ha);
+#endif
+       PM8001_CHIP_DISP->interrupt_enable(pm8001_ha, 0);
+       if (pm8001_ha->chip_id != chip_8001) {
+               for (i = 1; i < pm8001_ha->number_of_intr; i++)
+                       PM8001_CHIP_DISP->interrupt_enable(pm8001_ha, i);
+       }
        scsi_unblock_requests(pm8001_ha->shost);
        return 0;
 
@@ -843,14 +1018,45 @@ err_out_enable:
        return rc;
 }
 
+/* update of pci device, vendor id and driver data with
+ * unique value for each of the controller
+ */
 static struct pci_device_id pm8001_pci_table[] = {
-       {
-               PCI_VDEVICE(PMC_Sierra, 0x8001), chip_8001
-       },
+       { PCI_VDEVICE(PMC_Sierra, 0x8001), chip_8001 },
        {
                PCI_DEVICE(0x117c, 0x0042),
                .driver_data = chip_8001
        },
+       /* Support for SPC/SPCv/SPCve controllers */
+       { PCI_VDEVICE(ADAPTEC2, 0x8001), chip_8001 },
+       { PCI_VDEVICE(PMC_Sierra, 0x8008), chip_8008 },
+       { PCI_VDEVICE(ADAPTEC2, 0x8008), chip_8008 },
+       { PCI_VDEVICE(PMC_Sierra, 0x8018), chip_8018 },
+       { PCI_VDEVICE(ADAPTEC2, 0x8018), chip_8018 },
+       { PCI_VDEVICE(PMC_Sierra, 0x8009), chip_8009 },
+       { PCI_VDEVICE(ADAPTEC2, 0x8009), chip_8009 },
+       { PCI_VDEVICE(PMC_Sierra, 0x8019), chip_8019 },
+       { PCI_VDEVICE(ADAPTEC2, 0x8019), chip_8019 },
+       { PCI_VENDOR_ID_ADAPTEC2, 0x8081,
+               PCI_VENDOR_ID_ADAPTEC2, 0x0400, 0, 0, chip_8001 },
+       { PCI_VENDOR_ID_ADAPTEC2, 0x8081,
+               PCI_VENDOR_ID_ADAPTEC2, 0x0800, 0, 0, chip_8001 },
+       { PCI_VENDOR_ID_ADAPTEC2, 0x8088,
+               PCI_VENDOR_ID_ADAPTEC2, 0x0008, 0, 0, chip_8008 },
+       { PCI_VENDOR_ID_ADAPTEC2, 0x8088,
+               PCI_VENDOR_ID_ADAPTEC2, 0x0800, 0, 0, chip_8008 },
+       { PCI_VENDOR_ID_ADAPTEC2, 0x8089,
+               PCI_VENDOR_ID_ADAPTEC2, 0x0008, 0, 0, chip_8009 },
+       { PCI_VENDOR_ID_ADAPTEC2, 0x8089,
+               PCI_VENDOR_ID_ADAPTEC2, 0x0800, 0, 0, chip_8009 },
+       { PCI_VENDOR_ID_ADAPTEC2, 0x8088,
+               PCI_VENDOR_ID_ADAPTEC2, 0x0016, 0, 0, chip_8018 },
+       { PCI_VENDOR_ID_ADAPTEC2, 0x8088,
+               PCI_VENDOR_ID_ADAPTEC2, 0x1600, 0, 0, chip_8018 },
+       { PCI_VENDOR_ID_ADAPTEC2, 0x8089,
+               PCI_VENDOR_ID_ADAPTEC2, 0x0016, 0, 0, chip_8019 },
+       { PCI_VENDOR_ID_ADAPTEC2, 0x8089,
+               PCI_VENDOR_ID_ADAPTEC2, 0x1600, 0, 0, chip_8019 },
        {} /* terminate list */
 };
 
@@ -870,7 +1076,7 @@ static int __init pm8001_init(void)
 {
        int rc = -ENOMEM;
 
-       pm8001_wq = alloc_workqueue("pm8001", 0, 0);
+       pm8001_wq = alloc_workqueue("pm80xx", 0, 0);
        if (!pm8001_wq)
                goto err;
 
@@ -902,7 +1108,8 @@ module_init(pm8001_init);
 module_exit(pm8001_exit);
 
 MODULE_AUTHOR("Jack Wang <jack_wang@usish.com>");
-MODULE_DESCRIPTION("PMC-Sierra PM8001 SAS/SATA controller driver");
+MODULE_DESCRIPTION(
+               "PMC-Sierra PM8001/8081/8088/8089 SAS/SATA controller driver");
 MODULE_VERSION(DRV_VERSION);
 MODULE_LICENSE("GPL");
 MODULE_DEVICE_TABLE(pci, pm8001_pci_table);
index b961112..a85d73d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * PMC-Sierra SPC 8001 SAS/SATA based host adapters driver
+ * PMC-Sierra PM8001/8081/8088/8089 SAS/SATA based host adapters driver
  *
  * Copyright (c) 2008-2009 USI Co., Ltd.
  * All rights reserved.
@@ -68,7 +68,7 @@ static void pm8001_tag_clear(struct pm8001_hba_info *pm8001_ha, u32 tag)
        clear_bit(tag, bitmap);
 }
 
-static void pm8001_tag_free(struct pm8001_hba_info *pm8001_ha, u32 tag)
+void pm8001_tag_free(struct pm8001_hba_info *pm8001_ha, u32 tag)
 {
        pm8001_tag_clear(pm8001_ha, tag);
 }
@@ -212,10 +212,12 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
                break;
        case PHY_FUNC_GET_EVENTS:
                spin_lock_irqsave(&pm8001_ha->lock, flags);
-               if (-1 == pm8001_bar4_shift(pm8001_ha,
+               if (pm8001_ha->chip_id == chip_8001) {
+                       if (-1 == pm8001_bar4_shift(pm8001_ha,
                                        (phy_id < 4) ? 0x30000 : 0x40000)) {
-                       spin_unlock_irqrestore(&pm8001_ha->lock, flags);
-                       return -EINVAL;
+                               spin_unlock_irqrestore(&pm8001_ha->lock, flags);
+                               return -EINVAL;
+                       }
                }
                {
                        struct sas_phy *phy = sas_phy->phy;
@@ -228,7 +230,8 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
                        phy->loss_of_dword_sync_count = qp[3];
                        phy->phy_reset_problem_count = qp[4];
                }
-               pm8001_bar4_shift(pm8001_ha, 0);
+               if (pm8001_ha->chip_id == chip_8001)
+                       pm8001_bar4_shift(pm8001_ha, 0);
                spin_unlock_irqrestore(&pm8001_ha->lock, flags);
                return 0;
        default:
@@ -249,7 +252,9 @@ void pm8001_scan_start(struct Scsi_Host *shost)
        struct pm8001_hba_info *pm8001_ha;
        struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
        pm8001_ha = sha->lldd_ha;
-       PM8001_CHIP_DISP->sas_re_init_req(pm8001_ha);
+       /* SAS_RE_INITIALIZATION not available in SPCv/ve */
+       if (pm8001_ha->chip_id == chip_8001)
+               PM8001_CHIP_DISP->sas_re_init_req(pm8001_ha);
        for (i = 0; i < pm8001_ha->chip->n_phy; ++i)
                PM8001_CHIP_DISP->phy_start_req(pm8001_ha, i);
 }
@@ -352,7 +357,7 @@ static int sas_find_local_port_id(struct domain_device *dev)
   * @tmf: the task management IU
   */
 #define DEV_IS_GONE(pm8001_dev)        \
-       ((!pm8001_dev || (pm8001_dev->dev_type == NO_DEVICE)))
+       ((!pm8001_dev || (pm8001_dev->dev_type == SAS_PHY_UNUSED)))
 static int pm8001_task_exec(struct sas_task *task, const int num,
        gfp_t gfp_flags, int is_tmf, struct pm8001_tmf_task *tmf)
 {
@@ -370,7 +375,7 @@ static int pm8001_task_exec(struct sas_task *task, const int num,
                struct task_status_struct *tsm = &t->task_status;
                tsm->resp = SAS_TASK_UNDELIVERED;
                tsm->stat = SAS_PHY_DOWN;
-               if (dev->dev_type != SATA_DEV)
+               if (dev->dev_type != SAS_SATA_DEV)
                        t->task_done(t);
                return 0;
        }
@@ -548,7 +553,7 @@ struct pm8001_device *pm8001_alloc_dev(struct pm8001_hba_info *pm8001_ha)
 {
        u32 dev;
        for (dev = 0; dev < PM8001_MAX_DEVICES; dev++) {
-               if (pm8001_ha->devices[dev].dev_type == NO_DEVICE) {
+               if (pm8001_ha->devices[dev].dev_type == SAS_PHY_UNUSED) {
                        pm8001_ha->devices[dev].id = dev;
                        return &pm8001_ha->devices[dev];
                }
@@ -560,13 +565,31 @@ struct pm8001_device *pm8001_alloc_dev(struct pm8001_hba_info *pm8001_ha)
        }
        return NULL;
 }
+/**
+  * pm8001_find_dev - find a matching pm8001_device
+  * @pm8001_ha: our hba card information
+  */
+struct pm8001_device *pm8001_find_dev(struct pm8001_hba_info *pm8001_ha,
+                                       u32 device_id)
+{
+       u32 dev;
+       for (dev = 0; dev < PM8001_MAX_DEVICES; dev++) {
+               if (pm8001_ha->devices[dev].device_id == device_id)
+                       return &pm8001_ha->devices[dev];
+       }
+       if (dev == PM8001_MAX_DEVICES) {
+               PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("NO MATCHING "
+                               "DEVICE FOUND !!!\n"));
+       }
+       return NULL;
+}
 
 static void pm8001_free_dev(struct pm8001_device *pm8001_dev)
 {
        u32 id = pm8001_dev->id;
        memset(pm8001_dev, 0, sizeof(*pm8001_dev));
        pm8001_dev->id = id;
-       pm8001_dev->dev_type = NO_DEVICE;
+       pm8001_dev->dev_type = SAS_PHY_UNUSED;
        pm8001_dev->device_id = PM8001_MAX_DEVICES;
        pm8001_dev->sas_device = NULL;
 }
@@ -624,7 +647,7 @@ static int pm8001_dev_found_notify(struct domain_device *dev)
                        res = -1;
                }
        } else {
-               if (dev->dev_type == SATA_DEV) {
+               if (dev->dev_type == SAS_SATA_DEV) {
                        pm8001_device->attached_phy =
                                dev->rphy->identify.phy_identifier;
                                flag = 1; /* directly sata*/
@@ -634,7 +657,7 @@ static int pm8001_dev_found_notify(struct domain_device *dev)
        PM8001_CHIP_DISP->reg_dev_req(pm8001_ha, pm8001_device, flag);
        spin_unlock_irqrestore(&pm8001_ha->lock, flags);
        wait_for_completion(&completion);
-       if (dev->dev_type == SAS_END_DEV)
+       if (dev->dev_type == SAS_END_DEVICE)
                msleep(50);
        pm8001_ha->flags = PM8001F_RUN_TIME;
        return 0;
@@ -648,7 +671,7 @@ int pm8001_dev_found(struct domain_device *dev)
        return pm8001_dev_found_notify(dev);
 }
 
-static void pm8001_task_done(struct sas_task *task)
+void pm8001_task_done(struct sas_task *task)
 {
        if (!del_timer(&task->slow_task->timer))
                return;
@@ -904,7 +927,7 @@ void pm8001_open_reject_retry(
                struct pm8001_ccb_info *ccb = &pm8001_ha->ccb_info[i];
 
                pm8001_dev = ccb->device;
-               if (!pm8001_dev || (pm8001_dev->dev_type == NO_DEVICE))
+               if (!pm8001_dev || (pm8001_dev->dev_type == SAS_PHY_UNUSED))
                        continue;
                if (!device_to_close) {
                        uintptr_t d = (uintptr_t)pm8001_dev
@@ -995,6 +1018,72 @@ int pm8001_I_T_nexus_reset(struct domain_device *dev)
        return rc;
 }
 
+/*
+* This function handle the IT_NEXUS_XXX event or completion
+* status code for SSP/SATA/SMP I/O request.
+*/
+int pm8001_I_T_nexus_event_handler(struct domain_device *dev)
+{
+       int rc = TMF_RESP_FUNC_FAILED;
+       struct pm8001_device *pm8001_dev;
+       struct pm8001_hba_info *pm8001_ha;
+       struct sas_phy *phy;
+       u32 device_id = 0;
+
+       if (!dev || !dev->lldd_dev)
+               return -1;
+
+       pm8001_dev = dev->lldd_dev;
+       device_id = pm8001_dev->device_id;
+       pm8001_ha = pm8001_find_ha_by_dev(dev);
+
+       PM8001_EH_DBG(pm8001_ha,
+                       pm8001_printk("I_T_Nexus handler invoked !!"));
+
+       phy = sas_get_local_phy(dev);
+
+       if (dev_is_sata(dev)) {
+               DECLARE_COMPLETION_ONSTACK(completion_setstate);
+               if (scsi_is_sas_phy_local(phy)) {
+                       rc = 0;
+                       goto out;
+               }
+               /* send internal ssp/sata/smp abort command to FW */
+               rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev ,
+                                                       dev, 1, 0);
+               msleep(100);
+
+               /* deregister the target device */
+               pm8001_dev_gone_notify(dev);
+               msleep(200);
+
+               /*send phy reset to hard reset target */
+               rc = sas_phy_reset(phy, 1);
+               msleep(2000);
+               pm8001_dev->setds_completion = &completion_setstate;
+
+               wait_for_completion(&completion_setstate);
+       } else {
+               /* send internal ssp/sata/smp abort command to FW */
+               rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev ,
+                                                       dev, 1, 0);
+               msleep(100);
+
+               /* deregister the target device */
+               pm8001_dev_gone_notify(dev);
+               msleep(200);
+
+               /*send phy reset to hard reset target */
+               rc = sas_phy_reset(phy, 1);
+               msleep(2000);
+       }
+       PM8001_EH_DBG(pm8001_ha, pm8001_printk(" for device[%x]:rc=%d\n",
+               pm8001_dev->device_id, rc));
+out:
+       sas_put_local_phy(phy);
+
+       return rc;
+}
 /* mandatory SAM-3, the task reset the specified LUN*/
 int pm8001_lu_reset(struct domain_device *dev, u8 *lun)
 {
index 1100820..5708194 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * PMC-Sierra SPC 8001 SAS/SATA based host adapters driver
+ * PMC-Sierra PM8001/8081/8088/8089 SAS/SATA based host adapters driver
  *
  * Copyright (c) 2008-2009 USI Co., Ltd.
  * All rights reserved.
@@ -57,8 +57,8 @@
 #include <linux/atomic.h>
 #include "pm8001_defs.h"
 
-#define DRV_NAME               "pm8001"
-#define DRV_VERSION            "0.1.36"
+#define DRV_NAME               "pm80xx"
+#define DRV_VERSION            "0.1.37"
 #define PM8001_FAIL_LOGGING    0x01 /* Error message logging */
 #define PM8001_INIT_LOGGING    0x02 /* driver init logging */
 #define PM8001_DISC_LOGGING    0x04 /* discovery layer logging */
@@ -66,8 +66,8 @@
 #define PM8001_EH_LOGGING      0x10 /* libsas EH function logging*/
 #define PM8001_IOCTL_LOGGING   0x20 /* IOCTL message logging */
 #define PM8001_MSG_LOGGING     0x40 /* misc message logging */
-#define pm8001_printk(format, arg...)  printk(KERN_INFO "%s %d:" format,\
-                               __func__, __LINE__, ## arg)
+#define pm8001_printk(format, arg...)  printk(KERN_INFO "pm80xx %s %d:" \
+                       format, __func__, __LINE__, ## arg)
 #define PM8001_CHECK_LOGGING(HBA, LEVEL, CMD)  \
 do {                                           \
        if (unlikely(HBA->logging_level & LEVEL))       \
@@ -103,11 +103,12 @@ do {                                              \
 #define PM8001_READ_VPD
 
 
-#define DEV_IS_EXPANDER(type)  ((type == EDGE_DEV) || (type == FANOUT_DEV))
+#define DEV_IS_EXPANDER(type)  ((type == SAS_EDGE_EXPANDER_DEVICE) || (type == SAS_FANOUT_EXPANDER_DEVICE))
 
 #define PM8001_NAME_LENGTH             32/* generic length of strings */
 extern struct list_head hba_list;
 extern const struct pm8001_dispatch pm8001_8001_dispatch;
+extern const struct pm8001_dispatch pm8001_80xx_dispatch;
 
 struct pm8001_hba_info;
 struct pm8001_ccb_info;
@@ -131,15 +132,15 @@ struct pm8001_ioctl_payload {
 struct pm8001_dispatch {
        char *name;
        int (*chip_init)(struct pm8001_hba_info *pm8001_ha);
-       int (*chip_soft_rst)(struct pm8001_hba_info *pm8001_ha, u32 signature);
+       int (*chip_soft_rst)(struct pm8001_hba_info *pm8001_ha);
        void (*chip_rst)(struct pm8001_hba_info *pm8001_ha);
        int (*chip_ioremap)(struct pm8001_hba_info *pm8001_ha);
        void (*chip_iounmap)(struct pm8001_hba_info *pm8001_ha);
-       irqreturn_t (*isr)(struct pm8001_hba_info *pm8001_ha);
+       irqreturn_t (*isr)(struct pm8001_hba_info *pm8001_ha, u8 vec);
        u32 (*is_our_interupt)(struct pm8001_hba_info *pm8001_ha);
-       int (*isr_process_oq)(struct pm8001_hba_info *pm8001_ha);
-       void (*interrupt_enable)(struct pm8001_hba_info *pm8001_ha);
-       void (*interrupt_disable)(struct pm8001_hba_info *pm8001_ha);
+       int (*isr_process_oq)(struct pm8001_hba_info *pm8001_ha, u8 vec);
+       void (*interrupt_enable)(struct pm8001_hba_info *pm8001_ha, u8 vec);
+       void (*interrupt_disable)(struct pm8001_hba_info *pm8001_ha, u8 vec);
        void (*make_prd)(struct scatterlist *scatter, int nr, void *prd);
        int (*smp_req)(struct pm8001_hba_info *pm8001_ha,
                struct pm8001_ccb_info *ccb);
@@ -173,6 +174,7 @@ struct pm8001_dispatch {
 };
 
 struct pm8001_chip_info {
+       u32     encrypt;
        u32     n_phy;
        const struct pm8001_dispatch    *dispatch;
 };
@@ -204,7 +206,7 @@ struct pm8001_phy {
 };
 
 struct pm8001_device {
-       enum sas_dev_type       dev_type;
+       enum sas_device_type    dev_type;
        struct domain_device    *sas_device;
        u32                     attached_phy;
        u32                     id;
@@ -256,7 +258,20 @@ struct mpi_mem_req {
        struct mpi_mem          region[USI_MAX_MEMCNT];
 };
 
-struct main_cfg_table {
+struct encrypt {
+       u32     cipher_mode;
+       u32     sec_mode;
+       u32     status;
+       u32     flag;
+};
+
+struct sas_phy_attribute_table {
+       u32     phystart1_16[16];
+       u32     outbound_hw_event_pid1_16[16];
+};
+
+union main_cfg_table {
+       struct {
        u32                     signature;
        u32                     interface_rev;
        u32                     firmware_rev;
@@ -292,19 +307,69 @@ struct main_cfg_table {
        u32                     fatal_err_dump_length1;
        u32                     hda_mode_flag;
        u32                     anolog_setup_table_offset;
+       u32                     rsvd[4];
+       } pm8001_tbl;
+
+       struct {
+       u32                     signature;
+       u32                     interface_rev;
+       u32                     firmware_rev;
+       u32                     max_out_io;
+       u32                     max_sgl;
+       u32                     ctrl_cap_flag;
+       u32                     gst_offset;
+       u32                     inbound_queue_offset;
+       u32                     outbound_queue_offset;
+       u32                     inbound_q_nppd_hppd;
+       u32                     rsvd[8];
+       u32                     crc_core_dump;
+       u32                     rsvd1;
+       u32                     upper_event_log_addr;
+       u32                     lower_event_log_addr;
+       u32                     event_log_size;
+       u32                     event_log_severity;
+       u32                     upper_pcs_event_log_addr;
+       u32                     lower_pcs_event_log_addr;
+       u32                     pcs_event_log_size;
+       u32                     pcs_event_log_severity;
+       u32                     fatal_err_interrupt;
+       u32                     fatal_err_dump_offset0;
+       u32                     fatal_err_dump_length0;
+       u32                     fatal_err_dump_offset1;
+       u32                     fatal_err_dump_length1;
+       u32                     gpio_led_mapping;
+       u32                     analog_setup_table_offset;
+       u32                     int_vec_table_offset;
+       u32                     phy_attr_table_offset;
+       u32                     port_recovery_timer;
+       u32                     interrupt_reassertion_delay;
+       } pm80xx_tbl;
 };
-struct general_status_table {
+
+union general_status_table {
+       struct {
        u32                     gst_len_mpistate;
        u32                     iq_freeze_state0;
        u32                     iq_freeze_state1;
        u32                     msgu_tcnt;
        u32                     iop_tcnt;
-       u32                     reserved;
+       u32                     rsvd;
        u32                     phy_state[8];
-       u32                     reserved1;
-       u32                     reserved2;
-       u32                     reserved3;
+       u32                     gpio_input_val;
+       u32                     rsvd1[2];
+       u32                     recover_err_info[8];
+       } pm8001_tbl;
+       struct {
+       u32                     gst_len_mpistate;
+       u32                     iq_freeze_state0;
+       u32                     iq_freeze_state1;
+       u32                     msgu_tcnt;
+       u32                     iop_tcnt;
+       u32                     rsvd[9];
+       u32                     gpio_input_val;
+       u32                     rsvd1[2];
        u32                     recover_err_info[8];
+       } pm80xx_tbl;
 };
 struct inbound_queue_table {
        u32                     element_pri_size_cnt;
@@ -351,15 +416,21 @@ struct pm8001_hba_info {
        struct device           *dev;
        struct pm8001_hba_memspace io_mem[6];
        struct mpi_mem_req      memoryMap;
+       struct encrypt          encrypt_info; /* support encryption */
        void __iomem    *msg_unit_tbl_addr;/*Message Unit Table Addr*/
        void __iomem    *main_cfg_tbl_addr;/*Main Config Table Addr*/
        void __iomem    *general_stat_tbl_addr;/*General Status Table Addr*/
        void __iomem    *inbnd_q_tbl_addr;/*Inbound Queue Config Table Addr*/
        void __iomem    *outbnd_q_tbl_addr;/*Outbound Queue Config Table Addr*/
-       struct main_cfg_table   main_cfg_tbl;
-       struct general_status_table     gs_tbl;
-       struct inbound_queue_table      inbnd_q_tbl[PM8001_MAX_INB_NUM];
-       struct outbound_queue_table     outbnd_q_tbl[PM8001_MAX_OUTB_NUM];
+       void __iomem    *pspa_q_tbl_addr;
+                       /*MPI SAS PHY attributes Queue Config Table Addr*/
+       void __iomem    *ivt_tbl_addr; /*MPI IVT Table Addr */
+       union main_cfg_table    main_cfg_tbl;
+       union general_status_table      gs_tbl;
+       struct inbound_queue_table      inbnd_q_tbl[PM8001_MAX_SPCV_INB_NUM];
+       struct outbound_queue_table     outbnd_q_tbl[PM8001_MAX_SPCV_OUTB_NUM];
+       struct sas_phy_attribute_table  phy_attr_table;
+                                       /* MPI SAS PHY attributes */
        u8                      sas_addr[SAS_ADDR_SIZE];
        struct sas_ha_struct    *sas;/* SCSI/SAS glue */
        struct Scsi_Host        *shost;
@@ -372,10 +443,12 @@ struct pm8001_hba_info {
        struct pm8001_port      port[PM8001_MAX_PHYS];
        u32                     id;
        u32                     irq;
+       u32                     iomb_size; /* SPC and SPCV IOMB size */
        struct pm8001_device    *devices;
        struct pm8001_ccb_info  *ccb_info;
 #ifdef PM8001_USE_MSIX
-       struct msix_entry       msix_entries[16];/*for msi-x interrupt*/
+       struct msix_entry       msix_entries[PM8001_MAX_MSIX_VEC];
+                                       /*for msi-x interrupt*/
        int                     number_of_intr;/*will be used in remove()*/
 #endif
 #ifdef PM8001_USE_TASKLET
@@ -383,7 +456,10 @@ struct pm8001_hba_info {
 #endif
        u32                     logging_level;
        u32                     fw_status;
+       u32                     smp_exp_mode;
+       u32                     int_vector;
        const struct firmware   *fw_image;
+       u8                      outq[PM8001_MAX_MSIX_VEC];
 };
 
 struct pm8001_work {
@@ -419,6 +495,9 @@ struct pm8001_fw_image_header {
 #define FLASH_UPDATE_DNLD_NOT_SUPPORTED                0x10
 #define FLASH_UPDATE_DISABLED                  0x11
 
+#define        NCQ_READ_LOG_FLAG                       0x80000000
+#define        NCQ_ABORT_ALL_FLAG                      0x40000000
+#define        NCQ_2ND_RLE_FLAG                        0x20000000
 /**
  * brief param structure for firmware flash update.
  */
@@ -484,6 +563,7 @@ int pm8001_dev_found(struct domain_device *dev);
 void pm8001_dev_gone(struct domain_device *dev);
 int pm8001_lu_reset(struct domain_device *dev, u8 *lun);
 int pm8001_I_T_nexus_reset(struct domain_device *dev);
+int pm8001_I_T_nexus_event_handler(struct domain_device *dev);
 int pm8001_query_task(struct sas_task *task);
 void pm8001_open_reject_retry(
        struct pm8001_hba_info *pm8001_ha,
@@ -493,6 +573,61 @@ int pm8001_mem_alloc(struct pci_dev *pdev, void **virt_addr,
        dma_addr_t *pphys_addr, u32 *pphys_addr_hi, u32 *pphys_addr_lo,
        u32 mem_size, u32 align);
 
+void pm8001_chip_iounmap(struct pm8001_hba_info *pm8001_ha);
+int pm8001_mpi_build_cmd(struct pm8001_hba_info *pm8001_ha,
+                       struct inbound_queue_table *circularQ,
+                       u32 opCode, void *payload, u32 responseQueue);
+int pm8001_mpi_msg_free_get(struct inbound_queue_table *circularQ,
+                               u16 messageSize, void **messagePtr);
+u32 pm8001_mpi_msg_free_set(struct pm8001_hba_info *pm8001_ha, void *pMsg,
+                       struct outbound_queue_table *circularQ, u8 bc);
+u32 pm8001_mpi_msg_consume(struct pm8001_hba_info *pm8001_ha,
+                       struct outbound_queue_table *circularQ,
+                       void **messagePtr1, u8 *pBC);
+int pm8001_chip_set_dev_state_req(struct pm8001_hba_info *pm8001_ha,
+                       struct pm8001_device *pm8001_dev, u32 state);
+int pm8001_chip_fw_flash_update_req(struct pm8001_hba_info *pm8001_ha,
+                                       void *payload);
+int pm8001_chip_fw_flash_update_build(struct pm8001_hba_info *pm8001_ha,
+                                       void *fw_flash_updata_info, u32 tag);
+int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha, void *payload);
+int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha, void *payload);
+int pm8001_chip_ssp_tm_req(struct pm8001_hba_info *pm8001_ha,
+                               struct pm8001_ccb_info *ccb,
+                               struct pm8001_tmf_task *tmf);
+int pm8001_chip_abort_task(struct pm8001_hba_info *pm8001_ha,
+                               struct pm8001_device *pm8001_dev,
+                               u8 flag, u32 task_tag, u32 cmd_tag);
+int pm8001_chip_dereg_dev_req(struct pm8001_hba_info *pm8001_ha, u32 device_id);
+void pm8001_chip_make_sg(struct scatterlist *scatter, int nr, void *prd);
+void pm8001_work_fn(struct work_struct *work);
+int pm8001_handle_event(struct pm8001_hba_info *pm8001_ha,
+                                       void *data, int handler);
+void pm8001_mpi_set_dev_state_resp(struct pm8001_hba_info *pm8001_ha,
+                                                       void *piomb);
+void pm8001_mpi_set_nvmd_resp(struct pm8001_hba_info *pm8001_ha,
+                                                       void *piomb);
+void pm8001_mpi_get_nvmd_resp(struct pm8001_hba_info *pm8001_ha,
+                                                       void *piomb);
+int pm8001_mpi_local_phy_ctl(struct pm8001_hba_info *pm8001_ha,
+                                                       void *piomb);
+void pm8001_get_lrate_mode(struct pm8001_phy *phy, u8 link_rate);
+void pm8001_get_attached_sas_addr(struct pm8001_phy *phy, u8 *sas_addr);
+void pm8001_bytes_dmaed(struct pm8001_hba_info *pm8001_ha, int i);
+int pm8001_mpi_reg_resp(struct pm8001_hba_info *pm8001_ha, void *piomb);
+int pm8001_mpi_dereg_resp(struct pm8001_hba_info *pm8001_ha, void *piomb);
+int pm8001_mpi_fw_flash_update_resp(struct pm8001_hba_info *pm8001_ha,
+                                                       void *piomb);
+int pm8001_mpi_general_event(struct pm8001_hba_info *pm8001_ha , void *piomb);
+int pm8001_mpi_task_abort_resp(struct pm8001_hba_info *pm8001_ha, void *piomb);
+struct sas_task *pm8001_alloc_task(void);
+void pm8001_task_done(struct sas_task *task);
+void pm8001_free_task(struct sas_task *task);
+void pm8001_tag_free(struct pm8001_hba_info *pm8001_ha, u32 tag);
+struct pm8001_device *pm8001_find_dev(struct pm8001_hba_info *pm8001_ha,
+                                       u32 device_id);
+int pm80xx_set_thermal_config(struct pm8001_hba_info *pm8001_ha);
+
 int pm8001_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue);
 
 /* ctl shared API */
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
new file mode 100644 (file)
index 0000000..302514d
--- /dev/null
@@ -0,0 +1,4130 @@
+/*
+ * PMC-Sierra SPCv/ve 8088/8089 SAS/SATA based host adapters driver
+ *
+ * Copyright (c) 2008-2009 PMC-Sierra, Inc.,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ *
+ */
+ #include <linux/slab.h>
+ #include "pm8001_sas.h"
+ #include "pm80xx_hwi.h"
+ #include "pm8001_chips.h"
+ #include "pm8001_ctl.h"
+
+#define SMP_DIRECT 1
+#define SMP_INDIRECT 2
+/**
+ * read_main_config_table - read the configure table and save it.
+ * @pm8001_ha: our hba card information
+ */
+static void read_main_config_table(struct pm8001_hba_info *pm8001_ha)
+{
+       void __iomem *address = pm8001_ha->main_cfg_tbl_addr;
+
+       pm8001_ha->main_cfg_tbl.pm80xx_tbl.signature    =
+               pm8001_mr32(address, MAIN_SIGNATURE_OFFSET);
+       pm8001_ha->main_cfg_tbl.pm80xx_tbl.interface_rev =
+               pm8001_mr32(address, MAIN_INTERFACE_REVISION);
+       pm8001_ha->main_cfg_tbl.pm80xx_tbl.firmware_rev =
+               pm8001_mr32(address, MAIN_FW_REVISION);
+       pm8001_ha->main_cfg_tbl.pm80xx_tbl.max_out_io   =
+               pm8001_mr32(address, MAIN_MAX_OUTSTANDING_IO_OFFSET);
+       pm8001_ha->main_cfg_tbl.pm80xx_tbl.max_sgl      =
+               pm8001_mr32(address, MAIN_MAX_SGL_OFFSET);
+       pm8001_ha->main_cfg_tbl.pm80xx_tbl.ctrl_cap_flag =
+               pm8001_mr32(address, MAIN_CNTRL_CAP_OFFSET);
+       pm8001_ha->main_cfg_tbl.pm80xx_tbl.gst_offset   =
+               pm8001_mr32(address, MAIN_GST_OFFSET);
+       pm8001_ha->main_cfg_tbl.pm80xx_tbl.inbound_queue_offset =
+               pm8001_mr32(address, MAIN_IBQ_OFFSET);
+       pm8001_ha->main_cfg_tbl.pm80xx_tbl.outbound_queue_offset =
+               pm8001_mr32(address, MAIN_OBQ_OFFSET);
+
+       /* read Error Dump Offset and Length */
+       pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_dump_offset0 =
+               pm8001_mr32(address, MAIN_FATAL_ERROR_RDUMP0_OFFSET);
+       pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_dump_length0 =
+               pm8001_mr32(address, MAIN_FATAL_ERROR_RDUMP0_LENGTH);
+       pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_dump_offset1 =
+               pm8001_mr32(address, MAIN_FATAL_ERROR_RDUMP1_OFFSET);
+       pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_dump_length1 =
+               pm8001_mr32(address, MAIN_FATAL_ERROR_RDUMP1_LENGTH);
+
+       /* read GPIO LED settings from the configuration table */
+       pm8001_ha->main_cfg_tbl.pm80xx_tbl.gpio_led_mapping =
+               pm8001_mr32(address, MAIN_GPIO_LED_FLAGS_OFFSET);
+
+       /* read analog Setting offset from the configuration table */
+       pm8001_ha->main_cfg_tbl.pm80xx_tbl.analog_setup_table_offset =
+               pm8001_mr32(address, MAIN_ANALOG_SETUP_OFFSET);
+
+       pm8001_ha->main_cfg_tbl.pm80xx_tbl.int_vec_table_offset =
+               pm8001_mr32(address, MAIN_INT_VECTOR_TABLE_OFFSET);
+       pm8001_ha->main_cfg_tbl.pm80xx_tbl.phy_attr_table_offset =
+               pm8001_mr32(address, MAIN_SAS_PHY_ATTR_TABLE_OFFSET);
+}
+
+/**
+ * read_general_status_table - read the general status table and save it.
+ * @pm8001_ha: our hba card information
+ */
+static void read_general_status_table(struct pm8001_hba_info *pm8001_ha)
+{
+       void __iomem *address = pm8001_ha->general_stat_tbl_addr;
+       pm8001_ha->gs_tbl.pm80xx_tbl.gst_len_mpistate   =
+                       pm8001_mr32(address, GST_GSTLEN_MPIS_OFFSET);
+       pm8001_ha->gs_tbl.pm80xx_tbl.iq_freeze_state0   =
+                       pm8001_mr32(address, GST_IQ_FREEZE_STATE0_OFFSET);
+       pm8001_ha->gs_tbl.pm80xx_tbl.iq_freeze_state1   =
+                       pm8001_mr32(address, GST_IQ_FREEZE_STATE1_OFFSET);
+       pm8001_ha->gs_tbl.pm80xx_tbl.msgu_tcnt          =
+                       pm8001_mr32(address, GST_MSGUTCNT_OFFSET);
+       pm8001_ha->gs_tbl.pm80xx_tbl.iop_tcnt           =
+                       pm8001_mr32(address, GST_IOPTCNT_OFFSET);
+       pm8001_ha->gs_tbl.pm80xx_tbl.gpio_input_val     =
+                       pm8001_mr32(address, GST_GPIO_INPUT_VAL);
+       pm8001_ha->gs_tbl.pm80xx_tbl.recover_err_info[0] =
+                       pm8001_mr32(address, GST_RERRINFO_OFFSET0);
+       pm8001_ha->gs_tbl.pm80xx_tbl.recover_err_info[1] =
+                       pm8001_mr32(address, GST_RERRINFO_OFFSET1);
+       pm8001_ha->gs_tbl.pm80xx_tbl.recover_err_info[2] =
+                       pm8001_mr32(address, GST_RERRINFO_OFFSET2);
+       pm8001_ha->gs_tbl.pm80xx_tbl.recover_err_info[3] =
+                       pm8001_mr32(address, GST_RERRINFO_OFFSET3);
+       pm8001_ha->gs_tbl.pm80xx_tbl.recover_err_info[4] =
+                       pm8001_mr32(address, GST_RERRINFO_OFFSET4);
+       pm8001_ha->gs_tbl.pm80xx_tbl.recover_err_info[5] =
+                       pm8001_mr32(address, GST_RERRINFO_OFFSET5);
+       pm8001_ha->gs_tbl.pm80xx_tbl.recover_err_info[6] =
+                       pm8001_mr32(address, GST_RERRINFO_OFFSET6);
+       pm8001_ha->gs_tbl.pm80xx_tbl.recover_err_info[7] =
+                        pm8001_mr32(address, GST_RERRINFO_OFFSET7);
+}
+/**
+ * read_phy_attr_table - read the phy attribute table and save it.
+ * @pm8001_ha: our hba card information
+ */
+static void read_phy_attr_table(struct pm8001_hba_info *pm8001_ha)
+{
+       void __iomem *address = pm8001_ha->pspa_q_tbl_addr;
+       pm8001_ha->phy_attr_table.phystart1_16[0] =
+                       pm8001_mr32(address, PSPA_PHYSTATE0_OFFSET);
+       pm8001_ha->phy_attr_table.phystart1_16[1] =
+                       pm8001_mr32(address, PSPA_PHYSTATE1_OFFSET);
+       pm8001_ha->phy_attr_table.phystart1_16[2] =
+                       pm8001_mr32(address, PSPA_PHYSTATE2_OFFSET);
+       pm8001_ha->phy_attr_table.phystart1_16[3] =
+                       pm8001_mr32(address, PSPA_PHYSTATE3_OFFSET);
+       pm8001_ha->phy_attr_table.phystart1_16[4] =
+                       pm8001_mr32(address, PSPA_PHYSTATE4_OFFSET);
+       pm8001_ha->phy_attr_table.phystart1_16[5] =
+                       pm8001_mr32(address, PSPA_PHYSTATE5_OFFSET);
+       pm8001_ha->phy_attr_table.phystart1_16[6] =
+                       pm8001_mr32(address, PSPA_PHYSTATE6_OFFSET);
+       pm8001_ha->phy_attr_table.phystart1_16[7] =
+                       pm8001_mr32(address, PSPA_PHYSTATE7_OFFSET);
+       pm8001_ha->phy_attr_table.phystart1_16[8] =
+                       pm8001_mr32(address, PSPA_PHYSTATE8_OFFSET);
+       pm8001_ha->phy_attr_table.phystart1_16[9] =
+                       pm8001_mr32(address, PSPA_PHYSTATE9_OFFSET);
+       pm8001_ha->phy_attr_table.phystart1_16[10] =
+                       pm8001_mr32(address, PSPA_PHYSTATE10_OFFSET);
+       pm8001_ha->phy_attr_table.phystart1_16[11] =
+                       pm8001_mr32(address, PSPA_PHYSTATE11_OFFSET);
+       pm8001_ha->phy_attr_table.phystart1_16[12] =
+                       pm8001_mr32(address, PSPA_PHYSTATE12_OFFSET);
+       pm8001_ha->phy_attr_table.phystart1_16[13] =
+                       pm8001_mr32(address, PSPA_PHYSTATE13_OFFSET);
+       pm8001_ha->phy_attr_table.phystart1_16[14] =
+                       pm8001_mr32(address, PSPA_PHYSTATE14_OFFSET);
+       pm8001_ha->phy_attr_table.phystart1_16[15] =
+                       pm8001_mr32(address, PSPA_PHYSTATE15_OFFSET);
+
+       pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[0] =
+                       pm8001_mr32(address, PSPA_OB_HW_EVENT_PID0_OFFSET);
+       pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[1] =
+                       pm8001_mr32(address, PSPA_OB_HW_EVENT_PID1_OFFSET);
+       pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[2] =
+                       pm8001_mr32(address, PSPA_OB_HW_EVENT_PID2_OFFSET);
+       pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[3] =
+                       pm8001_mr32(address, PSPA_OB_HW_EVENT_PID3_OFFSET);
+       pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[4] =
+                       pm8001_mr32(address, PSPA_OB_HW_EVENT_PID4_OFFSET);
+       pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[5] =
+                       pm8001_mr32(address, PSPA_OB_HW_EVENT_PID5_OFFSET);
+       pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[6] =
+                       pm8001_mr32(address, PSPA_OB_HW_EVENT_PID6_OFFSET);
+       pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[7] =
+                       pm8001_mr32(address, PSPA_OB_HW_EVENT_PID7_OFFSET);
+       pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[8] =
+                       pm8001_mr32(address, PSPA_OB_HW_EVENT_PID8_OFFSET);
+       pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[9] =
+                       pm8001_mr32(address, PSPA_OB_HW_EVENT_PID9_OFFSET);
+       pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[10] =
+                       pm8001_mr32(address, PSPA_OB_HW_EVENT_PID10_OFFSET);
+       pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[11] =
+                       pm8001_mr32(address, PSPA_OB_HW_EVENT_PID11_OFFSET);
+       pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[12] =
+                       pm8001_mr32(address, PSPA_OB_HW_EVENT_PID12_OFFSET);
+       pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[13] =
+                       pm8001_mr32(address, PSPA_OB_HW_EVENT_PID13_OFFSET);
+       pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[14] =
+                       pm8001_mr32(address, PSPA_OB_HW_EVENT_PID14_OFFSET);
+       pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[15] =
+                       pm8001_mr32(address, PSPA_OB_HW_EVENT_PID15_OFFSET);
+
+}
+
+/**
+ * read_inbnd_queue_table - read the inbound queue table and save it.
+ * @pm8001_ha: our hba card information
+ */
+static void read_inbnd_queue_table(struct pm8001_hba_info *pm8001_ha)
+{
+       int i;
+       void __iomem *address = pm8001_ha->inbnd_q_tbl_addr;
+       for (i = 0; i < PM8001_MAX_SPCV_INB_NUM; i++) {
+               u32 offset = i * 0x20;
+               pm8001_ha->inbnd_q_tbl[i].pi_pci_bar =
+                       get_pci_bar_index(pm8001_mr32(address,
+                               (offset + IB_PIPCI_BAR)));
+               pm8001_ha->inbnd_q_tbl[i].pi_offset =
+                       pm8001_mr32(address, (offset + IB_PIPCI_BAR_OFFSET));
+       }
+}
+
+/**
+ * read_outbnd_queue_table - read the outbound queue table and save it.
+ * @pm8001_ha: our hba card information
+ */
+static void read_outbnd_queue_table(struct pm8001_hba_info *pm8001_ha)
+{
+       int i;
+       void __iomem *address = pm8001_ha->outbnd_q_tbl_addr;
+       for (i = 0; i < PM8001_MAX_SPCV_OUTB_NUM; i++) {
+               u32 offset = i * 0x24;
+               pm8001_ha->outbnd_q_tbl[i].ci_pci_bar =
+                       get_pci_bar_index(pm8001_mr32(address,
+                               (offset + OB_CIPCI_BAR)));
+               pm8001_ha->outbnd_q_tbl[i].ci_offset =
+                       pm8001_mr32(address, (offset + OB_CIPCI_BAR_OFFSET));
+       }
+}
+
+/**
+ * init_default_table_values - init the default table.
+ * @pm8001_ha: our hba card information
+ */
+static void init_default_table_values(struct pm8001_hba_info *pm8001_ha)
+{
+       int i;
+       u32 offsetib, offsetob;
+       void __iomem *addressib = pm8001_ha->inbnd_q_tbl_addr;
+       void __iomem *addressob = pm8001_ha->outbnd_q_tbl_addr;
+
+       pm8001_ha->main_cfg_tbl.pm80xx_tbl.upper_event_log_addr         =
+               pm8001_ha->memoryMap.region[AAP1].phys_addr_hi;
+       pm8001_ha->main_cfg_tbl.pm80xx_tbl.lower_event_log_addr         =
+               pm8001_ha->memoryMap.region[AAP1].phys_addr_lo;
+       pm8001_ha->main_cfg_tbl.pm80xx_tbl.event_log_size               =
+                                                       PM8001_EVENT_LOG_SIZE;
+       pm8001_ha->main_cfg_tbl.pm80xx_tbl.event_log_severity           = 0x01;
+       pm8001_ha->main_cfg_tbl.pm80xx_tbl.upper_pcs_event_log_addr     =
+               pm8001_ha->memoryMap.region[IOP].phys_addr_hi;
+       pm8001_ha->main_cfg_tbl.pm80xx_tbl.lower_pcs_event_log_addr     =
+               pm8001_ha->memoryMap.region[IOP].phys_addr_lo;
+       pm8001_ha->main_cfg_tbl.pm80xx_tbl.pcs_event_log_size           =
+                                                       PM8001_EVENT_LOG_SIZE;
+       pm8001_ha->main_cfg_tbl.pm80xx_tbl.pcs_event_log_severity       = 0x01;
+       pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_interrupt          = 0x01;
+
+       /* Disable end to end CRC checking */
+       pm8001_ha->main_cfg_tbl.pm80xx_tbl.crc_core_dump = (0x1 << 16);
+
+       for (i = 0; i < PM8001_MAX_SPCV_INB_NUM; i++) {
+               pm8001_ha->inbnd_q_tbl[i].element_pri_size_cnt  =
+                       PM8001_MPI_QUEUE | (64 << 16) | (0x00<<30);
+               pm8001_ha->inbnd_q_tbl[i].upper_base_addr       =
+                       pm8001_ha->memoryMap.region[IB + i].phys_addr_hi;
+               pm8001_ha->inbnd_q_tbl[i].lower_base_addr       =
+               pm8001_ha->memoryMap.region[IB + i].phys_addr_lo;
+               pm8001_ha->inbnd_q_tbl[i].base_virt             =
+                       (u8 *)pm8001_ha->memoryMap.region[IB + i].virt_ptr;
+               pm8001_ha->inbnd_q_tbl[i].total_length          =
+                       pm8001_ha->memoryMap.region[IB + i].total_len;
+               pm8001_ha->inbnd_q_tbl[i].ci_upper_base_addr    =
+                       pm8001_ha->memoryMap.region[CI + i].phys_addr_hi;
+               pm8001_ha->inbnd_q_tbl[i].ci_lower_base_addr    =
+                       pm8001_ha->memoryMap.region[CI + i].phys_addr_lo;
+               pm8001_ha->inbnd_q_tbl[i].ci_virt               =
+                       pm8001_ha->memoryMap.region[CI + i].virt_ptr;
+               offsetib = i * 0x20;
+               pm8001_ha->inbnd_q_tbl[i].pi_pci_bar            =
+                       get_pci_bar_index(pm8001_mr32(addressib,
+                               (offsetib + 0x14)));
+               pm8001_ha->inbnd_q_tbl[i].pi_offset             =
+                       pm8001_mr32(addressib, (offsetib + 0x18));
+               pm8001_ha->inbnd_q_tbl[i].producer_idx          = 0;
+               pm8001_ha->inbnd_q_tbl[i].consumer_index        = 0;
+       }
+       for (i = 0; i < PM8001_MAX_SPCV_OUTB_NUM; i++) {
+               pm8001_ha->outbnd_q_tbl[i].element_size_cnt     =
+                       PM8001_MPI_QUEUE | (64 << 16) | (0x01<<30);
+               pm8001_ha->outbnd_q_tbl[i].upper_base_addr      =
+                       pm8001_ha->memoryMap.region[OB + i].phys_addr_hi;
+               pm8001_ha->outbnd_q_tbl[i].lower_base_addr      =
+                       pm8001_ha->memoryMap.region[OB + i].phys_addr_lo;
+               pm8001_ha->outbnd_q_tbl[i].base_virt            =
+                       (u8 *)pm8001_ha->memoryMap.region[OB + i].virt_ptr;
+               pm8001_ha->outbnd_q_tbl[i].total_length         =
+                       pm8001_ha->memoryMap.region[OB + i].total_len;
+               pm8001_ha->outbnd_q_tbl[i].pi_upper_base_addr   =
+                       pm8001_ha->memoryMap.region[PI + i].phys_addr_hi;
+               pm8001_ha->outbnd_q_tbl[i].pi_lower_base_addr   =
+                       pm8001_ha->memoryMap.region[PI + i].phys_addr_lo;
+               /* interrupt vector based on oq */
+               pm8001_ha->outbnd_q_tbl[i].interrup_vec_cnt_delay = (i << 24);
+               pm8001_ha->outbnd_q_tbl[i].pi_virt              =
+                       pm8001_ha->memoryMap.region[PI + i].virt_ptr;
+               offsetob = i * 0x24;
+               pm8001_ha->outbnd_q_tbl[i].ci_pci_bar           =
+                       get_pci_bar_index(pm8001_mr32(addressob,
+                       offsetob + 0x14));
+               pm8001_ha->outbnd_q_tbl[i].ci_offset            =
+                       pm8001_mr32(addressob, (offsetob + 0x18));
+               pm8001_ha->outbnd_q_tbl[i].consumer_idx         = 0;
+               pm8001_ha->outbnd_q_tbl[i].producer_index       = 0;
+       }
+}
+
+/**
+ * update_main_config_table - update the main default table to the HBA.
+ * @pm8001_ha: our hba card information
+ */
+static void update_main_config_table(struct pm8001_hba_info *pm8001_ha)
+{
+       void __iomem *address = pm8001_ha->main_cfg_tbl_addr;
+       pm8001_mw32(address, MAIN_IQNPPD_HPPD_OFFSET,
+               pm8001_ha->main_cfg_tbl.pm80xx_tbl.inbound_q_nppd_hppd);
+       pm8001_mw32(address, MAIN_EVENT_LOG_ADDR_HI,
+               pm8001_ha->main_cfg_tbl.pm80xx_tbl.upper_event_log_addr);
+       pm8001_mw32(address, MAIN_EVENT_LOG_ADDR_LO,
+               pm8001_ha->main_cfg_tbl.pm80xx_tbl.lower_event_log_addr);
+       pm8001_mw32(address, MAIN_EVENT_LOG_BUFF_SIZE,
+               pm8001_ha->main_cfg_tbl.pm80xx_tbl.event_log_size);
+       pm8001_mw32(address, MAIN_EVENT_LOG_OPTION,
+               pm8001_ha->main_cfg_tbl.pm80xx_tbl.event_log_severity);
+       pm8001_mw32(address, MAIN_PCS_EVENT_LOG_ADDR_HI,
+               pm8001_ha->main_cfg_tbl.pm80xx_tbl.upper_pcs_event_log_addr);
+       pm8001_mw32(address, MAIN_PCS_EVENT_LOG_ADDR_LO,
+               pm8001_ha->main_cfg_tbl.pm80xx_tbl.lower_pcs_event_log_addr);
+       pm8001_mw32(address, MAIN_PCS_EVENT_LOG_BUFF_SIZE,
+               pm8001_ha->main_cfg_tbl.pm80xx_tbl.pcs_event_log_size);
+       pm8001_mw32(address, MAIN_PCS_EVENT_LOG_OPTION,
+               pm8001_ha->main_cfg_tbl.pm80xx_tbl.pcs_event_log_severity);
+       pm8001_mw32(address, MAIN_FATAL_ERROR_INTERRUPT,
+               pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_interrupt);
+       pm8001_mw32(address, MAIN_EVENT_CRC_CHECK,
+               pm8001_ha->main_cfg_tbl.pm80xx_tbl.crc_core_dump);
+
+       /* SPCv specific */
+       pm8001_ha->main_cfg_tbl.pm80xx_tbl.gpio_led_mapping &= 0xCFFFFFFF;
+       /* Set GPIOLED to 0x2 for LED indicator */
+       pm8001_ha->main_cfg_tbl.pm80xx_tbl.gpio_led_mapping |= 0x20000000;
+       pm8001_mw32(address, MAIN_GPIO_LED_FLAGS_OFFSET,
+               pm8001_ha->main_cfg_tbl.pm80xx_tbl.gpio_led_mapping);
+
+       pm8001_mw32(address, MAIN_PORT_RECOVERY_TIMER,
+               pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer);
+       pm8001_mw32(address, MAIN_INT_REASSERTION_DELAY,
+               pm8001_ha->main_cfg_tbl.pm80xx_tbl.interrupt_reassertion_delay);
+}
+
+/**
+ * update_inbnd_queue_table - update the inbound queue table to the HBA.
+ * @pm8001_ha: our hba card information
+ */
+static void update_inbnd_queue_table(struct pm8001_hba_info *pm8001_ha,
+                                        int number)
+{
+       void __iomem *address = pm8001_ha->inbnd_q_tbl_addr;
+       u16 offset = number * 0x20;
+       pm8001_mw32(address, offset + IB_PROPERITY_OFFSET,
+               pm8001_ha->inbnd_q_tbl[number].element_pri_size_cnt);
+       pm8001_mw32(address, offset + IB_BASE_ADDR_HI_OFFSET,
+               pm8001_ha->inbnd_q_tbl[number].upper_base_addr);
+       pm8001_mw32(address, offset + IB_BASE_ADDR_LO_OFFSET,
+               pm8001_ha->inbnd_q_tbl[number].lower_base_addr);
+       pm8001_mw32(address, offset + IB_CI_BASE_ADDR_HI_OFFSET,
+               pm8001_ha->inbnd_q_tbl[number].ci_upper_base_addr);
+       pm8001_mw32(address, offset + IB_CI_BASE_ADDR_LO_OFFSET,
+               pm8001_ha->inbnd_q_tbl[number].ci_lower_base_addr);
+}
+
+/**
+ * update_outbnd_queue_table - update the outbound queue table to the HBA.
+ * @pm8001_ha: our hba card information
+ */
+static void update_outbnd_queue_table(struct pm8001_hba_info *pm8001_ha,
+                                                int number)
+{
+       void __iomem *address = pm8001_ha->outbnd_q_tbl_addr;
+       u16 offset = number * 0x24;
+       pm8001_mw32(address, offset + OB_PROPERITY_OFFSET,
+               pm8001_ha->outbnd_q_tbl[number].element_size_cnt);
+       pm8001_mw32(address, offset + OB_BASE_ADDR_HI_OFFSET,
+               pm8001_ha->outbnd_q_tbl[number].upper_base_addr);
+       pm8001_mw32(address, offset + OB_BASE_ADDR_LO_OFFSET,
+               pm8001_ha->outbnd_q_tbl[number].lower_base_addr);
+       pm8001_mw32(address, offset + OB_PI_BASE_ADDR_HI_OFFSET,
+               pm8001_ha->outbnd_q_tbl[number].pi_upper_base_addr);
+       pm8001_mw32(address, offset + OB_PI_BASE_ADDR_LO_OFFSET,
+               pm8001_ha->outbnd_q_tbl[number].pi_lower_base_addr);
+       pm8001_mw32(address, offset + OB_INTERRUPT_COALES_OFFSET,
+               pm8001_ha->outbnd_q_tbl[number].interrup_vec_cnt_delay);
+}
+
+/**
+ * mpi_init_check - check firmware initialization status.
+ * @pm8001_ha: our hba card information
+ */
+static int mpi_init_check(struct pm8001_hba_info *pm8001_ha)
+{
+       u32 max_wait_count;
+       u32 value;
+       u32 gst_len_mpistate;
+
+       /* Write bit0=1 to Inbound DoorBell Register to tell the SPC FW the
+       table is updated */
+       pm8001_cw32(pm8001_ha, 0, MSGU_IBDB_SET, SPCv_MSGU_CFG_TABLE_UPDATE);
+       /* wait until Inbound DoorBell Clear Register toggled */
+       max_wait_count = 2 * 1000 * 1000;/* 2 sec for spcv/ve */
+       do {
+               udelay(1);
+               value = pm8001_cr32(pm8001_ha, 0, MSGU_IBDB_SET);
+               value &= SPCv_MSGU_CFG_TABLE_UPDATE;
+       } while ((value != 0) && (--max_wait_count));
+
+       if (!max_wait_count)
+               return -1;
+       /* check the MPI-State for initialization upto 100ms*/
+       max_wait_count = 100 * 1000;/* 100 msec */
+       do {
+               udelay(1);
+               gst_len_mpistate =
+                       pm8001_mr32(pm8001_ha->general_stat_tbl_addr,
+                                       GST_GSTLEN_MPIS_OFFSET);
+       } while ((GST_MPI_STATE_INIT !=
+               (gst_len_mpistate & GST_MPI_STATE_MASK)) && (--max_wait_count));
+       if (!max_wait_count)
+               return -1;
+
+       /* check MPI Initialization error */
+       gst_len_mpistate = gst_len_mpistate >> 16;
+       if (0x0000 != gst_len_mpistate)
+               return -1;
+
+       return 0;
+}
+
+/**
+ * check_fw_ready - The LLDD check if the FW is ready, if not, return error.
+ * @pm8001_ha: our hba card information
+ */
+static int check_fw_ready(struct pm8001_hba_info *pm8001_ha)
+{
+       u32 value;
+       u32 max_wait_count;
+       u32 max_wait_time;
+       int ret = 0;
+
+       /* reset / PCIe ready */
+       max_wait_time = max_wait_count = 100 * 1000;    /* 100 milli sec */
+       do {
+               udelay(1);
+               value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1);
+       } while ((value == 0xFFFFFFFF) && (--max_wait_count));
+
+       /* check ila status */
+       max_wait_time = max_wait_count = 1000 * 1000;   /* 1000 milli sec */
+       do {
+               udelay(1);
+               value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1);
+       } while (((value & SCRATCH_PAD_ILA_READY) !=
+                       SCRATCH_PAD_ILA_READY) && (--max_wait_count));
+       if (!max_wait_count)
+               ret = -1;
+       else {
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk(" ila ready status in %d millisec\n",
+                               (max_wait_time - max_wait_count)));
+       }
+
+       /* check RAAE status */
+       max_wait_time = max_wait_count = 1800 * 1000;   /* 1800 milli sec */
+       do {
+               udelay(1);
+               value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1);
+       } while (((value & SCRATCH_PAD_RAAE_READY) !=
+                               SCRATCH_PAD_RAAE_READY) && (--max_wait_count));
+       if (!max_wait_count)
+               ret = -1;
+       else {
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk(" raae ready status in %d millisec\n",
+                                       (max_wait_time - max_wait_count)));
+       }
+
+       /* check iop0 status */
+       max_wait_time = max_wait_count = 600 * 1000;    /* 600 milli sec */
+       do {
+               udelay(1);
+               value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1);
+       } while (((value & SCRATCH_PAD_IOP0_READY) != SCRATCH_PAD_IOP0_READY) &&
+                       (--max_wait_count));
+       if (!max_wait_count)
+               ret = -1;
+       else {
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk(" iop0 ready status in %d millisec\n",
+                               (max_wait_time - max_wait_count)));
+       }
+
+       /* check iop1 status only for 16 port controllers */
+       if ((pm8001_ha->chip_id != chip_8008) &&
+                       (pm8001_ha->chip_id != chip_8009)) {
+               /* 200 milli sec */
+               max_wait_time = max_wait_count = 200 * 1000;
+               do {
+                       udelay(1);
+                       value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1);
+               } while (((value & SCRATCH_PAD_IOP1_READY) !=
+                               SCRATCH_PAD_IOP1_READY) && (--max_wait_count));
+               if (!max_wait_count)
+                       ret = -1;
+               else {
+                       PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
+                               "iop1 ready status in %d millisec\n",
+                               (max_wait_time - max_wait_count)));
+               }
+       }
+
+       return ret;
+}
+
+static void init_pci_device_addresses(struct pm8001_hba_info *pm8001_ha)
+{
+       void __iomem *base_addr;
+       u32     value;
+       u32     offset;
+       u32     pcibar;
+       u32     pcilogic;
+
+       value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_0);
+       offset = value & 0x03FFFFFF; /* scratch pad 0 TBL address */
+
+       PM8001_INIT_DBG(pm8001_ha,
+               pm8001_printk("Scratchpad 0 Offset: 0x%x value 0x%x\n",
+                               offset, value));
+       pcilogic = (value & 0xFC000000) >> 26;
+       pcibar = get_pci_bar_index(pcilogic);
+       PM8001_INIT_DBG(pm8001_ha,
+               pm8001_printk("Scratchpad 0 PCI BAR: %d\n", pcibar));
+       pm8001_ha->main_cfg_tbl_addr = base_addr =
+               pm8001_ha->io_mem[pcibar].memvirtaddr + offset;
+       pm8001_ha->general_stat_tbl_addr =
+               base_addr + (pm8001_cr32(pm8001_ha, pcibar, offset + 0x18) &
+                                       0xFFFFFF);
+       pm8001_ha->inbnd_q_tbl_addr =
+               base_addr + (pm8001_cr32(pm8001_ha, pcibar, offset + 0x1C) &
+                                       0xFFFFFF);
+       pm8001_ha->outbnd_q_tbl_addr =
+               base_addr + (pm8001_cr32(pm8001_ha, pcibar, offset + 0x20) &
+                                       0xFFFFFF);
+       pm8001_ha->ivt_tbl_addr =
+               base_addr + (pm8001_cr32(pm8001_ha, pcibar, offset + 0x8C) &
+                                       0xFFFFFF);
+       pm8001_ha->pspa_q_tbl_addr =
+               base_addr + (pm8001_cr32(pm8001_ha, pcibar, offset + 0x90) &
+                                       0xFFFFFF);
+
+       PM8001_INIT_DBG(pm8001_ha,
+                       pm8001_printk("GST OFFSET 0x%x\n",
+                       pm8001_cr32(pm8001_ha, pcibar, offset + 0x18)));
+       PM8001_INIT_DBG(pm8001_ha,
+                       pm8001_printk("INBND OFFSET 0x%x\n",
+                       pm8001_cr32(pm8001_ha, pcibar, offset + 0x1C)));
+       PM8001_INIT_DBG(pm8001_ha,
+                       pm8001_printk("OBND OFFSET 0x%x\n",
+                       pm8001_cr32(pm8001_ha, pcibar, offset + 0x20)));
+       PM8001_INIT_DBG(pm8001_ha,
+                       pm8001_printk("IVT OFFSET 0x%x\n",
+                       pm8001_cr32(pm8001_ha, pcibar, offset + 0x8C)));
+       PM8001_INIT_DBG(pm8001_ha,
+                       pm8001_printk("PSPA OFFSET 0x%x\n",
+                       pm8001_cr32(pm8001_ha, pcibar, offset + 0x90)));
+       PM8001_INIT_DBG(pm8001_ha,
+                       pm8001_printk("addr - main cfg %p general status %p\n",
+                       pm8001_ha->main_cfg_tbl_addr,
+                       pm8001_ha->general_stat_tbl_addr));
+       PM8001_INIT_DBG(pm8001_ha,
+                       pm8001_printk("addr - inbnd %p obnd %p\n",
+                       pm8001_ha->inbnd_q_tbl_addr,
+                       pm8001_ha->outbnd_q_tbl_addr));
+       PM8001_INIT_DBG(pm8001_ha,
+                       pm8001_printk("addr - pspa %p ivt %p\n",
+                       pm8001_ha->pspa_q_tbl_addr,
+                       pm8001_ha->ivt_tbl_addr));
+}
+
+/**
+ * pm80xx_set_thermal_config - support the thermal configuration
+ * @pm8001_ha: our hba card information.
+ */
+int
+pm80xx_set_thermal_config(struct pm8001_hba_info *pm8001_ha)
+{
+       struct set_ctrl_cfg_req payload;
+       struct inbound_queue_table *circularQ;
+       int rc;
+       u32 tag;
+       u32 opc = OPC_INB_SET_CONTROLLER_CONFIG;
+
+       memset(&payload, 0, sizeof(struct set_ctrl_cfg_req));
+       rc = pm8001_tag_alloc(pm8001_ha, &tag);
+       if (rc)
+               return -1;
+
+       circularQ = &pm8001_ha->inbnd_q_tbl[0];
+       payload.tag = cpu_to_le32(tag);
+       payload.cfg_pg[0] = (THERMAL_LOG_ENABLE << 9) |
+                       (THERMAL_ENABLE << 8) | THERMAL_OP_CODE;
+       payload.cfg_pg[1] = (LTEMPHIL << 24) | (RTEMPHIL << 8);
+
+       rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+       return rc;
+
+}
+
+/**
+* pm80xx_set_sas_protocol_timer_config - support the SAS Protocol
+* Timer configuration page
+* @pm8001_ha: our hba card information.
+*/
+static int
+pm80xx_set_sas_protocol_timer_config(struct pm8001_hba_info *pm8001_ha)
+{
+       struct set_ctrl_cfg_req payload;
+       struct inbound_queue_table *circularQ;
+       SASProtocolTimerConfig_t SASConfigPage;
+       int rc;
+       u32 tag;
+       u32 opc = OPC_INB_SET_CONTROLLER_CONFIG;
+
+       memset(&payload, 0, sizeof(struct set_ctrl_cfg_req));
+       memset(&SASConfigPage, 0, sizeof(SASProtocolTimerConfig_t));
+
+       rc = pm8001_tag_alloc(pm8001_ha, &tag);
+
+       if (rc)
+               return -1;
+
+       circularQ = &pm8001_ha->inbnd_q_tbl[0];
+       payload.tag = cpu_to_le32(tag);
+
+       SASConfigPage.pageCode        =  SAS_PROTOCOL_TIMER_CONFIG_PAGE;
+       SASConfigPage.MST_MSI         =  3 << 15;
+       SASConfigPage.STP_SSP_MCT_TMO =  (STP_MCT_TMO << 16) | SSP_MCT_TMO;
+       SASConfigPage.STP_FRM_TMO     = (SAS_MAX_OPEN_TIME << 24) |
+                               (SMP_MAX_CONN_TIMER << 16) | STP_FRM_TIMER;
+       SASConfigPage.STP_IDLE_TMO    =  STP_IDLE_TIME;
+
+       if (SASConfigPage.STP_IDLE_TMO > 0x3FFFFFF)
+               SASConfigPage.STP_IDLE_TMO = 0x3FFFFFF;
+
+
+       SASConfigPage.OPNRJT_RTRY_INTVL =         (SAS_MFD << 16) |
+                                               SAS_OPNRJT_RTRY_INTVL;
+       SASConfigPage.Data_Cmd_OPNRJT_RTRY_TMO =  (SAS_DOPNRJT_RTRY_TMO << 16)
+                                               | SAS_COPNRJT_RTRY_TMO;
+       SASConfigPage.Data_Cmd_OPNRJT_RTRY_THR =  (SAS_DOPNRJT_RTRY_THR << 16)
+                                               | SAS_COPNRJT_RTRY_THR;
+       SASConfigPage.MAX_AIP =  SAS_MAX_AIP;
+
+       PM8001_INIT_DBG(pm8001_ha,
+                       pm8001_printk("SASConfigPage.pageCode "
+                       "0x%08x\n", SASConfigPage.pageCode));
+       PM8001_INIT_DBG(pm8001_ha,
+                       pm8001_printk("SASConfigPage.MST_MSI "
+                       " 0x%08x\n", SASConfigPage.MST_MSI));
+       PM8001_INIT_DBG(pm8001_ha,
+                       pm8001_printk("SASConfigPage.STP_SSP_MCT_TMO "
+                       " 0x%08x\n", SASConfigPage.STP_SSP_MCT_TMO));
+       PM8001_INIT_DBG(pm8001_ha,
+                       pm8001_printk("SASConfigPage.STP_FRM_TMO "
+                       " 0x%08x\n", SASConfigPage.STP_FRM_TMO));
+       PM8001_INIT_DBG(pm8001_ha,
+                       pm8001_printk("SASConfigPage.STP_IDLE_TMO "
+                       " 0x%08x\n", SASConfigPage.STP_IDLE_TMO));
+       PM8001_INIT_DBG(pm8001_ha,
+                       pm8001_printk("SASConfigPage.OPNRJT_RTRY_INTVL "
+                       " 0x%08x\n", SASConfigPage.OPNRJT_RTRY_INTVL));
+       PM8001_INIT_DBG(pm8001_ha,
+                       pm8001_printk("SASConfigPage.Data_Cmd_OPNRJT_RTRY_TMO "
+                       " 0x%08x\n", SASConfigPage.Data_Cmd_OPNRJT_RTRY_TMO));
+       PM8001_INIT_DBG(pm8001_ha,
+                       pm8001_printk("SASConfigPage.Data_Cmd_OPNRJT_RTRY_THR "
+                       " 0x%08x\n", SASConfigPage.Data_Cmd_OPNRJT_RTRY_THR));
+       PM8001_INIT_DBG(pm8001_ha, pm8001_printk("SASConfigPage.MAX_AIP "
+                       " 0x%08x\n", SASConfigPage.MAX_AIP));
+
+       memcpy(&payload.cfg_pg, &SASConfigPage,
+                        sizeof(SASProtocolTimerConfig_t));
+
+       rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+
+       return rc;
+}
+
+/**
+ * pm80xx_get_encrypt_info - Check for encryption
+ * @pm8001_ha: our hba card information.
+ */
+static int
+pm80xx_get_encrypt_info(struct pm8001_hba_info *pm8001_ha)
+{
+       u32 scratch3_value;
+       int ret;
+
+       /* Read encryption status from SCRATCH PAD 3 */
+       scratch3_value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_3);
+
+       if ((scratch3_value & SCRATCH_PAD3_ENC_MASK) ==
+                                       SCRATCH_PAD3_ENC_READY) {
+               if (scratch3_value & SCRATCH_PAD3_XTS_ENABLED)
+                       pm8001_ha->encrypt_info.cipher_mode = CIPHER_MODE_XTS;
+               if ((scratch3_value & SCRATCH_PAD3_SM_MASK) ==
+                                               SCRATCH_PAD3_SMF_ENABLED)
+                       pm8001_ha->encrypt_info.sec_mode = SEC_MODE_SMF;
+               if ((scratch3_value & SCRATCH_PAD3_SM_MASK) ==
+                                               SCRATCH_PAD3_SMA_ENABLED)
+                       pm8001_ha->encrypt_info.sec_mode = SEC_MODE_SMA;
+               if ((scratch3_value & SCRATCH_PAD3_SM_MASK) ==
+                                               SCRATCH_PAD3_SMB_ENABLED)
+                       pm8001_ha->encrypt_info.sec_mode = SEC_MODE_SMB;
+               pm8001_ha->encrypt_info.status = 0;
+               PM8001_INIT_DBG(pm8001_ha, pm8001_printk(
+                       "Encryption: SCRATCH_PAD3_ENC_READY 0x%08X."
+                       "Cipher mode 0x%x Sec mode 0x%x status 0x%x\n",
+                       scratch3_value, pm8001_ha->encrypt_info.cipher_mode,
+                       pm8001_ha->encrypt_info.sec_mode,
+                       pm8001_ha->encrypt_info.status));
+               ret = 0;
+       } else if ((scratch3_value & SCRATCH_PAD3_ENC_READY) ==
+                                       SCRATCH_PAD3_ENC_DISABLED) {
+               PM8001_INIT_DBG(pm8001_ha, pm8001_printk(
+                       "Encryption: SCRATCH_PAD3_ENC_DISABLED 0x%08X\n",
+                       scratch3_value));
+               pm8001_ha->encrypt_info.status = 0xFFFFFFFF;
+               pm8001_ha->encrypt_info.cipher_mode = 0;
+               pm8001_ha->encrypt_info.sec_mode = 0;
+               return 0;
+       } else if ((scratch3_value & SCRATCH_PAD3_ENC_MASK) ==
+                               SCRATCH_PAD3_ENC_DIS_ERR) {
+               pm8001_ha->encrypt_info.status =
+                       (scratch3_value & SCRATCH_PAD3_ERR_CODE) >> 16;
+               if (scratch3_value & SCRATCH_PAD3_XTS_ENABLED)
+                       pm8001_ha->encrypt_info.cipher_mode = CIPHER_MODE_XTS;
+               if ((scratch3_value & SCRATCH_PAD3_SM_MASK) ==
+                                       SCRATCH_PAD3_SMF_ENABLED)
+                       pm8001_ha->encrypt_info.sec_mode = SEC_MODE_SMF;
+               if ((scratch3_value & SCRATCH_PAD3_SM_MASK) ==
+                                       SCRATCH_PAD3_SMA_ENABLED)
+                       pm8001_ha->encrypt_info.sec_mode = SEC_MODE_SMA;
+               if ((scratch3_value & SCRATCH_PAD3_SM_MASK) ==
+                                       SCRATCH_PAD3_SMB_ENABLED)
+                       pm8001_ha->encrypt_info.sec_mode = SEC_MODE_SMB;
+               PM8001_INIT_DBG(pm8001_ha, pm8001_printk(
+                       "Encryption: SCRATCH_PAD3_DIS_ERR 0x%08X."
+                       "Cipher mode 0x%x sec mode 0x%x status 0x%x\n",
+                       scratch3_value, pm8001_ha->encrypt_info.cipher_mode,
+                       pm8001_ha->encrypt_info.sec_mode,
+                       pm8001_ha->encrypt_info.status));
+               ret = -1;
+       } else if ((scratch3_value & SCRATCH_PAD3_ENC_MASK) ==
+                                SCRATCH_PAD3_ENC_ENA_ERR) {
+
+               pm8001_ha->encrypt_info.status =
+                       (scratch3_value & SCRATCH_PAD3_ERR_CODE) >> 16;
+               if (scratch3_value & SCRATCH_PAD3_XTS_ENABLED)
+                       pm8001_ha->encrypt_info.cipher_mode = CIPHER_MODE_XTS;
+               if ((scratch3_value & SCRATCH_PAD3_SM_MASK) ==
+                                       SCRATCH_PAD3_SMF_ENABLED)
+                       pm8001_ha->encrypt_info.sec_mode = SEC_MODE_SMF;
+               if ((scratch3_value & SCRATCH_PAD3_SM_MASK) ==
+                                       SCRATCH_PAD3_SMA_ENABLED)
+                       pm8001_ha->encrypt_info.sec_mode = SEC_MODE_SMA;
+               if ((scratch3_value & SCRATCH_PAD3_SM_MASK) ==
+                                       SCRATCH_PAD3_SMB_ENABLED)
+                       pm8001_ha->encrypt_info.sec_mode = SEC_MODE_SMB;
+
+               PM8001_INIT_DBG(pm8001_ha, pm8001_printk(
+                       "Encryption: SCRATCH_PAD3_ENA_ERR 0x%08X."
+                       "Cipher mode 0x%x sec mode 0x%x status 0x%x\n",
+                       scratch3_value, pm8001_ha->encrypt_info.cipher_mode,
+                       pm8001_ha->encrypt_info.sec_mode,
+                       pm8001_ha->encrypt_info.status));
+               ret = -1;
+       }
+       return ret;
+}
+
+/**
+ * pm80xx_encrypt_update - update flash with encryption informtion
+ * @pm8001_ha: our hba card information.
+ */
+static int pm80xx_encrypt_update(struct pm8001_hba_info *pm8001_ha)
+{
+       struct kek_mgmt_req payload;
+       struct inbound_queue_table *circularQ;
+       int rc;
+       u32 tag;
+       u32 opc = OPC_INB_KEK_MANAGEMENT;
+
+       memset(&payload, 0, sizeof(struct kek_mgmt_req));
+       rc = pm8001_tag_alloc(pm8001_ha, &tag);
+       if (rc)
+               return -1;
+
+       circularQ = &pm8001_ha->inbnd_q_tbl[0];
+       payload.tag = cpu_to_le32(tag);
+       /* Currently only one key is used. New KEK index is 1.
+        * Current KEK index is 1. Store KEK to NVRAM is 1.
+        */
+       payload.new_curidx_ksop = ((1 << 24) | (1 << 16) | (1 << 8) |
+                                       KEK_MGMT_SUBOP_KEYCARDUPDATE);
+
+       rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+
+       return rc;
+}
+
+/**
+ * pm8001_chip_init - the main init function that initialize whole PM8001 chip.
+ * @pm8001_ha: our hba card information
+ */
+static int pm80xx_chip_init(struct pm8001_hba_info *pm8001_ha)
+{
+       int ret;
+       u8 i = 0;
+
+       /* check the firmware status */
+       if (-1 == check_fw_ready(pm8001_ha)) {
+               PM8001_FAIL_DBG(pm8001_ha,
+                       pm8001_printk("Firmware is not ready!\n"));
+               return -EBUSY;
+       }
+
+       /* Initialize pci space address eg: mpi offset */
+       init_pci_device_addresses(pm8001_ha);
+       init_default_table_values(pm8001_ha);
+       read_main_config_table(pm8001_ha);
+       read_general_status_table(pm8001_ha);
+       read_inbnd_queue_table(pm8001_ha);
+       read_outbnd_queue_table(pm8001_ha);
+       read_phy_attr_table(pm8001_ha);
+
+       /* update main config table ,inbound table and outbound table */
+       update_main_config_table(pm8001_ha);
+       for (i = 0; i < PM8001_MAX_SPCV_INB_NUM; i++)
+               update_inbnd_queue_table(pm8001_ha, i);
+       for (i = 0; i < PM8001_MAX_SPCV_OUTB_NUM; i++)
+               update_outbnd_queue_table(pm8001_ha, i);
+
+       /* notify firmware update finished and check initialization status */
+       if (0 == mpi_init_check(pm8001_ha)) {
+               PM8001_INIT_DBG(pm8001_ha,
+                       pm8001_printk("MPI initialize successful!\n"));
+       } else
+               return -EBUSY;
+
+       /* send SAS protocol timer configuration page to FW */
+       ret = pm80xx_set_sas_protocol_timer_config(pm8001_ha);
+
+       /* Check for encryption */
+       if (pm8001_ha->chip->encrypt) {
+               PM8001_INIT_DBG(pm8001_ha,
+                       pm8001_printk("Checking for encryption\n"));
+               ret = pm80xx_get_encrypt_info(pm8001_ha);
+               if (ret == -1) {
+                       PM8001_INIT_DBG(pm8001_ha,
+                               pm8001_printk("Encryption error !!\n"));
+                       if (pm8001_ha->encrypt_info.status == 0x81) {
+                               PM8001_INIT_DBG(pm8001_ha, pm8001_printk(
+                                       "Encryption enabled with error."
+                                       "Saving encryption key to flash\n"));
+                               pm80xx_encrypt_update(pm8001_ha);
+                       }
+               }
+       }
+       return 0;
+}
+
+static int mpi_uninit_check(struct pm8001_hba_info *pm8001_ha)
+{
+       u32 max_wait_count;
+       u32 value;
+       u32 gst_len_mpistate;
+       init_pci_device_addresses(pm8001_ha);
+       /* Write bit1=1 to Inbound DoorBell Register to tell the SPC FW the
+       table is stop */
+       pm8001_cw32(pm8001_ha, 0, MSGU_IBDB_SET, SPCv_MSGU_CFG_TABLE_RESET);
+
+       /* wait until Inbound DoorBell Clear Register toggled */
+       max_wait_count = 2 * 1000 * 1000;       /* 2 sec for spcv/ve */
+       do {
+               udelay(1);
+               value = pm8001_cr32(pm8001_ha, 0, MSGU_IBDB_SET);
+               value &= SPCv_MSGU_CFG_TABLE_RESET;
+       } while ((value != 0) && (--max_wait_count));
+
+       if (!max_wait_count) {
+               PM8001_FAIL_DBG(pm8001_ha,
+                       pm8001_printk("TIMEOUT:IBDB value/=%x\n", value));
+               return -1;
+       }
+
+       /* check the MPI-State for termination in progress */
+       /* wait until Inbound DoorBell Clear Register toggled */
+       max_wait_count = 2 * 1000 * 1000;       /* 2 sec for spcv/ve */
+       do {
+               udelay(1);
+               gst_len_mpistate =
+                       pm8001_mr32(pm8001_ha->general_stat_tbl_addr,
+                       GST_GSTLEN_MPIS_OFFSET);
+               if (GST_MPI_STATE_UNINIT ==
+                       (gst_len_mpistate & GST_MPI_STATE_MASK))
+                       break;
+       } while (--max_wait_count);
+       if (!max_wait_count) {
+               PM8001_FAIL_DBG(pm8001_ha,
+                       pm8001_printk(" TIME OUT MPI State = 0x%x\n",
+                               gst_len_mpistate & GST_MPI_STATE_MASK));
+               return -1;
+       }
+
+       return 0;
+}
+
+/**
+ * pm8001_chip_soft_rst - soft reset the PM8001 chip, so that the clear all
+ * the FW register status to the originated status.
+ * @pm8001_ha: our hba card information
+ */
+
+static int
+pm80xx_chip_soft_rst(struct pm8001_hba_info *pm8001_ha)
+{
+       u32 regval;
+       u32 bootloader_state;
+
+       /* Check if MPI is in ready state to reset */
+       if (mpi_uninit_check(pm8001_ha) != 0) {
+               PM8001_FAIL_DBG(pm8001_ha,
+                       pm8001_printk("MPI state is not ready\n"));
+               return -1;
+       }
+
+       /* checked for reset register normal state; 0x0 */
+       regval = pm8001_cr32(pm8001_ha, 0, SPC_REG_SOFT_RESET);
+       PM8001_INIT_DBG(pm8001_ha,
+               pm8001_printk("reset register before write : 0x%x\n", regval));
+
+       pm8001_cw32(pm8001_ha, 0, SPC_REG_SOFT_RESET, SPCv_NORMAL_RESET_VALUE);
+       mdelay(500);
+
+       regval = pm8001_cr32(pm8001_ha, 0, SPC_REG_SOFT_RESET);
+       PM8001_INIT_DBG(pm8001_ha,
+       pm8001_printk("reset register after write 0x%x\n", regval));
+
+       if ((regval & SPCv_SOFT_RESET_READ_MASK) ==
+                       SPCv_SOFT_RESET_NORMAL_RESET_OCCURED) {
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk(" soft reset successful [regval: 0x%x]\n",
+                                       regval));
+       } else {
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk(" soft reset failed [regval: 0x%x]\n",
+                                       regval));
+
+               /* check bootloader is successfully executed or in HDA mode */
+               bootloader_state =
+                       pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1) &
+                       SCRATCH_PAD1_BOOTSTATE_MASK;
+
+               if (bootloader_state == SCRATCH_PAD1_BOOTSTATE_HDA_SEEPROM) {
+                       PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
+                               "Bootloader state - HDA mode SEEPROM\n"));
+               } else if (bootloader_state ==
+                               SCRATCH_PAD1_BOOTSTATE_HDA_BOOTSTRAP) {
+                       PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
+                               "Bootloader state - HDA mode Bootstrap Pin\n"));
+               } else if (bootloader_state ==
+                               SCRATCH_PAD1_BOOTSTATE_HDA_SOFTRESET) {
+                       PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
+                               "Bootloader state - HDA mode soft reset\n"));
+               } else if (bootloader_state ==
+                                       SCRATCH_PAD1_BOOTSTATE_CRIT_ERROR) {
+                       PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
+                               "Bootloader state-HDA mode critical error\n"));
+               }
+               return -EBUSY;
+       }
+
+       /* check the firmware status after reset */
+       if (-1 == check_fw_ready(pm8001_ha)) {
+               PM8001_FAIL_DBG(pm8001_ha,
+                       pm8001_printk("Firmware is not ready!\n"));
+               return -EBUSY;
+       }
+       PM8001_INIT_DBG(pm8001_ha,
+               pm8001_printk("SPCv soft reset Complete\n"));
+       return 0;
+}
+
+static void pm80xx_hw_chip_rst(struct pm8001_hba_info *pm8001_ha)
+{
+        u32 i;
+
+       PM8001_INIT_DBG(pm8001_ha,
+               pm8001_printk("chip reset start\n"));
+
+       /* do SPCv chip reset. */
+       pm8001_cw32(pm8001_ha, 0, SPC_REG_SOFT_RESET, 0x11);
+       PM8001_INIT_DBG(pm8001_ha,
+               pm8001_printk("SPC soft reset Complete\n"));
+
+       /* Check this ..whether delay is required or no */
+       /* delay 10 usec */
+       udelay(10);
+
+       /* wait for 20 msec until the firmware gets reloaded */
+       i = 20;
+       do {
+               mdelay(1);
+       } while ((--i) != 0);
+
+       PM8001_INIT_DBG(pm8001_ha,
+               pm8001_printk("chip reset finished\n"));
+}
+
+/**
+ * pm8001_chip_interrupt_enable - enable PM8001 chip interrupt
+ * @pm8001_ha: our hba card information
+ */
+static void
+pm80xx_chip_intx_interrupt_enable(struct pm8001_hba_info *pm8001_ha)
+{
+       pm8001_cw32(pm8001_ha, 0, MSGU_ODMR, ODMR_CLEAR_ALL);
+       pm8001_cw32(pm8001_ha, 0, MSGU_ODCR, ODCR_CLEAR_ALL);
+}
+
+/**
+ * pm8001_chip_intx_interrupt_disable- disable PM8001 chip interrupt
+ * @pm8001_ha: our hba card information
+ */
+static void
+pm80xx_chip_intx_interrupt_disable(struct pm8001_hba_info *pm8001_ha)
+{
+       pm8001_cw32(pm8001_ha, 0, MSGU_ODMR_CLR, ODMR_MASK_ALL);
+}
+
+/**
+ * pm8001_chip_interrupt_enable - enable PM8001 chip interrupt
+ * @pm8001_ha: our hba card information
+ */
+static void
+pm80xx_chip_interrupt_enable(struct pm8001_hba_info *pm8001_ha, u8 vec)
+{
+#ifdef PM8001_USE_MSIX
+       u32 mask;
+       mask = (u32)(1 << vec);
+
+       pm8001_cw32(pm8001_ha, 0, MSGU_ODMR_CLR, (u32)(mask & 0xFFFFFFFF));
+       return;
+#endif
+       pm80xx_chip_intx_interrupt_enable(pm8001_ha);
+
+}
+
+/**
+ * pm8001_chip_interrupt_disable- disable PM8001 chip interrupt
+ * @pm8001_ha: our hba card information
+ */
+static void
+pm80xx_chip_interrupt_disable(struct pm8001_hba_info *pm8001_ha, u8 vec)
+{
+#ifdef PM8001_USE_MSIX
+       u32 mask;
+       if (vec == 0xFF)
+               mask = 0xFFFFFFFF;
+       else
+               mask = (u32)(1 << vec);
+       pm8001_cw32(pm8001_ha, 0, MSGU_ODMR, (u32)(mask & 0xFFFFFFFF));
+       return;
+#endif
+       pm80xx_chip_intx_interrupt_disable(pm8001_ha);
+}
+
+static void pm80xx_send_abort_all(struct pm8001_hba_info *pm8001_ha,
+               struct pm8001_device *pm8001_ha_dev)
+{
+       int res;
+       u32 ccb_tag;
+       struct pm8001_ccb_info *ccb;
+       struct sas_task *task = NULL;
+       struct task_abort_req task_abort;
+       struct inbound_queue_table *circularQ;
+       u32 opc = OPC_INB_SATA_ABORT;
+       int ret;
+
+       if (!pm8001_ha_dev) {
+               PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("dev is null\n"));
+               return;
+       }
+
+       task = sas_alloc_slow_task(GFP_ATOMIC);
+
+       if (!task) {
+               PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("cannot "
+                                               "allocate task\n"));
+               return;
+       }
+
+       task->task_done = pm8001_task_done;
+
+       res = pm8001_tag_alloc(pm8001_ha, &ccb_tag);
+       if (res)
+               return;
+
+       ccb = &pm8001_ha->ccb_info[ccb_tag];
+       ccb->device = pm8001_ha_dev;
+       ccb->ccb_tag = ccb_tag;
+       ccb->task = task;
+
+       circularQ = &pm8001_ha->inbnd_q_tbl[0];
+
+       memset(&task_abort, 0, sizeof(task_abort));
+       task_abort.abort_all = cpu_to_le32(1);
+       task_abort.device_id = cpu_to_le32(pm8001_ha_dev->device_id);
+       task_abort.tag = cpu_to_le32(ccb_tag);
+
+       ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort, 0);
+
+}
+
+static void pm80xx_send_read_log(struct pm8001_hba_info *pm8001_ha,
+               struct pm8001_device *pm8001_ha_dev)
+{
+       struct sata_start_req sata_cmd;
+       int res;
+       u32 ccb_tag;
+       struct pm8001_ccb_info *ccb;
+       struct sas_task *task = NULL;
+       struct host_to_dev_fis fis;
+       struct domain_device *dev;
+       struct inbound_queue_table *circularQ;
+       u32 opc = OPC_INB_SATA_HOST_OPSTART;
+
+       task = sas_alloc_slow_task(GFP_ATOMIC);
+
+       if (!task) {
+               PM8001_FAIL_DBG(pm8001_ha,
+                       pm8001_printk("cannot allocate task !!!\n"));
+               return;
+       }
+       task->task_done = pm8001_task_done;
+
+       res = pm8001_tag_alloc(pm8001_ha, &ccb_tag);
+       if (res) {
+               PM8001_FAIL_DBG(pm8001_ha,
+                       pm8001_printk("cannot allocate tag !!!\n"));
+               return;
+       }
+
+       /* allocate domain device by ourselves as libsas
+        * is not going to provide any
+       */
+       dev = kzalloc(sizeof(struct domain_device), GFP_ATOMIC);
+       if (!dev) {
+               PM8001_FAIL_DBG(pm8001_ha,
+                       pm8001_printk("Domain device cannot be allocated\n"));
+               sas_free_task(task);
+               return;
+       } else {
+               task->dev = dev;
+               task->dev->lldd_dev = pm8001_ha_dev;
+       }
+
+       ccb = &pm8001_ha->ccb_info[ccb_tag];
+       ccb->device = pm8001_ha_dev;
+       ccb->ccb_tag = ccb_tag;
+       ccb->task = task;
+       pm8001_ha_dev->id |= NCQ_READ_LOG_FLAG;
+       pm8001_ha_dev->id |= NCQ_2ND_RLE_FLAG;
+
+       memset(&sata_cmd, 0, sizeof(sata_cmd));
+       circularQ = &pm8001_ha->inbnd_q_tbl[0];
+
+       /* construct read log FIS */
+       memset(&fis, 0, sizeof(struct host_to_dev_fis));
+       fis.fis_type = 0x27;
+       fis.flags = 0x80;
+       fis.command = ATA_CMD_READ_LOG_EXT;
+       fis.lbal = 0x10;
+       fis.sector_count = 0x1;
+
+       sata_cmd.tag = cpu_to_le32(ccb_tag);
+       sata_cmd.device_id = cpu_to_le32(pm8001_ha_dev->device_id);
+       sata_cmd.ncqtag_atap_dir_m_dad |= ((0x1 << 7) | (0x5 << 9));
+       memcpy(&sata_cmd.sata_fis, &fis, sizeof(struct host_to_dev_fis));
+
+       res = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd, 0);
+
+}
+
+/**
+ * mpi_ssp_completion- process the event that FW response to the SSP request.
+ * @pm8001_ha: our hba card information
+ * @piomb: the message contents of this outbound message.
+ *
+ * When FW has completed a ssp request for example a IO request, after it has
+ * filled the SG data with the data, it will trigger this event represent
+ * that he has finished the job,please check the coresponding buffer.
+ * So we will tell the caller who maybe waiting the result to tell upper layer
+ * that the task has been finished.
+ */
+static void
+mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
+{
+       struct sas_task *t;
+       struct pm8001_ccb_info *ccb;
+       unsigned long flags;
+       u32 status;
+       u32 param;
+       u32 tag;
+       struct ssp_completion_resp *psspPayload;
+       struct task_status_struct *ts;
+       struct ssp_response_iu *iu;
+       struct pm8001_device *pm8001_dev;
+       psspPayload = (struct ssp_completion_resp *)(piomb + 4);
+       status = le32_to_cpu(psspPayload->status);
+       tag = le32_to_cpu(psspPayload->tag);
+       ccb = &pm8001_ha->ccb_info[tag];
+       if ((status == IO_ABORTED) && ccb->open_retry) {
+               /* Being completed by another */
+               ccb->open_retry = 0;
+               return;
+       }
+       pm8001_dev = ccb->device;
+       param = le32_to_cpu(psspPayload->param);
+       t = ccb->task;
+
+       if (status && status != IO_UNDERFLOW)
+               PM8001_FAIL_DBG(pm8001_ha,
+                       pm8001_printk("sas IO status 0x%x\n", status));
+       if (unlikely(!t || !t->lldd_task || !t->dev))
+               return;
+       ts = &t->task_status;
+       switch (status) {
+       case IO_SUCCESS:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_SUCCESS ,param = 0x%x\n",
+                               param));
+               if (param == 0) {
+                       ts->resp = SAS_TASK_COMPLETE;
+                       ts->stat = SAM_STAT_GOOD;
+               } else {
+                       ts->resp = SAS_TASK_COMPLETE;
+                       ts->stat = SAS_PROTO_RESPONSE;
+                       ts->residual = param;
+                       iu = &psspPayload->ssp_resp_iu;
+                       sas_ssp_task_response(pm8001_ha->dev, t, iu);
+               }
+               if (pm8001_dev)
+                       pm8001_dev->running_req--;
+               break;
+       case IO_ABORTED:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_ABORTED IOMB Tag\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_ABORTED_TASK;
+               break;
+       case IO_UNDERFLOW:
+               /* SSP Completion with error */
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_UNDERFLOW ,param = 0x%x\n",
+                               param));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_DATA_UNDERRUN;
+               ts->residual = param;
+               if (pm8001_dev)
+                       pm8001_dev->running_req--;
+               break;
+       case IO_NO_DEVICE:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_NO_DEVICE\n"));
+               ts->resp = SAS_TASK_UNDELIVERED;
+               ts->stat = SAS_PHY_DOWN;
+               break;
+       case IO_XFER_ERROR_BREAK:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_XFER_ERROR_BREAK\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_REJECT;
+               /* Force the midlayer to retry */
+               ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+               break;
+       case IO_XFER_ERROR_PHY_NOT_READY:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_XFER_ERROR_PHY_NOT_READY\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_REJECT;
+               ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+               break;
+       case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED:
+               PM8001_IO_DBG(pm8001_ha,
+               pm8001_printk("IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_REJECT;
+               ts->open_rej_reason = SAS_OREJ_EPROTO;
+               break;
+       case IO_OPEN_CNX_ERROR_ZONE_VIOLATION:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_REJECT;
+               ts->open_rej_reason = SAS_OREJ_UNKNOWN;
+               break;
+       case IO_OPEN_CNX_ERROR_BREAK:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_OPEN_CNX_ERROR_BREAK\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_REJECT;
+               ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+               break;
+       case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS:
+       case IO_XFER_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED:
+       case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_TMO:
+       case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST:
+       case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE:
+       case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_REJECT;
+               ts->open_rej_reason = SAS_OREJ_UNKNOWN;
+               if (!t->uldd_task)
+                       pm8001_handle_event(pm8001_ha,
+                               pm8001_dev,
+                               IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS);
+               break;
+       case IO_OPEN_CNX_ERROR_BAD_DESTINATION:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_OPEN_CNX_ERROR_BAD_DESTINATION\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_REJECT;
+               ts->open_rej_reason = SAS_OREJ_BAD_DEST;
+               break;
+       case IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED:
+               PM8001_IO_DBG(pm8001_ha, pm8001_printk(
+                       "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_REJECT;
+               ts->open_rej_reason = SAS_OREJ_CONN_RATE;
+               break;
+       case IO_OPEN_CNX_ERROR_WRONG_DESTINATION:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n"));
+               ts->resp = SAS_TASK_UNDELIVERED;
+               ts->stat = SAS_OPEN_REJECT;
+               ts->open_rej_reason = SAS_OREJ_WRONG_DEST;
+               break;
+       case IO_XFER_ERROR_NAK_RECEIVED:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_XFER_ERROR_NAK_RECEIVED\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_REJECT;
+               ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+               break;
+       case IO_XFER_ERROR_ACK_NAK_TIMEOUT:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_XFER_ERROR_ACK_NAK_TIMEOUT\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_NAK_R_ERR;
+               break;
+       case IO_XFER_ERROR_DMA:
+               PM8001_IO_DBG(pm8001_ha,
+               pm8001_printk("IO_XFER_ERROR_DMA\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_REJECT;
+               break;
+       case IO_XFER_OPEN_RETRY_TIMEOUT:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_XFER_OPEN_RETRY_TIMEOUT\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_REJECT;
+               ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+               break;
+       case IO_XFER_ERROR_OFFSET_MISMATCH:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_XFER_ERROR_OFFSET_MISMATCH\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_REJECT;
+               break;
+       case IO_PORT_IN_RESET:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_PORT_IN_RESET\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_REJECT;
+               break;
+       case IO_DS_NON_OPERATIONAL:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_DS_NON_OPERATIONAL\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_REJECT;
+               if (!t->uldd_task)
+                       pm8001_handle_event(pm8001_ha,
+                               pm8001_dev,
+                               IO_DS_NON_OPERATIONAL);
+               break;
+       case IO_DS_IN_RECOVERY:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_DS_IN_RECOVERY\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_REJECT;
+               break;
+       case IO_TM_TAG_NOT_FOUND:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_TM_TAG_NOT_FOUND\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_REJECT;
+               break;
+       case IO_SSP_EXT_IU_ZERO_LEN_ERROR:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_SSP_EXT_IU_ZERO_LEN_ERROR\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_REJECT;
+               break;
+       case IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_REJECT;
+               ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+               break;
+       default:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("Unknown status 0x%x\n", status));
+               /* not allowed case. Therefore, return failed status */
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_REJECT;
+               break;
+       }
+       PM8001_IO_DBG(pm8001_ha,
+               pm8001_printk("scsi_status = 0x%x\n ",
+               psspPayload->ssp_resp_iu.status));
+       spin_lock_irqsave(&t->task_state_lock, flags);
+       t->task_state_flags &= ~SAS_TASK_STATE_PENDING;
+       t->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
+       t->task_state_flags |= SAS_TASK_STATE_DONE;
+       if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) {
+               spin_unlock_irqrestore(&t->task_state_lock, flags);
+               PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
+                       "task 0x%p done with io_status 0x%x resp 0x%x "
+                       "stat 0x%x but aborted by upper layer!\n",
+                       t, status, ts->resp, ts->stat));
+               pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+       } else {
+               spin_unlock_irqrestore(&t->task_state_lock, flags);
+               pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+               mb();/* in order to force CPU ordering */
+               t->task_done(t);
+       }
+}
+
+/*See the comments for mpi_ssp_completion */
+static void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha , void *piomb)
+{
+       struct sas_task *t;
+       unsigned long flags;
+       struct task_status_struct *ts;
+       struct pm8001_ccb_info *ccb;
+       struct pm8001_device *pm8001_dev;
+       struct ssp_event_resp *psspPayload =
+               (struct ssp_event_resp *)(piomb + 4);
+       u32 event = le32_to_cpu(psspPayload->event);
+       u32 tag = le32_to_cpu(psspPayload->tag);
+       u32 port_id = le32_to_cpu(psspPayload->port_id);
+
+       ccb = &pm8001_ha->ccb_info[tag];
+       t = ccb->task;
+       pm8001_dev = ccb->device;
+       if (event)
+               PM8001_FAIL_DBG(pm8001_ha,
+                       pm8001_printk("sas IO status 0x%x\n", event));
+       if (unlikely(!t || !t->lldd_task || !t->dev))
+               return;
+       ts = &t->task_status;
+       PM8001_IO_DBG(pm8001_ha,
+               pm8001_printk("port_id:0x%x, tag:0x%x, event:0x%x\n",
+                               port_id, tag, event));
+       switch (event) {
+       case IO_OVERFLOW:
+               PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_UNDERFLOW\n");)
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_DATA_OVERRUN;
+               ts->residual = 0;
+               if (pm8001_dev)
+                       pm8001_dev->running_req--;
+               break;
+       case IO_XFER_ERROR_BREAK:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_XFER_ERROR_BREAK\n"));
+               pm8001_handle_event(pm8001_ha, t, IO_XFER_ERROR_BREAK);
+               return;
+       case IO_XFER_ERROR_PHY_NOT_READY:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_XFER_ERROR_PHY_NOT_READY\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_REJECT;
+               ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+               break;
+       case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED:
+               PM8001_IO_DBG(pm8001_ha, pm8001_printk(
+                       "IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_REJECT;
+               ts->open_rej_reason = SAS_OREJ_EPROTO;
+               break;
+       case IO_OPEN_CNX_ERROR_ZONE_VIOLATION:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_REJECT;
+               ts->open_rej_reason = SAS_OREJ_UNKNOWN;
+               break;
+       case IO_OPEN_CNX_ERROR_BREAK:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_OPEN_CNX_ERROR_BREAK\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_REJECT;
+               ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+               break;
+       case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS:
+       case IO_XFER_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED:
+       case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_TMO:
+       case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST:
+       case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE:
+       case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_REJECT;
+               ts->open_rej_reason = SAS_OREJ_UNKNOWN;
+               if (!t->uldd_task)
+                       pm8001_handle_event(pm8001_ha,
+                               pm8001_dev,
+                               IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS);
+               break;
+       case IO_OPEN_CNX_ERROR_BAD_DESTINATION:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_OPEN_CNX_ERROR_BAD_DESTINATION\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_REJECT;
+               ts->open_rej_reason = SAS_OREJ_BAD_DEST;
+               break;
+       case IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED:
+               PM8001_IO_DBG(pm8001_ha, pm8001_printk(
+                       "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_REJECT;
+               ts->open_rej_reason = SAS_OREJ_CONN_RATE;
+               break;
+       case IO_OPEN_CNX_ERROR_WRONG_DESTINATION:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_REJECT;
+               ts->open_rej_reason = SAS_OREJ_WRONG_DEST;
+               break;
+       case IO_XFER_ERROR_NAK_RECEIVED:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_XFER_ERROR_NAK_RECEIVED\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_REJECT;
+               ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+               break;
+       case IO_XFER_ERROR_ACK_NAK_TIMEOUT:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_XFER_ERROR_ACK_NAK_TIMEOUT\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_NAK_R_ERR;
+               break;
+       case IO_XFER_OPEN_RETRY_TIMEOUT:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_XFER_OPEN_RETRY_TIMEOUT\n"));
+               pm8001_handle_event(pm8001_ha, t, IO_XFER_OPEN_RETRY_TIMEOUT);
+               return;
+       case IO_XFER_ERROR_UNEXPECTED_PHASE:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_XFER_ERROR_UNEXPECTED_PHASE\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_DATA_OVERRUN;
+               break;
+       case IO_XFER_ERROR_XFER_RDY_OVERRUN:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_XFER_ERROR_XFER_RDY_OVERRUN\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_DATA_OVERRUN;
+               break;
+       case IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_DATA_OVERRUN;
+               break;
+       case IO_XFER_ERROR_CMD_ISSUE_ACK_NAK_TIMEOUT:
+               PM8001_IO_DBG(pm8001_ha,
+               pm8001_printk("IO_XFER_ERROR_CMD_ISSUE_ACK_NAK_TIMEOUT\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_DATA_OVERRUN;
+               break;
+       case IO_XFER_ERROR_OFFSET_MISMATCH:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_XFER_ERROR_OFFSET_MISMATCH\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_DATA_OVERRUN;
+               break;
+       case IO_XFER_ERROR_XFER_ZERO_DATA_LEN:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_XFER_ERROR_XFER_ZERO_DATA_LEN\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_DATA_OVERRUN;
+               break;
+       case IO_XFER_ERROR_INTERNAL_CRC_ERROR:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_XFR_ERROR_INTERNAL_CRC_ERROR\n"));
+               /* TBC: used default set values */
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_DATA_OVERRUN;
+               break;
+       case IO_XFER_CMD_FRAME_ISSUED:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_XFER_CMD_FRAME_ISSUED\n"));
+               return;
+       default:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("Unknown status 0x%x\n", event));
+               /* not allowed case. Therefore, return failed status */
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_DATA_OVERRUN;
+               break;
+       }
+       spin_lock_irqsave(&t->task_state_lock, flags);
+       t->task_state_flags &= ~SAS_TASK_STATE_PENDING;
+       t->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
+       t->task_state_flags |= SAS_TASK_STATE_DONE;
+       if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) {
+               spin_unlock_irqrestore(&t->task_state_lock, flags);
+               PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
+                       "task 0x%p done with event 0x%x resp 0x%x "
+                       "stat 0x%x but aborted by upper layer!\n",
+                       t, event, ts->resp, ts->stat));
+               pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+       } else {
+               spin_unlock_irqrestore(&t->task_state_lock, flags);
+               pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+               mb();/* in order to force CPU ordering */
+               t->task_done(t);
+       }
+}
+
+/*See the comments for mpi_ssp_completion */
+static void
+mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
+{
+       struct sas_task *t;
+       struct pm8001_ccb_info *ccb;
+       u32 param;
+       u32 status;
+       u32 tag;
+       struct sata_completion_resp *psataPayload;
+       struct task_status_struct *ts;
+       struct ata_task_resp *resp ;
+       u32 *sata_resp;
+       struct pm8001_device *pm8001_dev;
+       unsigned long flags;
+
+       psataPayload = (struct sata_completion_resp *)(piomb + 4);
+       status = le32_to_cpu(psataPayload->status);
+       tag = le32_to_cpu(psataPayload->tag);
+
+       if (!tag) {
+               PM8001_FAIL_DBG(pm8001_ha,
+                       pm8001_printk("tag null\n"));
+               return;
+       }
+       ccb = &pm8001_ha->ccb_info[tag];
+       param = le32_to_cpu(psataPayload->param);
+       if (ccb) {
+               t = ccb->task;
+               pm8001_dev = ccb->device;
+       } else {
+               PM8001_FAIL_DBG(pm8001_ha,
+                       pm8001_printk("ccb null\n"));
+               return;
+       }
+
+       if (t) {
+               if (t->dev && (t->dev->lldd_dev))
+                       pm8001_dev = t->dev->lldd_dev;
+       } else {
+               PM8001_FAIL_DBG(pm8001_ha,
+                       pm8001_printk("task null\n"));
+               return;
+       }
+
+       if ((pm8001_dev && !(pm8001_dev->id & NCQ_READ_LOG_FLAG))
+               && unlikely(!t || !t->lldd_task || !t->dev)) {
+               PM8001_FAIL_DBG(pm8001_ha,
+                       pm8001_printk("task or dev null\n"));
+               return;
+       }
+
+       ts = &t->task_status;
+       if (!ts) {
+               PM8001_FAIL_DBG(pm8001_ha,
+                       pm8001_printk("ts null\n"));
+               return;
+       }
+
+       switch (status) {
+       case IO_SUCCESS:
+               PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_SUCCESS\n"));
+               if (param == 0) {
+                       ts->resp = SAS_TASK_COMPLETE;
+                       ts->stat = SAM_STAT_GOOD;
+                       /* check if response is for SEND READ LOG */
+                       if (pm8001_dev &&
+                               (pm8001_dev->id & NCQ_READ_LOG_FLAG)) {
+                               /* set new bit for abort_all */
+                               pm8001_dev->id |= NCQ_ABORT_ALL_FLAG;
+                               /* clear bit for read log */
+                               pm8001_dev->id = pm8001_dev->id & 0x7FFFFFFF;
+                               pm80xx_send_abort_all(pm8001_ha, pm8001_dev);
+                               /* Free the tag */
+                               pm8001_tag_free(pm8001_ha, tag);
+                               sas_free_task(t);
+                               return;
+                       }
+               } else {
+                       u8 len;
+                       ts->resp = SAS_TASK_COMPLETE;
+                       ts->stat = SAS_PROTO_RESPONSE;
+                       ts->residual = param;
+                       PM8001_IO_DBG(pm8001_ha,
+                               pm8001_printk("SAS_PROTO_RESPONSE len = %d\n",
+                               param));
+                       sata_resp = &psataPayload->sata_resp[0];
+                       resp = (struct ata_task_resp *)ts->buf;
+                       if (t->ata_task.dma_xfer == 0 &&
+                       t->data_dir == PCI_DMA_FROMDEVICE) {
+                               len = sizeof(struct pio_setup_fis);
+                               PM8001_IO_DBG(pm8001_ha,
+                               pm8001_printk("PIO read len = %d\n", len));
+                       } else if (t->ata_task.use_ncq) {
+                               len = sizeof(struct set_dev_bits_fis);
+                               PM8001_IO_DBG(pm8001_ha,
+                                       pm8001_printk("FPDMA len = %d\n", len));
+                       } else {
+                               len = sizeof(struct dev_to_host_fis);
+                               PM8001_IO_DBG(pm8001_ha,
+                               pm8001_printk("other len = %d\n", len));
+                       }
+                       if (SAS_STATUS_BUF_SIZE >= sizeof(*resp)) {
+                               resp->frame_len = len;
+                               memcpy(&resp->ending_fis[0], sata_resp, len);
+                               ts->buf_valid_size = sizeof(*resp);
+                       } else
+                               PM8001_IO_DBG(pm8001_ha,
+                                       pm8001_printk("response to large\n"));
+               }
+               if (pm8001_dev)
+                       pm8001_dev->running_req--;
+               break;
+       case IO_ABORTED:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_ABORTED IOMB Tag\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_ABORTED_TASK;
+               if (pm8001_dev)
+                       pm8001_dev->running_req--;
+               break;
+               /* following cases are to do cases */
+       case IO_UNDERFLOW:
+               /* SATA Completion with error */
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_UNDERFLOW param = %d\n", param));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_DATA_UNDERRUN;
+               ts->residual = param;
+               if (pm8001_dev)
+                       pm8001_dev->running_req--;
+               break;
+       case IO_NO_DEVICE:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_NO_DEVICE\n"));
+               ts->resp = SAS_TASK_UNDELIVERED;
+               ts->stat = SAS_PHY_DOWN;
+               break;
+       case IO_XFER_ERROR_BREAK:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_XFER_ERROR_BREAK\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_INTERRUPTED;
+               break;
+       case IO_XFER_ERROR_PHY_NOT_READY:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_XFER_ERROR_PHY_NOT_READY\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_REJECT;
+               ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+               break;
+       case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED:
+               PM8001_IO_DBG(pm8001_ha, pm8001_printk(
+                       "IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_REJECT;
+               ts->open_rej_reason = SAS_OREJ_EPROTO;
+               break;
+       case IO_OPEN_CNX_ERROR_ZONE_VIOLATION:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_REJECT;
+               ts->open_rej_reason = SAS_OREJ_UNKNOWN;
+               break;
+       case IO_OPEN_CNX_ERROR_BREAK:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_OPEN_CNX_ERROR_BREAK\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_REJECT;
+               ts->open_rej_reason = SAS_OREJ_RSVD_CONT0;
+               break;
+       case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS:
+       case IO_XFER_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED:
+       case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_TMO:
+       case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST:
+       case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE:
+       case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_DEV_NO_RESPONSE;
+               if (!t->uldd_task) {
+                       pm8001_handle_event(pm8001_ha,
+                               pm8001_dev,
+                               IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS);
+                       ts->resp = SAS_TASK_UNDELIVERED;
+                       ts->stat = SAS_QUEUE_FULL;
+                       pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+                       mb();/*in order to force CPU ordering*/
+                       spin_unlock_irq(&pm8001_ha->lock);
+                       t->task_done(t);
+                       spin_lock_irq(&pm8001_ha->lock);
+                       return;
+               }
+               break;
+       case IO_OPEN_CNX_ERROR_BAD_DESTINATION:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_OPEN_CNX_ERROR_BAD_DESTINATION\n"));
+               ts->resp = SAS_TASK_UNDELIVERED;
+               ts->stat = SAS_OPEN_REJECT;
+               ts->open_rej_reason = SAS_OREJ_BAD_DEST;
+               if (!t->uldd_task) {
+                       pm8001_handle_event(pm8001_ha,
+                               pm8001_dev,
+                               IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS);
+                       ts->resp = SAS_TASK_UNDELIVERED;
+                       ts->stat = SAS_QUEUE_FULL;
+                       pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+                       mb();/*ditto*/
+                       spin_unlock_irq(&pm8001_ha->lock);
+                       t->task_done(t);
+                       spin_lock_irq(&pm8001_ha->lock);
+                       return;
+               }
+               break;
+       case IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED:
+               PM8001_IO_DBG(pm8001_ha, pm8001_printk(
+                       "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_REJECT;
+               ts->open_rej_reason = SAS_OREJ_CONN_RATE;
+               break;
+       case IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY:
+               PM8001_IO_DBG(pm8001_ha, pm8001_printk(
+                       "IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_DEV_NO_RESPONSE;
+               if (!t->uldd_task) {
+                       pm8001_handle_event(pm8001_ha,
+                               pm8001_dev,
+                               IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY);
+                       ts->resp = SAS_TASK_UNDELIVERED;
+                       ts->stat = SAS_QUEUE_FULL;
+                       pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+                       mb();/* ditto*/
+                       spin_unlock_irq(&pm8001_ha->lock);
+                       t->task_done(t);
+                       spin_lock_irq(&pm8001_ha->lock);
+                       return;
+               }
+               break;
+       case IO_OPEN_CNX_ERROR_WRONG_DESTINATION:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_REJECT;
+               ts->open_rej_reason = SAS_OREJ_WRONG_DEST;
+               break;
+       case IO_XFER_ERROR_NAK_RECEIVED:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_XFER_ERROR_NAK_RECEIVED\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_NAK_R_ERR;
+               break;
+       case IO_XFER_ERROR_ACK_NAK_TIMEOUT:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_XFER_ERROR_ACK_NAK_TIMEOUT\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_NAK_R_ERR;
+               break;
+       case IO_XFER_ERROR_DMA:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_XFER_ERROR_DMA\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_ABORTED_TASK;
+               break;
+       case IO_XFER_ERROR_SATA_LINK_TIMEOUT:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_XFER_ERROR_SATA_LINK_TIMEOUT\n"));
+               ts->resp = SAS_TASK_UNDELIVERED;
+               ts->stat = SAS_DEV_NO_RESPONSE;
+               break;
+       case IO_XFER_ERROR_REJECTED_NCQ_MODE:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_XFER_ERROR_REJECTED_NCQ_MODE\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_DATA_UNDERRUN;
+               break;
+       case IO_XFER_OPEN_RETRY_TIMEOUT:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_XFER_OPEN_RETRY_TIMEOUT\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_TO;
+               break;
+       case IO_PORT_IN_RESET:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_PORT_IN_RESET\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_DEV_NO_RESPONSE;
+               break;
+       case IO_DS_NON_OPERATIONAL:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_DS_NON_OPERATIONAL\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_DEV_NO_RESPONSE;
+               if (!t->uldd_task) {
+                       pm8001_handle_event(pm8001_ha, pm8001_dev,
+                                       IO_DS_NON_OPERATIONAL);
+                       ts->resp = SAS_TASK_UNDELIVERED;
+                       ts->stat = SAS_QUEUE_FULL;
+                       pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+                       mb();/*ditto*/
+                       spin_unlock_irq(&pm8001_ha->lock);
+                       t->task_done(t);
+                       spin_lock_irq(&pm8001_ha->lock);
+                       return;
+               }
+               break;
+       case IO_DS_IN_RECOVERY:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_DS_IN_RECOVERY\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_DEV_NO_RESPONSE;
+               break;
+       case IO_DS_IN_ERROR:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_DS_IN_ERROR\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_DEV_NO_RESPONSE;
+               if (!t->uldd_task) {
+                       pm8001_handle_event(pm8001_ha, pm8001_dev,
+                                       IO_DS_IN_ERROR);
+                       ts->resp = SAS_TASK_UNDELIVERED;
+                       ts->stat = SAS_QUEUE_FULL;
+                       pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+                       mb();/*ditto*/
+                       spin_unlock_irq(&pm8001_ha->lock);
+                       t->task_done(t);
+                       spin_lock_irq(&pm8001_ha->lock);
+                       return;
+               }
+               break;
+       case IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_REJECT;
+               ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+       default:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("Unknown status 0x%x\n", status));
+               /* not allowed case. Therefore, return failed status */
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_DEV_NO_RESPONSE;
+               break;
+       }
+       spin_lock_irqsave(&t->task_state_lock, flags);
+       t->task_state_flags &= ~SAS_TASK_STATE_PENDING;
+       t->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
+       t->task_state_flags |= SAS_TASK_STATE_DONE;
+       if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) {
+               spin_unlock_irqrestore(&t->task_state_lock, flags);
+               PM8001_FAIL_DBG(pm8001_ha,
+                       pm8001_printk("task 0x%p done with io_status 0x%x"
+                       " resp 0x%x stat 0x%x but aborted by upper layer!\n",
+                       t, status, ts->resp, ts->stat));
+               pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+       } else if (t->uldd_task) {
+               spin_unlock_irqrestore(&t->task_state_lock, flags);
+               pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+               mb();/* ditto */
+               spin_unlock_irq(&pm8001_ha->lock);
+               t->task_done(t);
+               spin_lock_irq(&pm8001_ha->lock);
+       } else if (!t->uldd_task) {
+               spin_unlock_irqrestore(&t->task_state_lock, flags);
+               pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+               mb();/*ditto*/
+               spin_unlock_irq(&pm8001_ha->lock);
+               t->task_done(t);
+               spin_lock_irq(&pm8001_ha->lock);
+       }
+}
+
+/*See the comments for mpi_ssp_completion */
+static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb)
+{
+       struct sas_task *t;
+       struct task_status_struct *ts;
+       struct pm8001_ccb_info *ccb;
+       struct pm8001_device *pm8001_dev;
+       struct sata_event_resp *psataPayload =
+               (struct sata_event_resp *)(piomb + 4);
+       u32 event = le32_to_cpu(psataPayload->event);
+       u32 tag = le32_to_cpu(psataPayload->tag);
+       u32 port_id = le32_to_cpu(psataPayload->port_id);
+       u32 dev_id = le32_to_cpu(psataPayload->device_id);
+       unsigned long flags;
+
+       ccb = &pm8001_ha->ccb_info[tag];
+
+       if (ccb) {
+               t = ccb->task;
+               pm8001_dev = ccb->device;
+       } else {
+               PM8001_FAIL_DBG(pm8001_ha,
+                       pm8001_printk("No CCB !!!. returning\n"));
+               return;
+       }
+       if (event)
+               PM8001_FAIL_DBG(pm8001_ha,
+                       pm8001_printk("SATA EVENT 0x%x\n", event));
+
+       /* Check if this is NCQ error */
+       if (event == IO_XFER_ERROR_ABORTED_NCQ_MODE) {
+               /* find device using device id */
+               pm8001_dev = pm8001_find_dev(pm8001_ha, dev_id);
+               /* send read log extension */
+               if (pm8001_dev)
+                       pm80xx_send_read_log(pm8001_ha, pm8001_dev);
+               return;
+       }
+
+       if (unlikely(!t || !t->lldd_task || !t->dev)) {
+               PM8001_FAIL_DBG(pm8001_ha,
+                       pm8001_printk("task or dev null\n"));
+               return;
+       }
+
+       ts = &t->task_status;
+       PM8001_IO_DBG(pm8001_ha,
+               pm8001_printk("port_id:0x%x, tag:0x%x, event:0x%x\n",
+                               port_id, tag, event));
+       switch (event) {
+       case IO_OVERFLOW:
+               PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_UNDERFLOW\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_DATA_OVERRUN;
+               ts->residual = 0;
+               if (pm8001_dev)
+                       pm8001_dev->running_req--;
+               break;
+       case IO_XFER_ERROR_BREAK:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_XFER_ERROR_BREAK\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_INTERRUPTED;
+               break;
+       case IO_XFER_ERROR_PHY_NOT_READY:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_XFER_ERROR_PHY_NOT_READY\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_REJECT;
+               ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+               break;
+       case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED:
+               PM8001_IO_DBG(pm8001_ha, pm8001_printk(
+                       "IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_REJECT;
+               ts->open_rej_reason = SAS_OREJ_EPROTO;
+               break;
+       case IO_OPEN_CNX_ERROR_ZONE_VIOLATION:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_REJECT;
+               ts->open_rej_reason = SAS_OREJ_UNKNOWN;
+               break;
+       case IO_OPEN_CNX_ERROR_BREAK:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_OPEN_CNX_ERROR_BREAK\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_REJECT;
+               ts->open_rej_reason = SAS_OREJ_RSVD_CONT0;
+               break;
+       case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS:
+       case IO_XFER_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED:
+       case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_TMO:
+       case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST:
+       case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE:
+       case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED:
+               PM8001_FAIL_DBG(pm8001_ha,
+                       pm8001_printk("IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n"));
+               ts->resp = SAS_TASK_UNDELIVERED;
+               ts->stat = SAS_DEV_NO_RESPONSE;
+               if (!t->uldd_task) {
+                       pm8001_handle_event(pm8001_ha,
+                               pm8001_dev,
+                               IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS);
+                       ts->resp = SAS_TASK_COMPLETE;
+                       ts->stat = SAS_QUEUE_FULL;
+                       pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+                       mb();/*ditto*/
+                       spin_unlock_irq(&pm8001_ha->lock);
+                       t->task_done(t);
+                       spin_lock_irq(&pm8001_ha->lock);
+                       return;
+               }
+               break;
+       case IO_OPEN_CNX_ERROR_BAD_DESTINATION:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_OPEN_CNX_ERROR_BAD_DESTINATION\n"));
+               ts->resp = SAS_TASK_UNDELIVERED;
+               ts->stat = SAS_OPEN_REJECT;
+               ts->open_rej_reason = SAS_OREJ_BAD_DEST;
+               break;
+       case IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED:
+               PM8001_IO_DBG(pm8001_ha, pm8001_printk(
+                       "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_REJECT;
+               ts->open_rej_reason = SAS_OREJ_CONN_RATE;
+               break;
+       case IO_OPEN_CNX_ERROR_WRONG_DESTINATION:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_REJECT;
+               ts->open_rej_reason = SAS_OREJ_WRONG_DEST;
+               break;
+       case IO_XFER_ERROR_NAK_RECEIVED:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_XFER_ERROR_NAK_RECEIVED\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_NAK_R_ERR;
+               break;
+       case IO_XFER_ERROR_PEER_ABORTED:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_XFER_ERROR_PEER_ABORTED\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_NAK_R_ERR;
+               break;
+       case IO_XFER_ERROR_REJECTED_NCQ_MODE:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_XFER_ERROR_REJECTED_NCQ_MODE\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_DATA_UNDERRUN;
+               break;
+       case IO_XFER_OPEN_RETRY_TIMEOUT:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_XFER_OPEN_RETRY_TIMEOUT\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_TO;
+               break;
+       case IO_XFER_ERROR_UNEXPECTED_PHASE:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_XFER_ERROR_UNEXPECTED_PHASE\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_TO;
+               break;
+       case IO_XFER_ERROR_XFER_RDY_OVERRUN:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_XFER_ERROR_XFER_RDY_OVERRUN\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_TO;
+               break;
+       case IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_TO;
+               break;
+       case IO_XFER_ERROR_OFFSET_MISMATCH:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_XFER_ERROR_OFFSET_MISMATCH\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_TO;
+               break;
+       case IO_XFER_ERROR_XFER_ZERO_DATA_LEN:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_XFER_ERROR_XFER_ZERO_DATA_LEN\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_TO;
+               break;
+       case IO_XFER_CMD_FRAME_ISSUED:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_XFER_CMD_FRAME_ISSUED\n"));
+               break;
+       case IO_XFER_PIO_SETUP_ERROR:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_XFER_PIO_SETUP_ERROR\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_TO;
+               break;
+       case IO_XFER_ERROR_INTERNAL_CRC_ERROR:
+               PM8001_FAIL_DBG(pm8001_ha,
+                       pm8001_printk("IO_XFR_ERROR_INTERNAL_CRC_ERROR\n"));
+               /* TBC: used default set values */
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_TO;
+               break;
+       case IO_XFER_DMA_ACTIVATE_TIMEOUT:
+               PM8001_FAIL_DBG(pm8001_ha,
+                       pm8001_printk("IO_XFR_DMA_ACTIVATE_TIMEOUT\n"));
+               /* TBC: used default set values */
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_TO;
+               break;
+       default:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("Unknown status 0x%x\n", event));
+               /* not allowed case. Therefore, return failed status */
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_TO;
+               break;
+       }
+       spin_lock_irqsave(&t->task_state_lock, flags);
+       t->task_state_flags &= ~SAS_TASK_STATE_PENDING;
+       t->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
+       t->task_state_flags |= SAS_TASK_STATE_DONE;
+       if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) {
+               spin_unlock_irqrestore(&t->task_state_lock, flags);
+               PM8001_FAIL_DBG(pm8001_ha,
+                       pm8001_printk("task 0x%p done with io_status 0x%x"
+                       " resp 0x%x stat 0x%x but aborted by upper layer!\n",
+                       t, event, ts->resp, ts->stat));
+               pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+       } else if (t->uldd_task) {
+               spin_unlock_irqrestore(&t->task_state_lock, flags);
+               pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+               mb();/* ditto */
+               spin_unlock_irq(&pm8001_ha->lock);
+               t->task_done(t);
+               spin_lock_irq(&pm8001_ha->lock);
+       } else if (!t->uldd_task) {
+               spin_unlock_irqrestore(&t->task_state_lock, flags);
+               pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+               mb();/*ditto*/
+               spin_unlock_irq(&pm8001_ha->lock);
+               t->task_done(t);
+               spin_lock_irq(&pm8001_ha->lock);
+       }
+}
+
+/*See the comments for mpi_ssp_completion */
+static void
+mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
+{
+       u32 param, i;
+       struct sas_task *t;
+       struct pm8001_ccb_info *ccb;
+       unsigned long flags;
+       u32 status;
+       u32 tag;
+       struct smp_completion_resp *psmpPayload;
+       struct task_status_struct *ts;
+       struct pm8001_device *pm8001_dev;
+       char *pdma_respaddr = NULL;
+
+       psmpPayload = (struct smp_completion_resp *)(piomb + 4);
+       status = le32_to_cpu(psmpPayload->status);
+       tag = le32_to_cpu(psmpPayload->tag);
+
+       ccb = &pm8001_ha->ccb_info[tag];
+       param = le32_to_cpu(psmpPayload->param);
+       t = ccb->task;
+       ts = &t->task_status;
+       pm8001_dev = ccb->device;
+       if (status)
+               PM8001_FAIL_DBG(pm8001_ha,
+                       pm8001_printk("smp IO status 0x%x\n", status));
+       if (unlikely(!t || !t->lldd_task || !t->dev))
+               return;
+
+       switch (status) {
+
+       case IO_SUCCESS:
+               PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_SUCCESS\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAM_STAT_GOOD;
+               if (pm8001_dev)
+                       pm8001_dev->running_req--;
+               if (pm8001_ha->smp_exp_mode == SMP_DIRECT) {
+                       PM8001_IO_DBG(pm8001_ha,
+                               pm8001_printk("DIRECT RESPONSE Length:%d\n",
+                                               param));
+                       pdma_respaddr = (char *)(phys_to_virt(cpu_to_le64
+                                               ((u64)sg_dma_address
+                                               (&t->smp_task.smp_resp))));
+                       for (i = 0; i < param; i++) {
+                               *(pdma_respaddr+i) = psmpPayload->_r_a[i];
+                               PM8001_IO_DBG(pm8001_ha, pm8001_printk(
+                                       "SMP Byte%d DMA data 0x%x psmp 0x%x\n",
+                                       i, *(pdma_respaddr+i),
+                                       psmpPayload->_r_a[i]));
+                       }
+               }
+               break;
+       case IO_ABORTED:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_ABORTED IOMB\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_ABORTED_TASK;
+               if (pm8001_dev)
+                       pm8001_dev->running_req--;
+               break;
+       case IO_OVERFLOW:
+               PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_UNDERFLOW\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_DATA_OVERRUN;
+               ts->residual = 0;
+               if (pm8001_dev)
+                       pm8001_dev->running_req--;
+               break;
+       case IO_NO_DEVICE:
+               PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_NO_DEVICE\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_PHY_DOWN;
+               break;
+       case IO_ERROR_HW_TIMEOUT:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_ERROR_HW_TIMEOUT\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAM_STAT_BUSY;
+               break;
+       case IO_XFER_ERROR_BREAK:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_XFER_ERROR_BREAK\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAM_STAT_BUSY;
+               break;
+       case IO_XFER_ERROR_PHY_NOT_READY:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_XFER_ERROR_PHY_NOT_READY\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAM_STAT_BUSY;
+               break;
+       case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED:
+               PM8001_IO_DBG(pm8001_ha,
+               pm8001_printk("IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_REJECT;
+               ts->open_rej_reason = SAS_OREJ_UNKNOWN;
+               break;
+       case IO_OPEN_CNX_ERROR_ZONE_VIOLATION:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_REJECT;
+               ts->open_rej_reason = SAS_OREJ_UNKNOWN;
+               break;
+       case IO_OPEN_CNX_ERROR_BREAK:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_OPEN_CNX_ERROR_BREAK\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_REJECT;
+               ts->open_rej_reason = SAS_OREJ_RSVD_CONT0;
+               break;
+       case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS:
+       case IO_XFER_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED:
+       case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_TMO:
+       case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST:
+       case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE:
+       case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_REJECT;
+               ts->open_rej_reason = SAS_OREJ_UNKNOWN;
+               pm8001_handle_event(pm8001_ha,
+                               pm8001_dev,
+                               IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS);
+               break;
+       case IO_OPEN_CNX_ERROR_BAD_DESTINATION:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_OPEN_CNX_ERROR_BAD_DESTINATION\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_REJECT;
+               ts->open_rej_reason = SAS_OREJ_BAD_DEST;
+               break;
+       case IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED:
+               PM8001_IO_DBG(pm8001_ha, pm8001_printk(\
+                       "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_REJECT;
+               ts->open_rej_reason = SAS_OREJ_CONN_RATE;
+               break;
+       case IO_OPEN_CNX_ERROR_WRONG_DESTINATION:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_REJECT;
+               ts->open_rej_reason = SAS_OREJ_WRONG_DEST;
+               break;
+       case IO_XFER_ERROR_RX_FRAME:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_XFER_ERROR_RX_FRAME\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_DEV_NO_RESPONSE;
+               break;
+       case IO_XFER_OPEN_RETRY_TIMEOUT:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_XFER_OPEN_RETRY_TIMEOUT\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_REJECT;
+               ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+               break;
+       case IO_ERROR_INTERNAL_SMP_RESOURCE:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_ERROR_INTERNAL_SMP_RESOURCE\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_QUEUE_FULL;
+               break;
+       case IO_PORT_IN_RESET:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_PORT_IN_RESET\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_REJECT;
+               ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+               break;
+       case IO_DS_NON_OPERATIONAL:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_DS_NON_OPERATIONAL\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_DEV_NO_RESPONSE;
+               break;
+       case IO_DS_IN_RECOVERY:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_DS_IN_RECOVERY\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_REJECT;
+               ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+               break;
+       case IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY\n"));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_OPEN_REJECT;
+               ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+               break;
+       default:
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("Unknown status 0x%x\n", status));
+               ts->resp = SAS_TASK_COMPLETE;
+               ts->stat = SAS_DEV_NO_RESPONSE;
+               /* not allowed case. Therefore, return failed status */
+               break;
+       }
+       spin_lock_irqsave(&t->task_state_lock, flags);
+       t->task_state_flags &= ~SAS_TASK_STATE_PENDING;
+       t->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
+       t->task_state_flags |= SAS_TASK_STATE_DONE;
+       if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) {
+               spin_unlock_irqrestore(&t->task_state_lock, flags);
+               PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
+                       "task 0x%p done with io_status 0x%x resp 0x%x"
+                       "stat 0x%x but aborted by upper layer!\n",
+                       t, status, ts->resp, ts->stat));
+               pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+       } else {
+               spin_unlock_irqrestore(&t->task_state_lock, flags);
+               pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+               mb();/* in order to force CPU ordering */
+               t->task_done(t);
+       }
+}
+
+/**
+ * pm80xx_hw_event_ack_req- For PM8001,some events need to acknowage to FW.
+ * @pm8001_ha: our hba card information
+ * @Qnum: the outbound queue message number.
+ * @SEA: source of event to ack
+ * @port_id: port id.
+ * @phyId: phy id.
+ * @param0: parameter 0.
+ * @param1: parameter 1.
+ */
+static void pm80xx_hw_event_ack_req(struct pm8001_hba_info *pm8001_ha,
+       u32 Qnum, u32 SEA, u32 port_id, u32 phyId, u32 param0, u32 param1)
+{
+       struct hw_event_ack_req  payload;
+       u32 opc = OPC_INB_SAS_HW_EVENT_ACK;
+
+       struct inbound_queue_table *circularQ;
+
+       memset((u8 *)&payload, 0, sizeof(payload));
+       circularQ = &pm8001_ha->inbnd_q_tbl[Qnum];
+       payload.tag = cpu_to_le32(1);
+       payload.phyid_sea_portid = cpu_to_le32(((SEA & 0xFFFF) << 8) |
+               ((phyId & 0xFF) << 24) | (port_id & 0xFF));
+       payload.param0 = cpu_to_le32(param0);
+       payload.param1 = cpu_to_le32(param1);
+       pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+}
+
+static int pm80xx_chip_phy_ctl_req(struct pm8001_hba_info *pm8001_ha,
+       u32 phyId, u32 phy_op);
+
+/**
+ * hw_event_sas_phy_up -FW tells me a SAS phy up event.
+ * @pm8001_ha: our hba card information
+ * @piomb: IO message buffer
+ */
+static void
+hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)
+{
+       struct hw_event_resp *pPayload =
+               (struct hw_event_resp *)(piomb + 4);
+       u32 lr_status_evt_portid =
+               le32_to_cpu(pPayload->lr_status_evt_portid);
+       u32 phyid_npip_portstate = le32_to_cpu(pPayload->phyid_npip_portstate);
+
+       u8 link_rate =
+               (u8)((lr_status_evt_portid & 0xF0000000) >> 28);
+       u8 port_id = (u8)(lr_status_evt_portid & 0x000000FF);
+       u8 phy_id =
+               (u8)((phyid_npip_portstate & 0xFF0000) >> 16);
+       u8 portstate = (u8)(phyid_npip_portstate & 0x0000000F);
+
+       struct pm8001_port *port = &pm8001_ha->port[port_id];
+       struct sas_ha_struct *sas_ha = pm8001_ha->sas;
+       struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
+       unsigned long flags;
+       u8 deviceType = pPayload->sas_identify.dev_type;
+       port->port_state = portstate;
+       PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
+               "portid:%d; phyid:%d; linkrate:%d; "
+               "portstate:%x; devicetype:%x\n",
+               port_id, phy_id, link_rate, portstate, deviceType));
+
+       switch (deviceType) {
+       case SAS_PHY_UNUSED:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("device type no device.\n"));
+               break;
+       case SAS_END_DEVICE:
+               PM8001_MSG_DBG(pm8001_ha, pm8001_printk("end device.\n"));
+               pm80xx_chip_phy_ctl_req(pm8001_ha, phy_id,
+                       PHY_NOTIFY_ENABLE_SPINUP);
+               port->port_attached = 1;
+               pm8001_get_lrate_mode(phy, link_rate);
+               break;
+       case SAS_EDGE_EXPANDER_DEVICE:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("expander device.\n"));
+               port->port_attached = 1;
+               pm8001_get_lrate_mode(phy, link_rate);
+               break;
+       case SAS_FANOUT_EXPANDER_DEVICE:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("fanout expander device.\n"));
+               port->port_attached = 1;
+               pm8001_get_lrate_mode(phy, link_rate);
+               break;
+       default:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("unknown device type(%x)\n", deviceType));
+               break;
+       }
+       phy->phy_type |= PORT_TYPE_SAS;
+       phy->identify.device_type = deviceType;
+       phy->phy_attached = 1;
+       if (phy->identify.device_type == SAS_END_DEVICE)
+               phy->identify.target_port_protocols = SAS_PROTOCOL_SSP;
+       else if (phy->identify.device_type != SAS_PHY_UNUSED)
+               phy->identify.target_port_protocols = SAS_PROTOCOL_SMP;
+       phy->sas_phy.oob_mode = SAS_OOB_MODE;
+       sas_ha->notify_phy_event(&phy->sas_phy, PHYE_OOB_DONE);
+       spin_lock_irqsave(&phy->sas_phy.frame_rcvd_lock, flags);
+       memcpy(phy->frame_rcvd, &pPayload->sas_identify,
+               sizeof(struct sas_identify_frame)-4);
+       phy->frame_rcvd_size = sizeof(struct sas_identify_frame) - 4;
+       pm8001_get_attached_sas_addr(phy, phy->sas_phy.attached_sas_addr);
+       spin_unlock_irqrestore(&phy->sas_phy.frame_rcvd_lock, flags);
+       if (pm8001_ha->flags == PM8001F_RUN_TIME)
+               mdelay(200);/*delay a moment to wait disk to spinup*/
+       pm8001_bytes_dmaed(pm8001_ha, phy_id);
+}
+
+/**
+ * hw_event_sata_phy_up -FW tells me a SATA phy up event.
+ * @pm8001_ha: our hba card information
+ * @piomb: IO message buffer
+ */
+static void
+hw_event_sata_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)
+{
+       struct hw_event_resp *pPayload =
+               (struct hw_event_resp *)(piomb + 4);
+       u32 phyid_npip_portstate = le32_to_cpu(pPayload->phyid_npip_portstate);
+       u32 lr_status_evt_portid =
+               le32_to_cpu(pPayload->lr_status_evt_portid);
+       u8 link_rate =
+               (u8)((lr_status_evt_portid & 0xF0000000) >> 28);
+       u8 port_id = (u8)(lr_status_evt_portid & 0x000000FF);
+       u8 phy_id =
+               (u8)((phyid_npip_portstate & 0xFF0000) >> 16);
+
+       u8 portstate = (u8)(phyid_npip_portstate & 0x0000000F);
+
+       struct pm8001_port *port = &pm8001_ha->port[port_id];
+       struct sas_ha_struct *sas_ha = pm8001_ha->sas;
+       struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
+       unsigned long flags;
+       PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
+               "port id %d, phy id %d link_rate %d portstate 0x%x\n",
+                               port_id, phy_id, link_rate, portstate));
+
+       port->port_state = portstate;
+       port->port_attached = 1;
+       pm8001_get_lrate_mode(phy, link_rate);
+       phy->phy_type |= PORT_TYPE_SATA;
+       phy->phy_attached = 1;
+       phy->sas_phy.oob_mode = SATA_OOB_MODE;
+       sas_ha->notify_phy_event(&phy->sas_phy, PHYE_OOB_DONE);
+       spin_lock_irqsave(&phy->sas_phy.frame_rcvd_lock, flags);
+       memcpy(phy->frame_rcvd, ((u8 *)&pPayload->sata_fis - 4),
+               sizeof(struct dev_to_host_fis));
+       phy->frame_rcvd_size = sizeof(struct dev_to_host_fis);
+       phy->identify.target_port_protocols = SAS_PROTOCOL_SATA;
+       phy->identify.device_type = SAS_SATA_DEV;
+       pm8001_get_attached_sas_addr(phy, phy->sas_phy.attached_sas_addr);
+       spin_unlock_irqrestore(&phy->sas_phy.frame_rcvd_lock, flags);
+       pm8001_bytes_dmaed(pm8001_ha, phy_id);
+}
+
+/**
+ * hw_event_phy_down -we should notify the libsas the phy is down.
+ * @pm8001_ha: our hba card information
+ * @piomb: IO message buffer
+ */
+static void
+hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void *piomb)
+{
+       struct hw_event_resp *pPayload =
+               (struct hw_event_resp *)(piomb + 4);
+
+       u32 lr_status_evt_portid =
+               le32_to_cpu(pPayload->lr_status_evt_portid);
+       u8 port_id = (u8)(lr_status_evt_portid & 0x000000FF);
+       u32 phyid_npip_portstate = le32_to_cpu(pPayload->phyid_npip_portstate);
+       u8 phy_id =
+               (u8)((phyid_npip_portstate & 0xFF0000) >> 16);
+       u8 portstate = (u8)(phyid_npip_portstate & 0x0000000F);
+
+       struct pm8001_port *port = &pm8001_ha->port[port_id];
+       struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
+       port->port_state = portstate;
+       phy->phy_type = 0;
+       phy->identify.device_type = 0;
+       phy->phy_attached = 0;
+       memset(&phy->dev_sas_addr, 0, SAS_ADDR_SIZE);
+       switch (portstate) {
+       case PORT_VALID:
+               break;
+       case PORT_INVALID:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk(" PortInvalid portID %d\n", port_id));
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk(" Last phy Down and port invalid\n"));
+               port->port_attached = 0;
+               pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_PHY_DOWN,
+                       port_id, phy_id, 0, 0);
+               break;
+       case PORT_IN_RESET:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk(" Port In Reset portID %d\n", port_id));
+               break;
+       case PORT_NOT_ESTABLISHED:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk(" phy Down and PORT_NOT_ESTABLISHED\n"));
+               port->port_attached = 0;
+               break;
+       case PORT_LOSTCOMM:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk(" phy Down and PORT_LOSTCOMM\n"));
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk(" Last phy Down and port invalid\n"));
+               port->port_attached = 0;
+               pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_PHY_DOWN,
+                       port_id, phy_id, 0, 0);
+               break;
+       default:
+               port->port_attached = 0;
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk(" phy Down and(default) = 0x%x\n",
+                       portstate));
+               break;
+
+       }
+}
+
+static int mpi_phy_start_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
+{
+       struct phy_start_resp *pPayload =
+               (struct phy_start_resp *)(piomb + 4);
+       u32 status =
+               le32_to_cpu(pPayload->status);
+       u32 phy_id =
+               le32_to_cpu(pPayload->phyid);
+       struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
+
+       PM8001_INIT_DBG(pm8001_ha,
+               pm8001_printk("phy start resp status:0x%x, phyid:0x%x\n",
+                               status, phy_id));
+       if (status == 0) {
+               phy->phy_state = 1;
+               if (pm8001_ha->flags == PM8001F_RUN_TIME)
+                       complete(phy->enable_completion);
+       }
+       return 0;
+
+}
+
+/**
+ * mpi_thermal_hw_event -The hw event has come.
+ * @pm8001_ha: our hba card information
+ * @piomb: IO message buffer
+ */
+static int mpi_thermal_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb)
+{
+       struct thermal_hw_event *pPayload =
+               (struct thermal_hw_event *)(piomb + 4);
+
+       u32 thermal_event = le32_to_cpu(pPayload->thermal_event);
+       u32 rht_lht = le32_to_cpu(pPayload->rht_lht);
+
+       if (thermal_event & 0x40) {
+               PM8001_IO_DBG(pm8001_ha, pm8001_printk(
+                       "Thermal Event: Local high temperature violated!\n"));
+               PM8001_IO_DBG(pm8001_ha, pm8001_printk(
+                       "Thermal Event: Measured local high temperature %d\n",
+                               ((rht_lht & 0xFF00) >> 8)));
+       }
+       if (thermal_event & 0x10) {
+               PM8001_IO_DBG(pm8001_ha, pm8001_printk(
+                       "Thermal Event: Remote high temperature violated!\n"));
+               PM8001_IO_DBG(pm8001_ha, pm8001_printk(
+                       "Thermal Event: Measured remote high temperature %d\n",
+                               ((rht_lht & 0xFF000000) >> 24)));
+       }
+       return 0;
+}
+
+/**
+ * mpi_hw_event -The hw event has come.
+ * @pm8001_ha: our hba card information
+ * @piomb: IO message buffer
+ */
+static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb)
+{
+       unsigned long flags;
+       struct hw_event_resp *pPayload =
+               (struct hw_event_resp *)(piomb + 4);
+       u32 lr_status_evt_portid =
+               le32_to_cpu(pPayload->lr_status_evt_portid);
+       u32 phyid_npip_portstate = le32_to_cpu(pPayload->phyid_npip_portstate);
+       u8 port_id = (u8)(lr_status_evt_portid & 0x000000FF);
+       u8 phy_id =
+               (u8)((phyid_npip_portstate & 0xFF0000) >> 16);
+       u16 eventType =
+               (u16)((lr_status_evt_portid & 0x00FFFF00) >> 8);
+       u8 status =
+               (u8)((lr_status_evt_portid & 0x0F000000) >> 24);
+
+       struct sas_ha_struct *sas_ha = pm8001_ha->sas;
+       struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
+       struct asd_sas_phy *sas_phy = sas_ha->sas_phy[phy_id];
+       PM8001_MSG_DBG(pm8001_ha,
+               pm8001_printk("portid:%d phyid:%d event:0x%x status:0x%x\n",
+                               port_id, phy_id, eventType, status));
+
+       switch (eventType) {
+
+       case HW_EVENT_SAS_PHY_UP:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("HW_EVENT_PHY_START_STATUS\n"));
+               hw_event_sas_phy_up(pm8001_ha, piomb);
+               break;
+       case HW_EVENT_SATA_PHY_UP:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("HW_EVENT_SATA_PHY_UP\n"));
+               hw_event_sata_phy_up(pm8001_ha, piomb);
+               break;
+       case HW_EVENT_SATA_SPINUP_HOLD:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("HW_EVENT_SATA_SPINUP_HOLD\n"));
+               sas_ha->notify_phy_event(&phy->sas_phy, PHYE_SPINUP_HOLD);
+               break;
+       case HW_EVENT_PHY_DOWN:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("HW_EVENT_PHY_DOWN\n"));
+               sas_ha->notify_phy_event(&phy->sas_phy, PHYE_LOSS_OF_SIGNAL);
+               phy->phy_attached = 0;
+               phy->phy_state = 0;
+               hw_event_phy_down(pm8001_ha, piomb);
+               break;
+       case HW_EVENT_PORT_INVALID:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("HW_EVENT_PORT_INVALID\n"));
+               sas_phy_disconnected(sas_phy);
+               phy->phy_attached = 0;
+               sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
+               break;
+       /* the broadcast change primitive received, tell the LIBSAS this event
+       to revalidate the sas domain*/
+       case HW_EVENT_BROADCAST_CHANGE:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("HW_EVENT_BROADCAST_CHANGE\n"));
+               pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_BROADCAST_CHANGE,
+                       port_id, phy_id, 1, 0);
+               spin_lock_irqsave(&sas_phy->sas_prim_lock, flags);
+               sas_phy->sas_prim = HW_EVENT_BROADCAST_CHANGE;
+               spin_unlock_irqrestore(&sas_phy->sas_prim_lock, flags);
+               sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
+               break;
+       case HW_EVENT_PHY_ERROR:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("HW_EVENT_PHY_ERROR\n"));
+               sas_phy_disconnected(&phy->sas_phy);
+               phy->phy_attached = 0;
+               sas_ha->notify_phy_event(&phy->sas_phy, PHYE_OOB_ERROR);
+               break;
+       case HW_EVENT_BROADCAST_EXP:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("HW_EVENT_BROADCAST_EXP\n"));
+               spin_lock_irqsave(&sas_phy->sas_prim_lock, flags);
+               sas_phy->sas_prim = HW_EVENT_BROADCAST_EXP;
+               spin_unlock_irqrestore(&sas_phy->sas_prim_lock, flags);
+               sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
+               break;
+       case HW_EVENT_LINK_ERR_INVALID_DWORD:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("HW_EVENT_LINK_ERR_INVALID_DWORD\n"));
+               pm80xx_hw_event_ack_req(pm8001_ha, 0,
+                       HW_EVENT_LINK_ERR_INVALID_DWORD, port_id, phy_id, 0, 0);
+               sas_phy_disconnected(sas_phy);
+               phy->phy_attached = 0;
+               sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
+               break;
+       case HW_EVENT_LINK_ERR_DISPARITY_ERROR:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("HW_EVENT_LINK_ERR_DISPARITY_ERROR\n"));
+               pm80xx_hw_event_ack_req(pm8001_ha, 0,
+                       HW_EVENT_LINK_ERR_DISPARITY_ERROR,
+                       port_id, phy_id, 0, 0);
+               sas_phy_disconnected(sas_phy);
+               phy->phy_attached = 0;
+               sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
+               break;
+       case HW_EVENT_LINK_ERR_CODE_VIOLATION:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("HW_EVENT_LINK_ERR_CODE_VIOLATION\n"));
+               pm80xx_hw_event_ack_req(pm8001_ha, 0,
+                       HW_EVENT_LINK_ERR_CODE_VIOLATION,
+                       port_id, phy_id, 0, 0);
+               sas_phy_disconnected(sas_phy);
+               phy->phy_attached = 0;
+               sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
+               break;
+       case HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH:
+               PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
+                               "HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH\n"));
+               pm80xx_hw_event_ack_req(pm8001_ha, 0,
+                       HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH,
+                       port_id, phy_id, 0, 0);
+               sas_phy_disconnected(sas_phy);
+               phy->phy_attached = 0;
+               sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
+               break;
+       case HW_EVENT_MALFUNCTION:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("HW_EVENT_MALFUNCTION\n"));
+               break;
+       case HW_EVENT_BROADCAST_SES:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("HW_EVENT_BROADCAST_SES\n"));
+               spin_lock_irqsave(&sas_phy->sas_prim_lock, flags);
+               sas_phy->sas_prim = HW_EVENT_BROADCAST_SES;
+               spin_unlock_irqrestore(&sas_phy->sas_prim_lock, flags);
+               sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
+               break;
+       case HW_EVENT_INBOUND_CRC_ERROR:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("HW_EVENT_INBOUND_CRC_ERROR\n"));
+               pm80xx_hw_event_ack_req(pm8001_ha, 0,
+                       HW_EVENT_INBOUND_CRC_ERROR,
+                       port_id, phy_id, 0, 0);
+               break;
+       case HW_EVENT_HARD_RESET_RECEIVED:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("HW_EVENT_HARD_RESET_RECEIVED\n"));
+               sas_ha->notify_port_event(sas_phy, PORTE_HARD_RESET);
+               break;
+       case HW_EVENT_ID_FRAME_TIMEOUT:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("HW_EVENT_ID_FRAME_TIMEOUT\n"));
+               sas_phy_disconnected(sas_phy);
+               phy->phy_attached = 0;
+               sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
+               break;
+       case HW_EVENT_LINK_ERR_PHY_RESET_FAILED:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("HW_EVENT_LINK_ERR_PHY_RESET_FAILED\n"));
+               pm80xx_hw_event_ack_req(pm8001_ha, 0,
+                       HW_EVENT_LINK_ERR_PHY_RESET_FAILED,
+                       port_id, phy_id, 0, 0);
+               sas_phy_disconnected(sas_phy);
+               phy->phy_attached = 0;
+               sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
+               break;
+       case HW_EVENT_PORT_RESET_TIMER_TMO:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("HW_EVENT_PORT_RESET_TIMER_TMO\n"));
+               sas_phy_disconnected(sas_phy);
+               phy->phy_attached = 0;
+               sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
+               break;
+       case HW_EVENT_PORT_RECOVERY_TIMER_TMO:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("HW_EVENT_PORT_RECOVERY_TIMER_TMO\n"));
+               pm80xx_hw_event_ack_req(pm8001_ha, 0,
+                       HW_EVENT_PORT_RECOVERY_TIMER_TMO,
+                       port_id, phy_id, 0, 0);
+               sas_phy_disconnected(sas_phy);
+               phy->phy_attached = 0;
+               sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
+               break;
+       case HW_EVENT_PORT_RECOVER:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("HW_EVENT_PORT_RECOVER\n"));
+               break;
+       case HW_EVENT_PORT_RESET_COMPLETE:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("HW_EVENT_PORT_RESET_COMPLETE\n"));
+               break;
+       case EVENT_BROADCAST_ASYNCH_EVENT:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("EVENT_BROADCAST_ASYNCH_EVENT\n"));
+               break;
+       default:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("Unknown event type 0x%x\n", eventType));
+               break;
+       }
+       return 0;
+}
+
+/**
+ * mpi_phy_stop_resp - SPCv specific
+ * @pm8001_ha: our hba card information
+ * @piomb: IO message buffer
+ */
+static int mpi_phy_stop_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
+{
+       struct phy_stop_resp *pPayload =
+               (struct phy_stop_resp *)(piomb + 4);
+       u32 status =
+               le32_to_cpu(pPayload->status);
+       u32 phyid =
+               le32_to_cpu(pPayload->phyid);
+       struct pm8001_phy *phy = &pm8001_ha->phy[phyid];
+       PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("phy:0x%x status:0x%x\n",
+                                       phyid, status));
+       if (status == 0)
+               phy->phy_state = 0;
+       return 0;
+}
+
+/**
+ * mpi_set_controller_config_resp - SPCv specific
+ * @pm8001_ha: our hba card information
+ * @piomb: IO message buffer
+ */
+static int mpi_set_controller_config_resp(struct pm8001_hba_info *pm8001_ha,
+                       void *piomb)
+{
+       struct set_ctrl_cfg_resp *pPayload =
+                       (struct set_ctrl_cfg_resp *)(piomb + 4);
+       u32 status = le32_to_cpu(pPayload->status);
+       u32 err_qlfr_pgcd = le32_to_cpu(pPayload->err_qlfr_pgcd);
+
+       PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
+                       "SET CONTROLLER RESP: status 0x%x qlfr_pgcd 0x%x\n",
+                       status, err_qlfr_pgcd));
+
+       return 0;
+}
+
+/**
+ * mpi_get_controller_config_resp - SPCv specific
+ * @pm8001_ha: our hba card information
+ * @piomb: IO message buffer
+ */
+static int mpi_get_controller_config_resp(struct pm8001_hba_info *pm8001_ha,
+                       void *piomb)
+{
+       PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk(" pm80xx_addition_functionality\n"));
+
+       return 0;
+}
+
+/**
+ * mpi_get_phy_profile_resp - SPCv specific
+ * @pm8001_ha: our hba card information
+ * @piomb: IO message buffer
+ */
+static int mpi_get_phy_profile_resp(struct pm8001_hba_info *pm8001_ha,
+                       void *piomb)
+{
+       PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk(" pm80xx_addition_functionality\n"));
+
+       return 0;
+}
+
+/**
+ * mpi_flash_op_ext_resp - SPCv specific
+ * @pm8001_ha: our hba card information
+ * @piomb: IO message buffer
+ */
+static int mpi_flash_op_ext_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
+{
+       PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk(" pm80xx_addition_functionality\n"));
+
+       return 0;
+}
+
+/**
+ * mpi_set_phy_profile_resp - SPCv specific
+ * @pm8001_ha: our hba card information
+ * @piomb: IO message buffer
+ */
+static int mpi_set_phy_profile_resp(struct pm8001_hba_info *pm8001_ha,
+                       void *piomb)
+{
+       PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk(" pm80xx_addition_functionality\n"));
+
+       return 0;
+}
+
+/**
+ * mpi_kek_management_resp - SPCv specific
+ * @pm8001_ha: our hba card information
+ * @piomb: IO message buffer
+ */
+static int mpi_kek_management_resp(struct pm8001_hba_info *pm8001_ha,
+                       void *piomb)
+{
+       struct kek_mgmt_resp *pPayload = (struct kek_mgmt_resp *)(piomb + 4);
+
+       u32 status = le32_to_cpu(pPayload->status);
+       u32 kidx_new_curr_ksop = le32_to_cpu(pPayload->kidx_new_curr_ksop);
+       u32 err_qlfr = le32_to_cpu(pPayload->err_qlfr);
+
+       PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
+               "KEK MGMT RESP. Status 0x%x idx_ksop 0x%x err_qlfr 0x%x\n",
+               status, kidx_new_curr_ksop, err_qlfr));
+
+       return 0;
+}
+
+/**
+ * mpi_dek_management_resp - SPCv specific
+ * @pm8001_ha: our hba card information
+ * @piomb: IO message buffer
+ */
+static int mpi_dek_management_resp(struct pm8001_hba_info *pm8001_ha,
+                       void *piomb)
+{
+       PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk(" pm80xx_addition_functionality\n"));
+
+       return 0;
+}
+
+/**
+ * ssp_coalesced_comp_resp - SPCv specific
+ * @pm8001_ha: our hba card information
+ * @piomb: IO message buffer
+ */
+static int ssp_coalesced_comp_resp(struct pm8001_hba_info *pm8001_ha,
+                       void *piomb)
+{
+       PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk(" pm80xx_addition_functionality\n"));
+
+       return 0;
+}
+
+/**
+ * process_one_iomb - process one outbound Queue memory block
+ * @pm8001_ha: our hba card information
+ * @piomb: IO message buffer
+ */
+static void process_one_iomb(struct pm8001_hba_info *pm8001_ha, void *piomb)
+{
+       __le32 pHeader = *(__le32 *)piomb;
+       u32 opc = (u32)((le32_to_cpu(pHeader)) & 0xFFF);
+
+       switch (opc) {
+       case OPC_OUB_ECHO:
+               PM8001_MSG_DBG(pm8001_ha, pm8001_printk("OPC_OUB_ECHO\n"));
+               break;
+       case OPC_OUB_HW_EVENT:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("OPC_OUB_HW_EVENT\n"));
+               mpi_hw_event(pm8001_ha, piomb);
+               break;
+       case OPC_OUB_THERM_HW_EVENT:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("OPC_OUB_THERMAL_EVENT\n"));
+               mpi_thermal_hw_event(pm8001_ha, piomb);
+               break;
+       case OPC_OUB_SSP_COMP:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("OPC_OUB_SSP_COMP\n"));
+               mpi_ssp_completion(pm8001_ha, piomb);
+               break;
+       case OPC_OUB_SMP_COMP:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("OPC_OUB_SMP_COMP\n"));
+               mpi_smp_completion(pm8001_ha, piomb);
+               break;
+       case OPC_OUB_LOCAL_PHY_CNTRL:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("OPC_OUB_LOCAL_PHY_CNTRL\n"));
+               pm8001_mpi_local_phy_ctl(pm8001_ha, piomb);
+               break;
+       case OPC_OUB_DEV_REGIST:
+               PM8001_MSG_DBG(pm8001_ha,
+               pm8001_printk("OPC_OUB_DEV_REGIST\n"));
+               pm8001_mpi_reg_resp(pm8001_ha, piomb);
+               break;
+       case OPC_OUB_DEREG_DEV:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("unresgister the deviece\n"));
+               pm8001_mpi_dereg_resp(pm8001_ha, piomb);
+               break;
+       case OPC_OUB_GET_DEV_HANDLE:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("OPC_OUB_GET_DEV_HANDLE\n"));
+               break;
+       case OPC_OUB_SATA_COMP:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("OPC_OUB_SATA_COMP\n"));
+               mpi_sata_completion(pm8001_ha, piomb);
+               break;
+       case OPC_OUB_SATA_EVENT:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("OPC_OUB_SATA_EVENT\n"));
+               mpi_sata_event(pm8001_ha, piomb);
+               break;
+       case OPC_OUB_SSP_EVENT:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("OPC_OUB_SSP_EVENT\n"));
+               mpi_ssp_event(pm8001_ha, piomb);
+               break;
+       case OPC_OUB_DEV_HANDLE_ARRIV:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("OPC_OUB_DEV_HANDLE_ARRIV\n"));
+               /*This is for target*/
+               break;
+       case OPC_OUB_SSP_RECV_EVENT:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("OPC_OUB_SSP_RECV_EVENT\n"));
+               /*This is for target*/
+               break;
+       case OPC_OUB_FW_FLASH_UPDATE:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("OPC_OUB_FW_FLASH_UPDATE\n"));
+               pm8001_mpi_fw_flash_update_resp(pm8001_ha, piomb);
+               break;
+       case OPC_OUB_GPIO_RESPONSE:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("OPC_OUB_GPIO_RESPONSE\n"));
+               break;
+       case OPC_OUB_GPIO_EVENT:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("OPC_OUB_GPIO_EVENT\n"));
+               break;
+       case OPC_OUB_GENERAL_EVENT:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("OPC_OUB_GENERAL_EVENT\n"));
+               pm8001_mpi_general_event(pm8001_ha, piomb);
+               break;
+       case OPC_OUB_SSP_ABORT_RSP:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("OPC_OUB_SSP_ABORT_RSP\n"));
+               pm8001_mpi_task_abort_resp(pm8001_ha, piomb);
+               break;
+       case OPC_OUB_SATA_ABORT_RSP:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("OPC_OUB_SATA_ABORT_RSP\n"));
+               pm8001_mpi_task_abort_resp(pm8001_ha, piomb);
+               break;
+       case OPC_OUB_SAS_DIAG_MODE_START_END:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("OPC_OUB_SAS_DIAG_MODE_START_END\n"));
+               break;
+       case OPC_OUB_SAS_DIAG_EXECUTE:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("OPC_OUB_SAS_DIAG_EXECUTE\n"));
+               break;
+       case OPC_OUB_GET_TIME_STAMP:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("OPC_OUB_GET_TIME_STAMP\n"));
+               break;
+       case OPC_OUB_SAS_HW_EVENT_ACK:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("OPC_OUB_SAS_HW_EVENT_ACK\n"));
+               break;
+       case OPC_OUB_PORT_CONTROL:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("OPC_OUB_PORT_CONTROL\n"));
+               break;
+       case OPC_OUB_SMP_ABORT_RSP:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("OPC_OUB_SMP_ABORT_RSP\n"));
+               pm8001_mpi_task_abort_resp(pm8001_ha, piomb);
+               break;
+       case OPC_OUB_GET_NVMD_DATA:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("OPC_OUB_GET_NVMD_DATA\n"));
+               pm8001_mpi_get_nvmd_resp(pm8001_ha, piomb);
+               break;
+       case OPC_OUB_SET_NVMD_DATA:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("OPC_OUB_SET_NVMD_DATA\n"));
+               pm8001_mpi_set_nvmd_resp(pm8001_ha, piomb);
+               break;
+       case OPC_OUB_DEVICE_HANDLE_REMOVAL:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("OPC_OUB_DEVICE_HANDLE_REMOVAL\n"));
+               break;
+       case OPC_OUB_SET_DEVICE_STATE:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("OPC_OUB_SET_DEVICE_STATE\n"));
+               pm8001_mpi_set_dev_state_resp(pm8001_ha, piomb);
+               break;
+       case OPC_OUB_GET_DEVICE_STATE:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("OPC_OUB_GET_DEVICE_STATE\n"));
+               break;
+       case OPC_OUB_SET_DEV_INFO:
+               PM8001_MSG_DBG(pm8001_ha,
+                       pm8001_printk("OPC_OUB_SET_DEV_INFO\n"));
+               break;
+       /* spcv specifc commands */
+       case OPC_OUB_PHY_START_RESP:
+               PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
+                       "OPC_OUB_PHY_START_RESP opcode:%x\n", opc));
+               mpi_phy_start_resp(pm8001_ha, piomb);
+               break;
+       case OPC_OUB_PHY_STOP_RESP:
+               PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
+                       "OPC_OUB_PHY_STOP_RESP opcode:%x\n", opc));
+               mpi_phy_stop_resp(pm8001_ha, piomb);
+               break;
+       case OPC_OUB_SET_CONTROLLER_CONFIG:
+               PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
+                       "OPC_OUB_SET_CONTROLLER_CONFIG opcode:%x\n", opc));
+               mpi_set_controller_config_resp(pm8001_ha, piomb);
+               break;
+       case OPC_OUB_GET_CONTROLLER_CONFIG:
+               PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
+                       "OPC_OUB_GET_CONTROLLER_CONFIG opcode:%x\n", opc));
+               mpi_get_controller_config_resp(pm8001_ha, piomb);
+               break;
+       case OPC_OUB_GET_PHY_PROFILE:
+               PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
+                       "OPC_OUB_GET_PHY_PROFILE opcode:%x\n", opc));
+               mpi_get_phy_profile_resp(pm8001_ha, piomb);
+               break;
+       case OPC_OUB_FLASH_OP_EXT:
+               PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
+                       "OPC_OUB_FLASH_OP_EXT opcode:%x\n", opc));
+               mpi_flash_op_ext_resp(pm8001_ha, piomb);
+               break;
+       case OPC_OUB_SET_PHY_PROFILE:
+               PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
+                       "OPC_OUB_SET_PHY_PROFILE opcode:%x\n", opc));
+               mpi_set_phy_profile_resp(pm8001_ha, piomb);
+               break;
+       case OPC_OUB_KEK_MANAGEMENT_RESP:
+               PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
+                       "OPC_OUB_KEK_MANAGEMENT_RESP opcode:%x\n", opc));
+               mpi_kek_management_resp(pm8001_ha, piomb);
+               break;
+       case OPC_OUB_DEK_MANAGEMENT_RESP:
+               PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
+                       "OPC_OUB_DEK_MANAGEMENT_RESP opcode:%x\n", opc));
+               mpi_dek_management_resp(pm8001_ha, piomb);
+               break;
+       case OPC_OUB_SSP_COALESCED_COMP_RESP:
+               PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
+                       "OPC_OUB_SSP_COALESCED_COMP_RESP opcode:%x\n", opc));
+               ssp_coalesced_comp_resp(pm8001_ha, piomb);
+               break;
+       default:
+               PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
+                       "Unknown outbound Queue IOMB OPC = 0x%x\n", opc));
+               break;
+       }
+}
+
+static int process_oq(struct pm8001_hba_info *pm8001_ha, u8 vec)
+{
+       struct outbound_queue_table *circularQ;
+       void *pMsg1 = NULL;
+       u8 uninitialized_var(bc);
+       u32 ret = MPI_IO_STATUS_FAIL;
+       unsigned long flags;
+
+       spin_lock_irqsave(&pm8001_ha->lock, flags);
+       circularQ = &pm8001_ha->outbnd_q_tbl[vec];
+       do {
+               ret = pm8001_mpi_msg_consume(pm8001_ha, circularQ, &pMsg1, &bc);
+               if (MPI_IO_STATUS_SUCCESS == ret) {
+                       /* process the outbound message */
+                       process_one_iomb(pm8001_ha, (void *)(pMsg1 - 4));
+                       /* free the message from the outbound circular buffer */
+                       pm8001_mpi_msg_free_set(pm8001_ha, pMsg1,
+                                                       circularQ, bc);
+               }
+               if (MPI_IO_STATUS_BUSY == ret) {
+                       /* Update the producer index from SPC */
+                       circularQ->producer_index =
+                               cpu_to_le32(pm8001_read_32(circularQ->pi_virt));
+                       if (le32_to_cpu(circularQ->producer_index) ==
+                               circularQ->consumer_idx)
+                               /* OQ is empty */
+                               break;
+               }
+       } while (1);
+       spin_unlock_irqrestore(&pm8001_ha->lock, flags);
+       return ret;
+}
+
+/* PCI_DMA_... to our direction translation. */
+static const u8 data_dir_flags[] = {
+       [PCI_DMA_BIDIRECTIONAL] = DATA_DIR_BYRECIPIENT,/* UNSPECIFIED */
+       [PCI_DMA_TODEVICE]      = DATA_DIR_OUT,/* OUTBOUND */
+       [PCI_DMA_FROMDEVICE]    = DATA_DIR_IN,/* INBOUND */
+       [PCI_DMA_NONE]          = DATA_DIR_NONE,/* NO TRANSFER */
+};
+
+static void build_smp_cmd(u32 deviceID, __le32 hTag,
+                       struct smp_req *psmp_cmd, int mode, int length)
+{
+       psmp_cmd->tag = hTag;
+       psmp_cmd->device_id = cpu_to_le32(deviceID);
+       if (mode == SMP_DIRECT) {
+               length = length - 4; /* subtract crc */
+               psmp_cmd->len_ip_ir = cpu_to_le32(length << 16);
+       } else {
+               psmp_cmd->len_ip_ir = cpu_to_le32(1|(1 << 1));
+       }
+}
+
+/**
+ * pm8001_chip_smp_req - send a SMP task to FW
+ * @pm8001_ha: our hba card information.
+ * @ccb: the ccb information this request used.
+ */
+static int pm80xx_chip_smp_req(struct pm8001_hba_info *pm8001_ha,
+       struct pm8001_ccb_info *ccb)
+{
+       int elem, rc;
+       struct sas_task *task = ccb->task;
+       struct domain_device *dev = task->dev;
+       struct pm8001_device *pm8001_dev = dev->lldd_dev;
+       struct scatterlist *sg_req, *sg_resp;
+       u32 req_len, resp_len;
+       struct smp_req smp_cmd;
+       u32 opc;
+       struct inbound_queue_table *circularQ;
+       char *preq_dma_addr = NULL;
+       __le64 tmp_addr;
+       u32 i, length;
+
+       memset(&smp_cmd, 0, sizeof(smp_cmd));
+       /*
+        * DMA-map SMP request, response buffers
+        */
+       sg_req = &task->smp_task.smp_req;
+       elem = dma_map_sg(pm8001_ha->dev, sg_req, 1, PCI_DMA_TODEVICE);
+       if (!elem)
+               return -ENOMEM;
+       req_len = sg_dma_len(sg_req);
+
+       sg_resp = &task->smp_task.smp_resp;
+       elem = dma_map_sg(pm8001_ha->dev, sg_resp, 1, PCI_DMA_FROMDEVICE);
+       if (!elem) {
+               rc = -ENOMEM;
+               goto err_out;
+       }
+       resp_len = sg_dma_len(sg_resp);
+       /* must be in dwords */
+       if ((req_len & 0x3) || (resp_len & 0x3)) {
+               rc = -EINVAL;
+               goto err_out_2;
+       }
+
+       opc = OPC_INB_SMP_REQUEST;
+       circularQ = &pm8001_ha->inbnd_q_tbl[0];
+       smp_cmd.tag = cpu_to_le32(ccb->ccb_tag);
+
+       length = sg_req->length;
+       PM8001_IO_DBG(pm8001_ha,
+               pm8001_printk("SMP Frame Length %d\n", sg_req->length));
+       if (!(length - 8))
+               pm8001_ha->smp_exp_mode = SMP_DIRECT;
+       else
+               pm8001_ha->smp_exp_mode = SMP_INDIRECT;
+
+       /* DIRECT MODE support only in spcv/ve */
+       pm8001_ha->smp_exp_mode = SMP_DIRECT;
+
+       tmp_addr = cpu_to_le64((u64)sg_dma_address(&task->smp_task.smp_req));
+       preq_dma_addr = (char *)phys_to_virt(tmp_addr);
+
+       /* INDIRECT MODE command settings. Use DMA */
+       if (pm8001_ha->smp_exp_mode == SMP_INDIRECT) {
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("SMP REQUEST INDIRECT MODE\n"));
+               /* for SPCv indirect mode. Place the top 4 bytes of
+                * SMP Request header here. */
+               for (i = 0; i < 4; i++)
+                       smp_cmd.smp_req16[i] = *(preq_dma_addr + i);
+               /* exclude top 4 bytes for SMP req header */
+               smp_cmd.long_smp_req.long_req_addr =
+                       cpu_to_le64((u64)sg_dma_address
+                               (&task->smp_task.smp_req) - 4);
+               /* exclude 4 bytes for SMP req header and CRC */
+               smp_cmd.long_smp_req.long_req_size =
+                       cpu_to_le32((u32)sg_dma_len(&task->smp_task.smp_req)-8);
+               smp_cmd.long_smp_req.long_resp_addr =
+                               cpu_to_le64((u64)sg_dma_address
+                                       (&task->smp_task.smp_resp));
+               smp_cmd.long_smp_req.long_resp_size =
+                               cpu_to_le32((u32)sg_dma_len
+                                       (&task->smp_task.smp_resp)-4);
+       } else { /* DIRECT MODE */
+               smp_cmd.long_smp_req.long_req_addr =
+                       cpu_to_le64((u64)sg_dma_address
+                                       (&task->smp_task.smp_req));
+               smp_cmd.long_smp_req.long_req_size =
+                       cpu_to_le32((u32)sg_dma_len(&task->smp_task.smp_req)-4);
+               smp_cmd.long_smp_req.long_resp_addr =
+                       cpu_to_le64((u64)sg_dma_address
+                               (&task->smp_task.smp_resp));
+               smp_cmd.long_smp_req.long_resp_size =
+                       cpu_to_le32
+                       ((u32)sg_dma_len(&task->smp_task.smp_resp)-4);
+       }
+       if (pm8001_ha->smp_exp_mode == SMP_DIRECT) {
+               PM8001_IO_DBG(pm8001_ha,
+                       pm8001_printk("SMP REQUEST DIRECT MODE\n"));
+               for (i = 0; i < length; i++)
+                       if (i < 16) {
+                               smp_cmd.smp_req16[i] = *(preq_dma_addr+i);
+                               PM8001_IO_DBG(pm8001_ha, pm8001_printk(
+                                       "Byte[%d]:%x (DMA data:%x)\n",
+                                       i, smp_cmd.smp_req16[i],
+                                       *(preq_dma_addr)));
+                       } else {
+                               smp_cmd.smp_req[i] = *(preq_dma_addr+i);
+                               PM8001_IO_DBG(pm8001_ha, pm8001_printk(
+                                       "Byte[%d]:%x (DMA data:%x)\n",
+                                       i, smp_cmd.smp_req[i],
+                                       *(preq_dma_addr)));
+                       }
+       }
+
+       build_smp_cmd(pm8001_dev->device_id, smp_cmd.tag,
+                               &smp_cmd, pm8001_ha->smp_exp_mode, length);
+       pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, (u32 *)&smp_cmd, 0);
+       return 0;
+
+err_out_2:
+       dma_unmap_sg(pm8001_ha->dev, &ccb->task->smp_task.smp_resp, 1,
+                       PCI_DMA_FROMDEVICE);
+err_out:
+       dma_unmap_sg(pm8001_ha->dev, &ccb->task->smp_task.smp_req, 1,
+                       PCI_DMA_TODEVICE);
+       return rc;
+}
+
+static int check_enc_sas_cmd(struct sas_task *task)
+{
+       if ((task->ssp_task.cdb[0] == READ_10)
+               || (task->ssp_task.cdb[0] == WRITE_10)
+               || (task->ssp_task.cdb[0] == WRITE_VERIFY))
+               return 1;
+       else
+               return 0;
+}
+
+static int check_enc_sat_cmd(struct sas_task *task)
+{
+       int ret = 0;
+       switch (task->ata_task.fis.command) {
+       case ATA_CMD_FPDMA_READ:
+       case ATA_CMD_READ_EXT:
+       case ATA_CMD_READ:
+       case ATA_CMD_FPDMA_WRITE:
+       case ATA_CMD_WRITE_EXT:
+       case ATA_CMD_WRITE:
+       case ATA_CMD_PIO_READ:
+       case ATA_CMD_PIO_READ_EXT:
+       case ATA_CMD_PIO_WRITE:
+       case ATA_CMD_PIO_WRITE_EXT:
+               ret = 1;
+               break;
+       default:
+               ret = 0;
+               break;
+       }
+       return ret;
+}
+
+/**
+ * pm80xx_chip_ssp_io_req - send a SSP task to FW
+ * @pm8001_ha: our hba card information.
+ * @ccb: the ccb information this request used.
+ */
+static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha,
+       struct pm8001_ccb_info *ccb)
+{
+       struct sas_task *task = ccb->task;
+       struct domain_device *dev = task->dev;
+       struct pm8001_device *pm8001_dev = dev->lldd_dev;
+       struct ssp_ini_io_start_req ssp_cmd;
+       u32 tag = ccb->ccb_tag;
+       int ret;
+       u64 phys_addr;
+       struct inbound_queue_table *circularQ;
+       static u32 inb;
+       static u32 outb;
+       u32 opc = OPC_INB_SSPINIIOSTART;
+       memset(&ssp_cmd, 0, sizeof(ssp_cmd));
+       memcpy(ssp_cmd.ssp_iu.lun, task->ssp_task.LUN, 8);
+       /* data address domain added for spcv; set to 0 by host,
+        * used internally by controller
+        * 0 for SAS 1.1 and SAS 2.0 compatible TLR
+        */
+       ssp_cmd.dad_dir_m_tlr =
+               cpu_to_le32(data_dir_flags[task->data_dir] << 8 | 0x0);
+       ssp_cmd.data_len = cpu_to_le32(task->total_xfer_len);
+       ssp_cmd.device_id = cpu_to_le32(pm8001_dev->device_id);
+       ssp_cmd.tag = cpu_to_le32(tag);
+       if (task->ssp_task.enable_first_burst)
+               ssp_cmd.ssp_iu.efb_prio_attr |= 0x80;
+       ssp_cmd.ssp_iu.efb_prio_attr |= (task->ssp_task.task_prio << 3);
+       ssp_cmd.ssp_iu.efb_prio_attr |= (task->ssp_task.task_attr & 7);
+       memcpy(ssp_cmd.ssp_iu.cdb, task->ssp_task.cdb, 16);
+       circularQ = &pm8001_ha->inbnd_q_tbl[0];
+
+       /* Check if encryption is set */
+       if (pm8001_ha->chip->encrypt &&
+               !(pm8001_ha->encrypt_info.status) && check_enc_sas_cmd(task)) {
+               PM8001_IO_DBG(pm8001_ha, pm8001_printk(
+                       "Encryption enabled.Sending Encrypt SAS command 0x%x\n",
+                       task->ssp_task.cdb[0]));
+               opc = OPC_INB_SSP_INI_DIF_ENC_IO;
+               /* enable encryption. 0 for SAS 1.1 and SAS 2.0 compatible TLR*/
+               ssp_cmd.dad_dir_m_tlr = cpu_to_le32
+                       ((data_dir_flags[task->data_dir] << 8) | 0x20 | 0x0);
+
+               /* fill in PRD (scatter/gather) table, if any */
+               if (task->num_scatter > 1) {
+                       pm8001_chip_make_sg(task->scatter,
+                                               ccb->n_elem, ccb->buf_prd);
+                       phys_addr = ccb->ccb_dma_handle +
+                               offsetof(struct pm8001_ccb_info, buf_prd[0]);
+                       ssp_cmd.enc_addr_low =
+                               cpu_to_le32(lower_32_bits(phys_addr));
+                       ssp_cmd.enc_addr_high =
+                               cpu_to_le32(upper_32_bits(phys_addr));
+                       ssp_cmd.enc_esgl = cpu_to_le32(1<<31);
+               } else if (task->num_scatter == 1) {
+                       u64 dma_addr = sg_dma_address(task->scatter);
+                       ssp_cmd.enc_addr_low =
+                               cpu_to_le32(lower_32_bits(dma_addr));
+                       ssp_cmd.enc_addr_high =
+                               cpu_to_le32(upper_32_bits(dma_addr));
+                       ssp_cmd.enc_len = cpu_to_le32(task->total_xfer_len);
+                       ssp_cmd.enc_esgl = 0;
+               } else if (task->num_scatter == 0) {
+                       ssp_cmd.enc_addr_low = 0;
+                       ssp_cmd.enc_addr_high = 0;
+                       ssp_cmd.enc_len = cpu_to_le32(task->total_xfer_len);
+                       ssp_cmd.enc_esgl = 0;
+               }
+               /* XTS mode. All other fields are 0 */
+               ssp_cmd.key_cmode = 0x6 << 4;
+               /* set tweak values. Should be the start lba */
+               ssp_cmd.twk_val0 = cpu_to_le32((task->ssp_task.cdb[2] << 24) |
+                                               (task->ssp_task.cdb[3] << 16) |
+                                               (task->ssp_task.cdb[4] << 8) |
+                                               (task->ssp_task.cdb[5]));
+       } else {
+               PM8001_IO_DBG(pm8001_ha, pm8001_printk(
+                       "Sending Normal SAS command 0x%x inb q %x\n",
+                       task->ssp_task.cdb[0], inb));
+               /* fill in PRD (scatter/gather) table, if any */
+               if (task->num_scatter > 1) {
+                       pm8001_chip_make_sg(task->scatter, ccb->n_elem,
+                                       ccb->buf_prd);
+                       phys_addr = ccb->ccb_dma_handle +
+                               offsetof(struct pm8001_ccb_info, buf_prd[0]);
+                       ssp_cmd.addr_low =
+                               cpu_to_le32(lower_32_bits(phys_addr));
+                       ssp_cmd.addr_high =
+                               cpu_to_le32(upper_32_bits(phys_addr));
+                       ssp_cmd.esgl = cpu_to_le32(1<<31);
+               } else if (task->num_scatter == 1) {
+                       u64 dma_addr = sg_dma_address(task->scatter);
+                       ssp_cmd.addr_low = cpu_to_le32(lower_32_bits(dma_addr));
+                       ssp_cmd.addr_high =
+                               cpu_to_le32(upper_32_bits(dma_addr));
+                       ssp_cmd.len = cpu_to_le32(task->total_xfer_len);
+                       ssp_cmd.esgl = 0;
+               } else if (task->num_scatter == 0) {
+                       ssp_cmd.addr_low = 0;
+                       ssp_cmd.addr_high = 0;
+                       ssp_cmd.len = cpu_to_le32(task->total_xfer_len);
+                       ssp_cmd.esgl = 0;
+               }
+       }
+       ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &ssp_cmd, outb++);
+
+       /* rotate the outb queue */
+       outb = outb%PM8001_MAX_SPCV_OUTB_NUM;
+
+       return ret;
+}
+
+static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
+       struct pm8001_ccb_info *ccb)
+{
+       struct sas_task *task = ccb->task;
+       struct domain_device *dev = task->dev;
+       struct pm8001_device *pm8001_ha_dev = dev->lldd_dev;
+       u32 tag = ccb->ccb_tag;
+       int ret;
+       static u32 inb;
+       static u32 outb;
+       struct sata_start_req sata_cmd;
+       u32 hdr_tag, ncg_tag = 0;
+       u64 phys_addr;
+       u32 ATAP = 0x0;
+       u32 dir;
+       struct inbound_queue_table *circularQ;
+       unsigned long flags;
+       u32 opc = OPC_INB_SATA_HOST_OPSTART;
+       memset(&sata_cmd, 0, sizeof(sata_cmd));
+       circularQ = &pm8001_ha->inbnd_q_tbl[0];
+
+       if (task->data_dir == PCI_DMA_NONE) {
+               ATAP = 0x04; /* no data*/
+               PM8001_IO_DBG(pm8001_ha, pm8001_printk("no data\n"));
+       } else if (likely(!task->ata_task.device_control_reg_update)) {
+               if (task->ata_task.dma_xfer) {
+                       ATAP = 0x06; /* DMA */
+                       PM8001_IO_DBG(pm8001_ha, pm8001_printk("DMA\n"));
+               } else {
+                       ATAP = 0x05; /* PIO*/
+                       PM8001_IO_DBG(pm8001_ha, pm8001_printk("PIO\n"));
+               }
+               if (task->ata_task.use_ncq &&
+                       dev->sata_dev.command_set != ATAPI_COMMAND_SET) {
+                       ATAP = 0x07; /* FPDMA */
+                       PM8001_IO_DBG(pm8001_ha, pm8001_printk("FPDMA\n"));
+               }
+       }
+       if (task->ata_task.use_ncq && pm8001_get_ncq_tag(task, &hdr_tag)) {
+               task->ata_task.fis.sector_count |= (u8) (hdr_tag << 3);
+               ncg_tag = hdr_tag;
+       }
+       dir = data_dir_flags[task->data_dir] << 8;
+       sata_cmd.tag = cpu_to_le32(tag);
+       sata_cmd.device_id = cpu_to_le32(pm8001_ha_dev->device_id);
+       sata_cmd.data_len = cpu_to_le32(task->total_xfer_len);
+
+       sata_cmd.sata_fis = task->ata_task.fis;
+       if (likely(!task->ata_task.device_control_reg_update))
+               sata_cmd.sata_fis.flags |= 0x80;/* C=1: update ATA cmd reg */
+       sata_cmd.sata_fis.flags &= 0xF0;/* PM_PORT field shall be 0 */
+
+       /* Check if encryption is set */
+       if (pm8001_ha->chip->encrypt &&
+               !(pm8001_ha->encrypt_info.status) && check_enc_sat_cmd(task)) {
+               PM8001_IO_DBG(pm8001_ha, pm8001_printk(
+                       "Encryption enabled.Sending Encrypt SATA cmd 0x%x\n",
+                       sata_cmd.sata_fis.command));
+               opc = OPC_INB_SATA_DIF_ENC_IO;
+
+               /* set encryption bit */
+               sata_cmd.ncqtag_atap_dir_m_dad =
+                       cpu_to_le32(((ncg_tag & 0xff)<<16)|
+                               ((ATAP & 0x3f) << 10) | 0x20 | dir);
+                                                       /* dad (bit 0-1) is 0 */
+               /* fill in PRD (scatter/gather) table, if any */
+               if (task->num_scatter > 1) {
+                       pm8001_chip_make_sg(task->scatter,
+                                               ccb->n_elem, ccb->buf_prd);
+                       phys_addr = ccb->ccb_dma_handle +
+                               offsetof(struct pm8001_ccb_info, buf_prd[0]);
+                       sata_cmd.enc_addr_low = lower_32_bits(phys_addr);
+                       sata_cmd.enc_addr_high = upper_32_bits(phys_addr);
+                       sata_cmd.enc_esgl = cpu_to_le32(1 << 31);
+               } else if (task->num_scatter == 1) {
+                       u64 dma_addr = sg_dma_address(task->scatter);
+                       sata_cmd.enc_addr_low = lower_32_bits(dma_addr);
+                       sata_cmd.enc_addr_high = upper_32_bits(dma_addr);
+                       sata_cmd.enc_len = cpu_to_le32(task->total_xfer_len);
+                       sata_cmd.enc_esgl = 0;
+               } else if (task->num_scatter == 0) {
+                       sata_cmd.enc_addr_low = 0;
+                       sata_cmd.enc_addr_high = 0;
+                       sata_cmd.enc_len = cpu_to_le32(task->total_xfer_len);
+                       sata_cmd.enc_esgl = 0;
+               }
+               /* XTS mode. All other fields are 0 */
+               sata_cmd.key_index_mode = 0x6 << 4;
+               /* set tweak values. Should be the start lba */
+               sata_cmd.twk_val0 =
+                       cpu_to_le32((sata_cmd.sata_fis.lbal_exp << 24) |
+                                       (sata_cmd.sata_fis.lbah << 16) |
+                                       (sata_cmd.sata_fis.lbam << 8) |
+                                       (sata_cmd.sata_fis.lbal));
+               sata_cmd.twk_val1 =
+                       cpu_to_le32((sata_cmd.sata_fis.lbah_exp << 8) |
+                                        (sata_cmd.sata_fis.lbam_exp));
+       } else {
+               PM8001_IO_DBG(pm8001_ha, pm8001_printk(
+                       "Sending Normal SATA command 0x%x inb %x\n",
+                       sata_cmd.sata_fis.command, inb));
+               /* dad (bit 0-1) is 0 */
+               sata_cmd.ncqtag_atap_dir_m_dad =
+                       cpu_to_le32(((ncg_tag & 0xff)<<16) |
+                                       ((ATAP & 0x3f) << 10) | dir);
+
+               /* fill in PRD (scatter/gather) table, if any */
+               if (task->num_scatter > 1) {
+                       pm8001_chip_make_sg(task->scatter,
+                                       ccb->n_elem, ccb->buf_prd);
+                       phys_addr = ccb->ccb_dma_handle +
+                               offsetof(struct pm8001_ccb_info, buf_prd[0]);
+                       sata_cmd.addr_low = lower_32_bits(phys_addr);
+                       sata_cmd.addr_high = upper_32_bits(phys_addr);
+                       sata_cmd.esgl = cpu_to_le32(1 << 31);
+               } else if (task->num_scatter == 1) {
+                       u64 dma_addr = sg_dma_address(task->scatter);
+                       sata_cmd.addr_low = lower_32_bits(dma_addr);
+                       sata_cmd.addr_high = upper_32_bits(dma_addr);
+                       sata_cmd.len = cpu_to_le32(task->total_xfer_len);
+                       sata_cmd.esgl = 0;
+               } else if (task->num_scatter == 0) {
+                       sata_cmd.addr_low = 0;
+                       sata_cmd.addr_high = 0;
+                       sata_cmd.len = cpu_to_le32(task->total_xfer_len);
+                       sata_cmd.esgl = 0;
+               }
+                       /* scsi cdb */
+                       sata_cmd.atapi_scsi_cdb[0] =
+                               cpu_to_le32(((task->ata_task.atapi_packet[0]) |
+                               (task->ata_task.atapi_packet[1] << 8) |
+                               (task->ata_task.atapi_packet[2] << 16) |
+                               (task->ata_task.atapi_packet[3] << 24)));
+                       sata_cmd.atapi_scsi_cdb[1] =
+                               cpu_to_le32(((task->ata_task.atapi_packet[4]) |
+                               (task->ata_task.atapi_packet[5] << 8) |
+                               (task->ata_task.atapi_packet[6] << 16) |
+                               (task->ata_task.atapi_packet[7] << 24)));
+                       sata_cmd.atapi_scsi_cdb[2] =
+                               cpu_to_le32(((task->ata_task.atapi_packet[8]) |
+                               (task->ata_task.atapi_packet[9] << 8) |
+                               (task->ata_task.atapi_packet[10] << 16) |
+                               (task->ata_task.atapi_packet[11] << 24)));
+                       sata_cmd.atapi_scsi_cdb[3] =
+                               cpu_to_le32(((task->ata_task.atapi_packet[12]) |
+                               (task->ata_task.atapi_packet[13] << 8) |
+                               (task->ata_task.atapi_packet[14] << 16) |
+                               (task->ata_task.atapi_packet[15] << 24)));
+       }
+
+       /* Check for read log for failed drive and return */
+       if (sata_cmd.sata_fis.command == 0x2f) {
+               if (pm8001_ha_dev && ((pm8001_ha_dev->id & NCQ_READ_LOG_FLAG) ||
+                       (pm8001_ha_dev->id & NCQ_ABORT_ALL_FLAG) ||
+                       (pm8001_ha_dev->id & NCQ_2ND_RLE_FLAG))) {
+                       struct task_status_struct *ts;
+
+                       pm8001_ha_dev->id &= 0xDFFFFFFF;
+                       ts = &task->task_status;
+
+                       spin_lock_irqsave(&task->task_state_lock, flags);
+                       ts->resp = SAS_TASK_COMPLETE;
+                       ts->stat = SAM_STAT_GOOD;
+                       task->task_state_flags &= ~SAS_TASK_STATE_PENDING;
+                       task->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
+                       task->task_state_flags |= SAS_TASK_STATE_DONE;
+                       if (unlikely((task->task_state_flags &
+                                       SAS_TASK_STATE_ABORTED))) {
+                               spin_unlock_irqrestore(&task->task_state_lock,
+                                                       flags);
+                               PM8001_FAIL_DBG(pm8001_ha,
+                                       pm8001_printk("task 0x%p resp 0x%x "
+                                       " stat 0x%x but aborted by upper layer "
+                                       "\n", task, ts->resp, ts->stat));
+                               pm8001_ccb_task_free(pm8001_ha, task, ccb, tag);
+                               return 0;
+                       } else if (task->uldd_task) {
+                               spin_unlock_irqrestore(&task->task_state_lock,
+                                                       flags);
+                               pm8001_ccb_task_free(pm8001_ha, task, ccb, tag);
+                               mb();/* ditto */
+                               spin_unlock_irq(&pm8001_ha->lock);
+                               task->task_done(task);
+                               spin_lock_irq(&pm8001_ha->lock);
+                               return 0;
+                       } else if (!task->uldd_task) {
+                               spin_unlock_irqrestore(&task->task_state_lock,
+                                                       flags);
+                               pm8001_ccb_task_free(pm8001_ha, task, ccb, tag);
+                               mb();/*ditto*/
+                               spin_unlock_irq(&pm8001_ha->lock);
+                               task->task_done(task);
+                               spin_lock_irq(&pm8001_ha->lock);
+                               return 0;
+                       }
+               }
+       }
+
+       ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc,
+                                               &sata_cmd, outb++);
+
+       /* rotate the outb queue */
+       outb = outb%PM8001_MAX_SPCV_OUTB_NUM;
+       return ret;
+}
+
+/**
+ * pm80xx_chip_phy_start_req - start phy via PHY_START COMMAND
+ * @pm8001_ha: our hba card information.
+ * @num: the inbound queue number
+ * @phy_id: the phy id which we wanted to start up.
+ */
+static int
+pm80xx_chip_phy_start_req(struct pm8001_hba_info *pm8001_ha, u8 phy_id)
+{
+       struct phy_start_req payload;
+       struct inbound_queue_table *circularQ;
+       int ret;
+       u32 tag = 0x01;
+       u32 opcode = OPC_INB_PHYSTART;
+       circularQ = &pm8001_ha->inbnd_q_tbl[0];
+       memset(&payload, 0, sizeof(payload));
+       payload.tag = cpu_to_le32(tag);
+
+       PM8001_INIT_DBG(pm8001_ha,
+               pm8001_printk("PHY START REQ for phy_id %d\n", phy_id));
+       /*
+        ** [0:7]       PHY Identifier
+        ** [8:11]      link rate 1.5G, 3G, 6G
+        ** [12:13] link mode 01b SAS mode; 10b SATA mode; 11b Auto mode
+        ** [14]        0b disable spin up hold; 1b enable spin up hold
+        ** [15] ob no change in current PHY analig setup 1b enable using SPAST
+        */
+       payload.ase_sh_lm_slr_phyid = cpu_to_le32(SPINHOLD_DISABLE |
+                       LINKMODE_AUTO | LINKRATE_15 |
+                       LINKRATE_30 | LINKRATE_60 | phy_id);
+       /* SSC Disable and SAS Analog ST configuration */
+       /**
+       payload.ase_sh_lm_slr_phyid =
+               cpu_to_le32(SSC_DISABLE_30 | SAS_ASE | SPINHOLD_DISABLE |
+               LINKMODE_AUTO | LINKRATE_15 | LINKRATE_30 | LINKRATE_60 |
+               phy_id);
+       Have to add "SAS PHY Analog Setup SPASTI 1 Byte" Based on need
+       **/
+
+       payload.sas_identify.dev_type = SAS_END_DEVICE;
+       payload.sas_identify.initiator_bits = SAS_PROTOCOL_ALL;
+       memcpy(payload.sas_identify.sas_addr,
+               pm8001_ha->sas_addr, SAS_ADDR_SIZE);
+       payload.sas_identify.phy_id = phy_id;
+       ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload, 0);
+       return ret;
+}
+
+/**
+ * pm8001_chip_phy_stop_req - start phy via PHY_STOP COMMAND
+ * @pm8001_ha: our hba card information.
+ * @num: the inbound queue number
+ * @phy_id: the phy id which we wanted to start up.
+ */
+static int pm80xx_chip_phy_stop_req(struct pm8001_hba_info *pm8001_ha,
+       u8 phy_id)
+{
+       struct phy_stop_req payload;
+       struct inbound_queue_table *circularQ;
+       int ret;
+       u32 tag = 0x01;
+       u32 opcode = OPC_INB_PHYSTOP;
+       circularQ = &pm8001_ha->inbnd_q_tbl[0];
+       memset(&payload, 0, sizeof(payload));
+       payload.tag = cpu_to_le32(tag);
+       payload.phy_id = cpu_to_le32(phy_id);
+       ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload, 0);
+       return ret;
+}
+
+/**
+ * see comments on pm8001_mpi_reg_resp.
+ */
+static int pm80xx_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha,
+       struct pm8001_device *pm8001_dev, u32 flag)
+{
+       struct reg_dev_req payload;
+       u32     opc;
+       u32 stp_sspsmp_sata = 0x4;
+       struct inbound_queue_table *circularQ;
+       u32 linkrate, phy_id;
+       int rc, tag = 0xdeadbeef;
+       struct pm8001_ccb_info *ccb;
+       u8 retryFlag = 0x1;
+       u16 firstBurstSize = 0;
+       u16 ITNT = 2000;
+       struct domain_device *dev = pm8001_dev->sas_device;
+       struct domain_device *parent_dev = dev->parent;
+       circularQ = &pm8001_ha->inbnd_q_tbl[0];
+
+       memset(&payload, 0, sizeof(payload));
+       rc = pm8001_tag_alloc(pm8001_ha, &tag);
+       if (rc)
+               return rc;
+       ccb = &pm8001_ha->ccb_info[tag];
+       ccb->device = pm8001_dev;
+       ccb->ccb_tag = tag;
+       payload.tag = cpu_to_le32(tag);
+
+       if (flag == 1) {
+               stp_sspsmp_sata = 0x02; /*direct attached sata */
+       } else {
+               if (pm8001_dev->dev_type == SAS_SATA_DEV)
+                       stp_sspsmp_sata = 0x00; /* stp*/
+               else if (pm8001_dev->dev_type == SAS_END_DEVICE ||
+                       pm8001_dev->dev_type == SAS_EDGE_EXPANDER_DEVICE ||
+                       pm8001_dev->dev_type == SAS_FANOUT_EXPANDER_DEVICE)
+                       stp_sspsmp_sata = 0x01; /*ssp or smp*/
+       }
+       if (parent_dev && DEV_IS_EXPANDER(parent_dev->dev_type))
+               phy_id = parent_dev->ex_dev.ex_phy->phy_id;
+       else
+               phy_id = pm8001_dev->attached_phy;
+
+       opc = OPC_INB_REG_DEV;
+
+       linkrate = (pm8001_dev->sas_device->linkrate < dev->port->linkrate) ?
+                       pm8001_dev->sas_device->linkrate : dev->port->linkrate;
+
+       payload.phyid_portid =
+               cpu_to_le32(((pm8001_dev->sas_device->port->id) & 0xFF) |
+               ((phy_id & 0xFF) << 8));
+
+       payload.dtype_dlr_mcn_ir_retry = cpu_to_le32((retryFlag & 0x01) |
+               ((linkrate & 0x0F) << 24) |
+               ((stp_sspsmp_sata & 0x03) << 28));
+       payload.firstburstsize_ITNexustimeout =
+               cpu_to_le32(ITNT | (firstBurstSize * 0x10000));
+
+       memcpy(payload.sas_addr, pm8001_dev->sas_device->sas_addr,
+               SAS_ADDR_SIZE);
+
+       rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+
+       return rc;
+}
+
+/**
+ * pm80xx_chip_phy_ctl_req - support the local phy operation
+ * @pm8001_ha: our hba card information.
+ * @num: the inbound queue number
+ * @phy_id: the phy id which we wanted to operate
+ * @phy_op:
+ */
+static int pm80xx_chip_phy_ctl_req(struct pm8001_hba_info *pm8001_ha,
+       u32 phyId, u32 phy_op)
+{
+       struct local_phy_ctl_req payload;
+       struct inbound_queue_table *circularQ;
+       int ret;
+       u32 opc = OPC_INB_LOCAL_PHY_CONTROL;
+       memset(&payload, 0, sizeof(payload));
+       circularQ = &pm8001_ha->inbnd_q_tbl[0];
+       payload.tag = cpu_to_le32(1);
+       payload.phyop_phyid =
+               cpu_to_le32(((phy_op & 0xFF) << 8) | (phyId & 0xFF));
+       ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+       return ret;
+}
+
+static u32 pm80xx_chip_is_our_interupt(struct pm8001_hba_info *pm8001_ha)
+{
+       u32 value;
+#ifdef PM8001_USE_MSIX
+       return 1;
+#endif
+       value = pm8001_cr32(pm8001_ha, 0, MSGU_ODR);
+       if (value)
+               return 1;
+       return 0;
+
+}
+
+/**
+ * pm8001_chip_isr - PM8001 isr handler.
+ * @pm8001_ha: our hba card information.
+ * @irq: irq number.
+ * @stat: stat.
+ */
+static irqreturn_t
+pm80xx_chip_isr(struct pm8001_hba_info *pm8001_ha, u8 vec)
+{
+       pm80xx_chip_interrupt_disable(pm8001_ha, vec);
+       process_oq(pm8001_ha, vec);
+       pm80xx_chip_interrupt_enable(pm8001_ha, vec);
+       return IRQ_HANDLED;
+}
+
+const struct pm8001_dispatch pm8001_80xx_dispatch = {
+       .name                   = "pmc80xx",
+       .chip_init              = pm80xx_chip_init,
+       .chip_soft_rst          = pm80xx_chip_soft_rst,
+       .chip_rst               = pm80xx_hw_chip_rst,
+       .chip_iounmap           = pm8001_chip_iounmap,
+       .isr                    = pm80xx_chip_isr,
+       .is_our_interupt        = pm80xx_chip_is_our_interupt,
+       .isr_process_oq         = process_oq,
+       .interrupt_enable       = pm80xx_chip_interrupt_enable,
+       .interrupt_disable      = pm80xx_chip_interrupt_disable,
+       .make_prd               = pm8001_chip_make_sg,
+       .smp_req                = pm80xx_chip_smp_req,
+       .ssp_io_req             = pm80xx_chip_ssp_io_req,
+       .sata_req               = pm80xx_chip_sata_req,
+       .phy_start_req          = pm80xx_chip_phy_start_req,
+       .phy_stop_req           = pm80xx_chip_phy_stop_req,
+       .reg_dev_req            = pm80xx_chip_reg_dev_req,
+       .dereg_dev_req          = pm8001_chip_dereg_dev_req,
+       .phy_ctl_req            = pm80xx_chip_phy_ctl_req,
+       .task_abort             = pm8001_chip_abort_task,
+       .ssp_tm_req             = pm8001_chip_ssp_tm_req,
+       .get_nvmd_req           = pm8001_chip_get_nvmd_req,
+       .set_nvmd_req           = pm8001_chip_set_nvmd_req,
+       .fw_flash_update_req    = pm8001_chip_fw_flash_update_req,
+       .set_dev_state_req      = pm8001_chip_set_dev_state_req,
+};
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.h b/drivers/scsi/pm8001/pm80xx_hwi.h
new file mode 100644 (file)
index 0000000..2b760ba
--- /dev/null
@@ -0,0 +1,1523 @@
+/*
+ * PMC-Sierra SPCv/ve 8088/8089 SAS/SATA based host adapters driver
+ *
+ * Copyright (c) 2008-2009 USI Co., Ltd.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions, and the following disclaimer,
+ *     without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *     substantially similar to the "NO WARRANTY" disclaimer below
+ *     ("Disclaimer") and any redistribution must be conditioned upon
+ *     including a substantially similar Disclaimer requirement for further
+ *     binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ *     of any contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ *
+ */
+
+#ifndef _PMC8001_REG_H_
+#define _PMC8001_REG_H_
+
+#include <linux/types.h>
+#include <scsi/libsas.h>
+
+/* for Request Opcode of IOMB */
+#define OPC_INB_ECHO                           1       /* 0x000 */
+#define OPC_INB_PHYSTART                       4       /* 0x004 */
+#define OPC_INB_PHYSTOP                                5       /* 0x005 */
+#define OPC_INB_SSPINIIOSTART                  6       /* 0x006 */
+#define OPC_INB_SSPINITMSTART                  7       /* 0x007 */
+/* 0x8 RESV IN SPCv */
+#define OPC_INB_RSVD                           8       /* 0x008 */
+#define OPC_INB_DEV_HANDLE_ACCEPT              9       /* 0x009 */
+#define OPC_INB_SSPTGTIOSTART                  10      /* 0x00A */
+#define OPC_INB_SSPTGTRSPSTART                 11      /* 0x00B */
+/* 0xC, 0xD, 0xE removed in SPCv */
+#define OPC_INB_SSP_ABORT                      15      /* 0x00F */
+#define OPC_INB_DEREG_DEV_HANDLE               16      /* 0x010 */
+#define OPC_INB_GET_DEV_HANDLE                 17      /* 0x011 */
+#define OPC_INB_SMP_REQUEST                    18      /* 0x012 */
+/* 0x13 SMP_RESPONSE is removed in SPCv */
+#define OPC_INB_SMP_ABORT                      20      /* 0x014 */
+/* 0x16 RESV IN SPCv */
+#define OPC_INB_RSVD1                          22      /* 0x016 */
+#define OPC_INB_SATA_HOST_OPSTART              23      /* 0x017 */
+#define OPC_INB_SATA_ABORT                     24      /* 0x018 */
+#define OPC_INB_LOCAL_PHY_CONTROL              25      /* 0x019 */
+/* 0x1A RESV IN SPCv */
+#define OPC_INB_RSVD2                          26      /* 0x01A */
+#define OPC_INB_FW_FLASH_UPDATE                        32      /* 0x020 */
+#define OPC_INB_GPIO                           34      /* 0x022 */
+#define OPC_INB_SAS_DIAG_MODE_START_END                35      /* 0x023 */
+#define OPC_INB_SAS_DIAG_EXECUTE               36      /* 0x024 */
+/* 0x25 RESV IN SPCv */
+#define OPC_INB_RSVD3                          37      /* 0x025 */
+#define OPC_INB_GET_TIME_STAMP                 38      /* 0x026 */
+#define OPC_INB_PORT_CONTROL                   39      /* 0x027 */
+#define OPC_INB_GET_NVMD_DATA                  40      /* 0x028 */
+#define OPC_INB_SET_NVMD_DATA                  41      /* 0x029 */
+#define OPC_INB_SET_DEVICE_STATE               42      /* 0x02A */
+#define OPC_INB_GET_DEVICE_STATE               43      /* 0x02B */
+#define OPC_INB_SET_DEV_INFO                   44      /* 0x02C */
+/* 0x2D RESV IN SPCv */
+#define OPC_INB_RSVD4                          45      /* 0x02D */
+#define OPC_INB_SGPIO_REGISTER                 46      /* 0x02E */
+#define OPC_INB_PCIE_DIAG_EXEC                 47      /* 0x02F */
+#define OPC_INB_SET_CONTROLLER_CONFIG          48      /* 0x030 */
+#define OPC_INB_GET_CONTROLLER_CONFIG          49      /* 0x031 */
+#define OPC_INB_REG_DEV                                50      /* 0x032 */
+#define OPC_INB_SAS_HW_EVENT_ACK               51      /* 0x033 */
+#define OPC_INB_GET_DEVICE_INFO                        52      /* 0x034 */
+#define OPC_INB_GET_PHY_PROFILE                        53      /* 0x035 */
+#define OPC_INB_FLASH_OP_EXT                   54      /* 0x036 */
+#define OPC_INB_SET_PHY_PROFILE                        55      /* 0x037 */
+#define OPC_INB_KEK_MANAGEMENT                 256     /* 0x100 */
+#define OPC_INB_DEK_MANAGEMENT                 257     /* 0x101 */
+#define OPC_INB_SSP_INI_DIF_ENC_IO             258     /* 0x102 */
+#define OPC_INB_SATA_DIF_ENC_IO                        259     /* 0x103 */
+
+/* for Response Opcode of IOMB */
+#define OPC_OUB_ECHO                                   1       /* 0x001 */
+#define OPC_OUB_RSVD                                   4       /* 0x004 */
+#define OPC_OUB_SSP_COMP                               5       /* 0x005 */
+#define OPC_OUB_SMP_COMP                               6       /* 0x006 */
+#define OPC_OUB_LOCAL_PHY_CNTRL                                7       /* 0x007 */
+#define OPC_OUB_RSVD1                                  10      /* 0x00A */
+#define OPC_OUB_DEREG_DEV                              11      /* 0x00B */
+#define OPC_OUB_GET_DEV_HANDLE                         12      /* 0x00C */
+#define OPC_OUB_SATA_COMP                              13      /* 0x00D */
+#define OPC_OUB_SATA_EVENT                             14      /* 0x00E */
+#define OPC_OUB_SSP_EVENT                              15      /* 0x00F */
+#define OPC_OUB_RSVD2                                  16      /* 0x010 */
+/* 0x11 - SMP_RECEIVED Notification removed in SPCv*/
+#define OPC_OUB_SSP_RECV_EVENT                         18      /* 0x012 */
+#define OPC_OUB_RSVD3                                  19      /* 0x013 */
+#define OPC_OUB_FW_FLASH_UPDATE                                20      /* 0x014 */
+#define OPC_OUB_GPIO_RESPONSE                          22      /* 0x016 */
+#define OPC_OUB_GPIO_EVENT                             23      /* 0x017 */
+#define OPC_OUB_GENERAL_EVENT                          24      /* 0x018 */
+#define OPC_OUB_SSP_ABORT_RSP                          26      /* 0x01A */
+#define OPC_OUB_SATA_ABORT_RSP                         27      /* 0x01B */
+#define OPC_OUB_SAS_DIAG_MODE_START_END                        28      /* 0x01C */
+#define OPC_OUB_SAS_DIAG_EXECUTE                       29      /* 0x01D */
+#define OPC_OUB_GET_TIME_STAMP                         30      /* 0x01E */
+#define OPC_OUB_RSVD4                                  31      /* 0x01F */
+#define OPC_OUB_PORT_CONTROL                           32      /* 0x020 */
+#define OPC_OUB_SKIP_ENTRY                             33      /* 0x021 */
+#define OPC_OUB_SMP_ABORT_RSP                          34      /* 0x022 */
+#define OPC_OUB_GET_NVMD_DATA                          35      /* 0x023 */
+#define OPC_OUB_SET_NVMD_DATA                          36      /* 0x024 */
+#define OPC_OUB_DEVICE_HANDLE_REMOVAL                  37      /* 0x025 */
+#define OPC_OUB_SET_DEVICE_STATE                       38      /* 0x026 */
+#define OPC_OUB_GET_DEVICE_STATE                       39      /* 0x027 */
+#define OPC_OUB_SET_DEV_INFO                           40      /* 0x028 */
+#define OPC_OUB_RSVD5                                  41      /* 0x029 */
+#define OPC_OUB_HW_EVENT                               1792    /* 0x700 */
+#define OPC_OUB_DEV_HANDLE_ARRIV                       1824    /* 0x720 */
+#define OPC_OUB_THERM_HW_EVENT                         1840    /* 0x730 */
+#define OPC_OUB_SGPIO_RESP                             2094    /* 0x82E */
+#define OPC_OUB_PCIE_DIAG_EXECUTE                      2095    /* 0x82F */
+#define OPC_OUB_DEV_REGIST                             2098    /* 0x832 */
+#define OPC_OUB_SAS_HW_EVENT_ACK                       2099    /* 0x833 */
+#define OPC_OUB_GET_DEVICE_INFO                                2100    /* 0x834 */
+/* spcv specific commands */
+#define OPC_OUB_PHY_START_RESP                         2052    /* 0x804 */
+#define OPC_OUB_PHY_STOP_RESP                          2053    /* 0x805 */
+#define OPC_OUB_SET_CONTROLLER_CONFIG                  2096    /* 0x830 */
+#define OPC_OUB_GET_CONTROLLER_CONFIG                  2097    /* 0x831 */
+#define OPC_OUB_GET_PHY_PROFILE                                2101    /* 0x835 */
+#define OPC_OUB_FLASH_OP_EXT                           2102    /* 0x836 */
+#define OPC_OUB_SET_PHY_PROFILE                                2103    /* 0x837 */
+#define OPC_OUB_KEK_MANAGEMENT_RESP                    2304    /* 0x900 */
+#define OPC_OUB_DEK_MANAGEMENT_RESP                    2305    /* 0x901 */
+#define OPC_OUB_SSP_COALESCED_COMP_RESP                        2306    /* 0x902 */
+
+/* for phy start*/
+#define SSC_DISABLE_15                 (0x01 << 16)
+#define SSC_DISABLE_30                 (0x02 << 16)
+#define SSC_DISABLE_60                 (0x04 << 16)
+#define SAS_ASE                                (0x01 << 15)
+#define SPINHOLD_DISABLE               (0x00 << 14)
+#define SPINHOLD_ENABLE                        (0x01 << 14)
+#define LINKMODE_SAS                   (0x01 << 12)
+#define LINKMODE_DSATA                 (0x02 << 12)
+#define LINKMODE_AUTO                  (0x03 << 12)
+#define LINKRATE_15                    (0x01 << 8)
+#define LINKRATE_30                    (0x02 << 8)
+#define LINKRATE_60                    (0x06 << 8)
+
+/* Thermal related */
+#define        THERMAL_ENABLE                  0x1
+#define        THERMAL_LOG_ENABLE              0x1
+#define THERMAL_OP_CODE                        0x6
+#define LTEMPHIL                        70
+#define RTEMPHIL                       100
+
+/* Encryption info */
+#define SCRATCH_PAD3_ENC_DISABLED      0x00000000
+#define SCRATCH_PAD3_ENC_DIS_ERR       0x00000001
+#define SCRATCH_PAD3_ENC_ENA_ERR       0x00000002
+#define SCRATCH_PAD3_ENC_READY         0x00000003
+#define SCRATCH_PAD3_ENC_MASK          SCRATCH_PAD3_ENC_READY
+
+#define SCRATCH_PAD3_XTS_ENABLED               (1 << 14)
+#define SCRATCH_PAD3_SMA_ENABLED               (1 << 4)
+#define SCRATCH_PAD3_SMB_ENABLED               (1 << 5)
+#define SCRATCH_PAD3_SMF_ENABLED               0
+#define SCRATCH_PAD3_SM_MASK                   0x000000F0
+#define SCRATCH_PAD3_ERR_CODE                  0x00FF0000
+
+#define SEC_MODE_SMF                           0x0
+#define SEC_MODE_SMA                           0x100
+#define SEC_MODE_SMB                           0x200
+#define CIPHER_MODE_ECB                                0x00000001
+#define CIPHER_MODE_XTS                                0x00000002
+#define KEK_MGMT_SUBOP_KEYCARDUPDATE           0x4
+
+/* SAS protocol timer configuration page */
+#define SAS_PROTOCOL_TIMER_CONFIG_PAGE  0x04
+#define STP_MCT_TMO                     32
+#define SSP_MCT_TMO                     32
+#define SAS_MAX_OPEN_TIME                              5
+#define SMP_MAX_CONN_TIMER              0xFF
+#define STP_FRM_TIMER                   0
+#define STP_IDLE_TIME                   5 /* 5 us; controller default */
+#define SAS_MFD                         0
+#define SAS_OPNRJT_RTRY_INTVL           2
+#define SAS_DOPNRJT_RTRY_TMO            128
+#define SAS_COPNRJT_RTRY_TMO            128
+
+/*
+  Making ORR bigger than IT NEXUS LOSS which is 2000000us = 2 second.
+  Assuming a bigger value 3 second, 3000000/128 = 23437.5 where 128
+  is DOPNRJT_RTRY_TMO
+*/
+#define SAS_DOPNRJT_RTRY_THR            23438
+#define SAS_COPNRJT_RTRY_THR            23438
+#define SAS_MAX_AIP                     0x200000
+#define IT_NEXUS_TIMEOUT       0x7D0
+#define PORT_RECOVERY_TIMEOUT  ((IT_NEXUS_TIMEOUT/100) + 30)
+
+struct mpi_msg_hdr {
+       __le32  header; /* Bits [11:0] - Message operation code */
+       /* Bits [15:12] - Message Category */
+       /* Bits [21:16] - Outboundqueue ID for the
+       operation completion message */
+       /* Bits [23:22] - Reserved */
+       /* Bits [28:24] - Buffer Count, indicates how
+       many buffer are allocated for the massage */
+       /* Bits [30:29] - Reserved */
+       /* Bits [31] - Message Valid bit */
+} __attribute__((packed, aligned(4)));
+
+/*
+ * brief the data structure of PHY Start Command
+ * use to describe enable the phy (128 bytes)
+ */
+struct phy_start_req {
+       __le32  tag;
+       __le32  ase_sh_lm_slr_phyid;
+       struct sas_identify_frame sas_identify; /* 28 Bytes */
+       __le32 spasti;
+       u32     reserved[21];
+} __attribute__((packed, aligned(4)));
+
+/*
+ * brief the data structure of PHY Start Command
+ * use to disable the phy (128 bytes)
+ */
+struct phy_stop_req {
+       __le32  tag;
+       __le32  phy_id;
+       u32     reserved[29];
+} __attribute__((packed, aligned(4)));
+
+/* set device bits fis - device to host */
+struct set_dev_bits_fis {
+       u8      fis_type;       /* 0xA1*/
+       u8      n_i_pmport;
+       /* b7 : n Bit. Notification bit. If set device needs attention. */
+       /* b6 : i Bit. Interrupt Bit */
+       /* b5-b4: reserved2 */
+       /* b3-b0: PM Port */
+       u8      status;
+       u8      error;
+       u32     _r_a;
+} __attribute__ ((packed));
+/* PIO setup FIS - device to host */
+struct pio_setup_fis {
+       u8      fis_type;       /* 0x5f */
+       u8      i_d_pmPort;
+       /* b7 : reserved */
+       /* b6 : i bit. Interrupt bit */
+       /* b5 : d bit. data transfer direction. set to 1 for device to host
+       xfer */
+       /* b4 : reserved */
+       /* b3-b0: PM Port */
+       u8      status;
+       u8      error;
+       u8      lbal;
+       u8      lbam;
+       u8      lbah;
+       u8      device;
+       u8      lbal_exp;
+       u8      lbam_exp;
+       u8      lbah_exp;
+       u8      _r_a;
+       u8      sector_count;
+       u8      sector_count_exp;
+       u8      _r_b;
+       u8      e_status;
+       u8      _r_c[2];
+       u8      transfer_count;
+} __attribute__ ((packed));
+
+/*
+ * brief the data structure of SATA Completion Response
+ * use to describe the sata task response (64 bytes)
+ */
+struct sata_completion_resp {
+       __le32  tag;
+       __le32  status;
+       __le32  param;
+       u32     sata_resp[12];
+} __attribute__((packed, aligned(4)));
+
+/*
+ * brief the data structure of SAS HW Event Notification
+ * use to alert the host about the hardware event(64 bytes)
+ */
+/* updated outbound struct for spcv */
+
+struct hw_event_resp {
+       __le32  lr_status_evt_portid;
+       __le32  evt_param;
+       __le32  phyid_npip_portstate;
+       struct sas_identify_frame       sas_identify;
+       struct dev_to_host_fis  sata_fis;
+} __attribute__((packed, aligned(4)));
+
+/*
+ * brief the data structure for thermal event notification
+ */
+
+struct thermal_hw_event {
+       __le32  thermal_event;
+       __le32  rht_lht;
+} __attribute__((packed, aligned(4)));
+
+/*
+ * brief the data structure of REGISTER DEVICE Command
+ * use to describe MPI REGISTER DEVICE Command (64 bytes)
+ */
+
+struct reg_dev_req {
+       __le32  tag;
+       __le32  phyid_portid;
+       __le32  dtype_dlr_mcn_ir_retry;
+       __le32  firstburstsize_ITNexustimeout;
+       u8      sas_addr[SAS_ADDR_SIZE];
+       __le32  upper_device_id;
+       u32     reserved[24];
+} __attribute__((packed, aligned(4)));
+
+/*
+ * brief the data structure of DEREGISTER DEVICE Command
+ * use to request spc to remove all internal resources associated
+ * with the device id (64 bytes)
+ */
+
+struct dereg_dev_req {
+       __le32  tag;
+       __le32  device_id;
+       u32     reserved[29];
+} __attribute__((packed, aligned(4)));
+
+/*
+ * brief the data structure of DEVICE_REGISTRATION Response
+ * use to notify the completion of the device registration (64 bytes)
+ */
+struct dev_reg_resp {
+       __le32  tag;
+       __le32  status;
+       __le32  device_id;
+       u32     reserved[12];
+} __attribute__((packed, aligned(4)));
+
+/*
+ * brief the data structure of Local PHY Control Command
+ * use to issue PHY CONTROL to local phy (64 bytes)
+ */
+struct local_phy_ctl_req {
+       __le32  tag;
+       __le32  phyop_phyid;
+       u32     reserved1[29];
+} __attribute__((packed, aligned(4)));
+
+/**
+ * brief the data structure of Local Phy Control Response
+ * use to describe MPI Local Phy Control Response (64 bytes)
+ */
+ struct local_phy_ctl_resp {
+       __le32  tag;
+       __le32  phyop_phyid;
+       __le32  status;
+       u32     reserved[12];
+} __attribute__((packed, aligned(4)));
+
+#define OP_BITS 0x0000FF00
+#define ID_BITS 0x000000FF
+
+/*
+ * brief the data structure of PORT Control Command
+ * use to control port properties (64 bytes)
+ */
+
+struct port_ctl_req {
+       __le32  tag;
+       __le32  portop_portid;
+       __le32  param0;
+       __le32  param1;
+       u32     reserved1[27];
+} __attribute__((packed, aligned(4)));
+
+/*
+ * brief the data structure of HW Event Ack Command
+ * use to acknowledge receive HW event (64 bytes)
+ */
+struct hw_event_ack_req {
+       __le32  tag;
+       __le32  phyid_sea_portid;
+       __le32  param0;
+       __le32  param1;
+       u32     reserved1[27];
+} __attribute__((packed, aligned(4)));
+
+/*
+ * brief the data structure of PHY_START Response Command
+ * indicates the completion of PHY_START command (64 bytes)
+ */
+struct phy_start_resp {
+       __le32  tag;
+       __le32  status;
+       __le32  phyid;
+       u32     reserved[12];
+} __attribute__((packed, aligned(4)));
+
+/*
+ * brief the data structure of PHY_STOP Response Command
+ * indicates the completion of PHY_STOP command (64 bytes)
+ */
+struct phy_stop_resp {
+       __le32  tag;
+       __le32  status;
+       __le32  phyid;
+       u32     reserved[12];
+} __attribute__((packed, aligned(4)));
+
+/*
+ * brief the data structure of SSP Completion Response
+ * use to indicate a SSP Completion (n bytes)
+ */
+struct ssp_completion_resp {
+       __le32  tag;
+       __le32  status;
+       __le32  param;
+       __le32  ssptag_rescv_rescpad;
+       struct ssp_response_iu ssp_resp_iu;
+       __le32  residual_count;
+} __attribute__((packed, aligned(4)));
+
+#define SSP_RESCV_BIT  0x00010000
+
+/*
+ * brief the data structure of SATA EVNET response
+ * use to indicate a SATA Completion (64 bytes)
+ */
+struct sata_event_resp {
+       __le32 tag;
+       __le32 event;
+       __le32 port_id;
+       __le32 device_id;
+       u32 reserved;
+       __le32 event_param0;
+       __le32 event_param1;
+       __le32 sata_addr_h32;
+       __le32 sata_addr_l32;
+       __le32 e_udt1_udt0_crc;
+       __le32 e_udt5_udt4_udt3_udt2;
+       __le32 a_udt1_udt0_crc;
+       __le32 a_udt5_udt4_udt3_udt2;
+       __le32 hwdevid_diferr;
+       __le32 err_framelen_byteoffset;
+       __le32 err_dataframe;
+} __attribute__((packed, aligned(4)));
+
+/*
+ * brief the data structure of SSP EVNET esponse
+ * use to indicate a SSP Completion (64 bytes)
+ */
+struct ssp_event_resp {
+       __le32 tag;
+       __le32 event;
+       __le32 port_id;
+       __le32 device_id;
+       __le32 ssp_tag;
+       __le32 event_param0;
+       __le32 event_param1;
+       __le32 sas_addr_h32;
+       __le32 sas_addr_l32;
+       __le32 e_udt1_udt0_crc;
+       __le32 e_udt5_udt4_udt3_udt2;
+       __le32 a_udt1_udt0_crc;
+       __le32 a_udt5_udt4_udt3_udt2;
+       __le32 hwdevid_diferr;
+       __le32 err_framelen_byteoffset;
+       __le32 err_dataframe;
+} __attribute__((packed, aligned(4)));
+
+/**
+ * brief the data structure of General Event Notification Response
+ * use to describe MPI General Event Notification Response (64 bytes)
+ */
+struct general_event_resp {
+       __le32  status;
+       __le32  inb_IOMB_payload[14];
+} __attribute__((packed, aligned(4)));
+
+#define GENERAL_EVENT_PAYLOAD  14
+#define OPCODE_BITS    0x00000fff
+
+/*
+ * brief the data structure of SMP Request Command
+ * use to describe MPI SMP REQUEST Command (64 bytes)
+ */
+struct smp_req {
+       __le32  tag;
+       __le32  device_id;
+       __le32  len_ip_ir;
+       /* Bits [0] - Indirect response */
+       /* Bits [1] - Indirect Payload */
+       /* Bits [15:2] - Reserved */
+       /* Bits [23:16] - direct payload Len */
+       /* Bits [31:24] - Reserved */
+       u8      smp_req16[16];
+       union {
+               u8      smp_req[32];
+               struct {
+                       __le64 long_req_addr;/* sg dma address, LE */
+                       __le32 long_req_size;/* LE */
+                       u32     _r_a;
+                       __le64 long_resp_addr;/* sg dma address, LE */
+                       __le32 long_resp_size;/* LE */
+                       u32     _r_b;
+                       } long_smp_req;/* sequencer extension */
+       };
+       __le32  rsvd[16];
+} __attribute__((packed, aligned(4)));
+/*
+ * brief the data structure of SMP Completion Response
+ * use to describe MPI SMP Completion Response (64 bytes)
+ */
+struct smp_completion_resp {
+       __le32  tag;
+       __le32  status;
+       __le32  param;
+       u8      _r_a[252];
+} __attribute__((packed, aligned(4)));
+
+/*
+ *brief the data structure of SSP SMP SATA Abort Command
+ * use to describe MPI SSP SMP & SATA Abort Command (64 bytes)
+ */
+struct task_abort_req {
+       __le32  tag;
+       __le32  device_id;
+       __le32  tag_to_abort;
+       __le32  abort_all;
+       u32     reserved[27];
+} __attribute__((packed, aligned(4)));
+
+/* These flags used for SSP SMP & SATA Abort */
+#define ABORT_MASK             0x3
+#define ABORT_SINGLE           0x0
+#define ABORT_ALL              0x1
+
+/**
+ * brief the data structure of SSP SATA SMP Abort Response
+ * use to describe SSP SMP & SATA Abort Response ( 64 bytes)
+ */
+struct task_abort_resp {
+       __le32  tag;
+       __le32  status;
+       __le32  scp;
+       u32     reserved[12];
+} __attribute__((packed, aligned(4)));
+
+/**
+ * brief the data structure of SAS Diagnostic Start/End Command
+ * use to describe MPI SAS Diagnostic Start/End Command (64 bytes)
+ */
+struct sas_diag_start_end_req {
+       __le32  tag;
+       __le32  operation_phyid;
+       u32     reserved[29];
+} __attribute__((packed, aligned(4)));
+
+/**
+ * brief the data structure of SAS Diagnostic Execute Command
+ * use to describe MPI SAS Diagnostic Execute Command (64 bytes)
+ */
+struct sas_diag_execute_req {
+       __le32  tag;
+       __le32  cmdtype_cmddesc_phyid;
+       __le32  pat1_pat2;
+       __le32  threshold;
+       __le32  codepat_errmsk;
+       __le32  pmon;
+       __le32  pERF1CTL;
+       u32     reserved[24];
+} __attribute__((packed, aligned(4)));
+
+#define SAS_DIAG_PARAM_BYTES 24
+
+/*
+ * brief the data structure of Set Device State Command
+ * use to describe MPI Set Device State Command (64 bytes)
+ */
+struct set_dev_state_req {
+       __le32  tag;
+       __le32  device_id;
+       __le32  nds;
+       u32     reserved[28];
+} __attribute__((packed, aligned(4)));
+
+/*
+ * brief the data structure of SATA Start Command
+ * use to describe MPI SATA IO Start Command (64 bytes)
+ * Note: This structure is common for normal / encryption I/O
+ */
+
+struct sata_start_req {
+       __le32  tag;
+       __le32  device_id;
+       __le32  data_len;
+       __le32  ncqtag_atap_dir_m_dad;
+       struct host_to_dev_fis  sata_fis;
+       u32     reserved1;
+       u32     reserved2;      /* dword 11. rsvd for normal I/O. */
+                               /* EPLE Descl for enc I/O */
+       u32     addr_low;       /* dword 12. rsvd for enc I/O */
+       u32     addr_high;      /* dword 13. reserved for enc I/O */
+       __le32  len;            /* dword 14: length for normal I/O. */
+                               /* EPLE Desch for enc I/O */
+       __le32  esgl;           /* dword 15. rsvd for enc I/O */
+       __le32  atapi_scsi_cdb[4];      /* dword 16-19. rsvd for enc I/O */
+       /* The below fields are reserved for normal I/O */
+       __le32  key_index_mode; /* dword 20 */
+       __le32  sector_cnt_enss;/* dword 21 */
+       __le32  keytagl;        /* dword 22 */
+       __le32  keytagh;        /* dword 23 */
+       __le32  twk_val0;       /* dword 24 */
+       __le32  twk_val1;       /* dword 25 */
+       __le32  twk_val2;       /* dword 26 */
+       __le32  twk_val3;       /* dword 27 */
+       __le32  enc_addr_low;   /* dword 28. Encryption SGL address high */
+       __le32  enc_addr_high;  /* dword 29. Encryption SGL address low */
+       __le32  enc_len;        /* dword 30. Encryption length */
+       __le32  enc_esgl;       /* dword 31. Encryption esgl bit */
+} __attribute__((packed, aligned(4)));
+
+/**
+ * brief the data structure of SSP INI TM Start Command
+ * use to describe MPI SSP INI TM Start Command (64 bytes)
+ */
+struct ssp_ini_tm_start_req {
+       __le32  tag;
+       __le32  device_id;
+       __le32  relate_tag;
+       __le32  tmf;
+       u8      lun[8];
+       __le32  ds_ads_m;
+       u32     reserved[24];
+} __attribute__((packed, aligned(4)));
+
+struct ssp_info_unit {
+       u8      lun[8];/* SCSI Logical Unit Number */
+       u8      reserved1;/* reserved */
+       u8      efb_prio_attr;
+       /* B7 : enabledFirstBurst */
+       /* B6-3 : taskPriority */
+       /* B2-0 : taskAttribute */
+       u8      reserved2;      /* reserved */
+       u8      additional_cdb_len;
+       /* B7-2 : additional_cdb_len */
+       /* B1-0 : reserved */
+       u8      cdb[16];/* The SCSI CDB up to 16 bytes length */
+} __attribute__((packed, aligned(4)));
+
+/**
+ * brief the data structure of SSP INI IO Start Command
+ * use to describe MPI SSP INI IO Start Command (64 bytes)
+ * Note: This structure is common for normal / encryption I/O
+ */
+struct ssp_ini_io_start_req {
+       __le32  tag;
+       __le32  device_id;
+       __le32  data_len;
+       __le32  dad_dir_m_tlr;
+       struct ssp_info_unit    ssp_iu;
+       __le32  addr_low;       /* dword 12: sgl low for normal I/O. */
+                               /* epl_descl for encryption I/O */
+       __le32  addr_high;      /* dword 13: sgl hi for normal I/O */
+                               /* dpl_descl for encryption I/O */
+       __le32  len;            /* dword 14: len for normal I/O. */
+                               /* edpl_desch for encryption I/O */
+       __le32  esgl;           /* dword 15: ESGL bit for normal I/O. */
+                               /* user defined tag mask for enc I/O */
+       /* The below fields are reserved for normal I/O */
+       u8      udt[12];        /* dword 16-18 */
+       __le32  sectcnt_ios;    /* dword 19 */
+       __le32  key_cmode;      /* dword 20 */
+       __le32  ks_enss;        /* dword 21 */
+       __le32  keytagl;        /* dword 22 */
+       __le32  keytagh;        /* dword 23 */
+       __le32  twk_val0;       /* dword 24 */
+       __le32  twk_val1;       /* dword 25 */
+       __le32  twk_val2;       /* dword 26 */
+       __le32  twk_val3;       /* dword 27 */
+       __le32  enc_addr_low;   /* dword 28: Encryption sgl addr low */
+       __le32  enc_addr_high;  /* dword 29: Encryption sgl addr hi */
+       __le32  enc_len;        /* dword 30: Encryption length */
+       __le32  enc_esgl;       /* dword 31: ESGL bit for encryption */
+} __attribute__((packed, aligned(4)));
+
+/**
+ * brief the data structure for SSP_INI_DIF_ENC_IO COMMAND
+ * use to initiate SSP I/O operation with optional DIF/ENC
+ */
+struct ssp_dif_enc_io_req {
+       __le32  tag;
+       __le32  device_id;
+       __le32  data_len;
+       __le32  dirMTlr;
+       __le32  sspiu0;
+       __le32  sspiu1;
+       __le32  sspiu2;
+       __le32  sspiu3;
+       __le32  sspiu4;
+       __le32  sspiu5;
+       __le32  sspiu6;
+       __le32  epl_des;
+       __le32  dpl_desl_ndplr;
+       __le32  dpl_desh;
+       __le32  uum_uuv_bss_difbits;
+       u8      udt[12];
+       __le32  sectcnt_ios;
+       __le32  key_cmode;
+       __le32  ks_enss;
+       __le32  keytagl;
+       __le32  keytagh;
+       __le32  twk_val0;
+       __le32  twk_val1;
+       __le32  twk_val2;
+       __le32  twk_val3;
+       __le32  addr_low;
+       __le32  addr_high;
+       __le32  len;
+       __le32  esgl;
+} __attribute__((packed, aligned(4)));
+
+/**
+ * brief the data structure of Firmware download
+ * use to describe MPI FW DOWNLOAD Command (64 bytes)
+ */
+struct fw_flash_Update_req {
+       __le32  tag;
+       __le32  cur_image_offset;
+       __le32  cur_image_len;
+       __le32  total_image_len;
+       u32     reserved0[7];
+       __le32  sgl_addr_lo;
+       __le32  sgl_addr_hi;
+       __le32  len;
+       __le32  ext_reserved;
+       u32     reserved1[16];
+} __attribute__((packed, aligned(4)));
+
+#define FWFLASH_IOMB_RESERVED_LEN 0x07
+/**
+ * brief the data structure of FW_FLASH_UPDATE Response
+ * use to describe MPI FW_FLASH_UPDATE Response (64 bytes)
+ *
+ */
+ struct fw_flash_Update_resp {
+       __le32  tag;
+       __le32  status;
+       u32     reserved[13];
+} __attribute__((packed, aligned(4)));
+
+/**
+ * brief the data structure of Get NVM Data Command
+ * use to get data from NVM in HBA(64 bytes)
+ */
+struct get_nvm_data_req {
+       __le32  tag;
+       __le32  len_ir_vpdd;
+       __le32  vpd_offset;
+       u32     reserved[8];
+       __le32  resp_addr_lo;
+       __le32  resp_addr_hi;
+       __le32  resp_len;
+       u32     reserved1[17];
+} __attribute__((packed, aligned(4)));
+
+struct set_nvm_data_req {
+       __le32  tag;
+       __le32  len_ir_vpdd;
+       __le32  vpd_offset;
+       u32     reserved[8];
+       __le32  resp_addr_lo;
+       __le32  resp_addr_hi;
+       __le32  resp_len;
+       u32     reserved1[17];
+} __attribute__((packed, aligned(4)));
+
+/**
+ * brief the data structure for SET CONTROLLER CONFIG COMMAND
+ * use to modify controller configuration
+ */
+struct set_ctrl_cfg_req {
+       __le32  tag;
+       __le32  cfg_pg[14];
+       u32     reserved[16];
+} __attribute__((packed, aligned(4)));
+
+/**
+ * brief the data structure for GET CONTROLLER CONFIG COMMAND
+ * use to get controller configuration page
+ */
+struct get_ctrl_cfg_req {
+       __le32  tag;
+       __le32  pgcd;
+       __le32  int_vec;
+       u32     reserved[28];
+} __attribute__((packed, aligned(4)));
+
+/**
+ * brief the data structure for KEK_MANAGEMENT COMMAND
+ * use for KEK management
+ */
+struct kek_mgmt_req {
+       __le32  tag;
+       __le32  new_curidx_ksop;
+       u32     reserved;
+       __le32  kblob[12];
+       u32     reserved1[16];
+} __attribute__((packed, aligned(4)));
+
+/**
+ * brief the data structure for DEK_MANAGEMENT COMMAND
+ * use for DEK management
+ */
+struct dek_mgmt_req {
+       __le32  tag;
+       __le32  kidx_dsop;
+       __le32  dekidx;
+       __le32  addr_l;
+       __le32  addr_h;
+       __le32  nent;
+       __le32  dbf_tblsize;
+       u32     reserved[24];
+} __attribute__((packed, aligned(4)));
+
+/**
+ * brief the data structure for SET PHY PROFILE COMMAND
+ * use to retrive phy specific information
+ */
+struct set_phy_profile_req {
+       __le32  tag;
+       __le32  ppc_phyid;
+       u32     reserved[29];
+} __attribute__((packed, aligned(4)));
+
+/**
+ * brief the data structure for GET PHY PROFILE COMMAND
+ * use to retrive phy specific information
+ */
+struct get_phy_profile_req {
+       __le32  tag;
+       __le32  ppc_phyid;
+       __le32  profile[29];
+} __attribute__((packed, aligned(4)));
+
+/**
+ * brief the data structure for EXT FLASH PARTITION
+ * use to manage ext flash partition
+ */
+struct ext_flash_partition_req {
+       __le32  tag;
+       __le32  cmd;
+       __le32  offset;
+       __le32  len;
+       u32     reserved[7];
+       __le32  addr_low;
+       __le32  addr_high;
+       __le32  len1;
+       __le32  ext;
+       u32     reserved1[16];
+} __attribute__((packed, aligned(4)));
+
+#define TWI_DEVICE     0x0
+#define C_SEEPROM      0x1
+#define VPD_FLASH      0x4
+#define AAP1_RDUMP     0x5
+#define IOP_RDUMP      0x6
+#define EXPAN_ROM      0x7
+
+#define IPMode         0x80000000
+#define NVMD_TYPE      0x0000000F
+#define NVMD_STAT      0x0000FFFF
+#define NVMD_LEN       0xFF000000
+/**
+ * brief the data structure of Get NVMD Data Response
+ * use to describe MPI Get NVMD Data Response (64 bytes)
+ */
+struct get_nvm_data_resp {
+       __le32          tag;
+       __le32          ir_tda_bn_dps_das_nvm;
+       __le32          dlen_status;
+       __le32          nvm_data[12];
+} __attribute__((packed, aligned(4)));
+
+/**
+ * brief the data structure of SAS Diagnostic Start/End Response
+ * use to describe MPI SAS Diagnostic Start/End Response (64 bytes)
+ *
+ */
+struct sas_diag_start_end_resp {
+       __le32          tag;
+       __le32          status;
+       u32             reserved[13];
+} __attribute__((packed, aligned(4)));
+
+/**
+ * brief the data structure of SAS Diagnostic Execute Response
+ * use to describe MPI SAS Diagnostic Execute Response (64 bytes)
+ *
+ */
+struct sas_diag_execute_resp {
+       __le32          tag;
+       __le32          cmdtype_cmddesc_phyid;
+       __le32          Status;
+       __le32          ReportData;
+       u32             reserved[11];
+} __attribute__((packed, aligned(4)));
+
+/**
+ * brief the data structure of Set Device State Response
+ * use to describe MPI Set Device State Response (64 bytes)
+ *
+ */
+struct set_dev_state_resp {
+       __le32          tag;
+       __le32          status;
+       __le32          device_id;
+       __le32          pds_nds;
+       u32             reserved[11];
+} __attribute__((packed, aligned(4)));
+
+/* new outbound structure for spcv - begins */
+/**
+ * brief the data structure for SET CONTROLLER CONFIG COMMAND
+ * use to modify controller configuration
+ */
+struct set_ctrl_cfg_resp {
+       __le32 tag;
+       __le32 status;
+       __le32 err_qlfr_pgcd;
+       u32 reserved[12];
+} __attribute__((packed, aligned(4)));
+
+struct get_ctrl_cfg_resp {
+       __le32 tag;
+       __le32 status;
+       __le32 err_qlfr;
+       __le32 confg_page[12];
+} __attribute__((packed, aligned(4)));
+
+struct kek_mgmt_resp {
+       __le32 tag;
+       __le32 status;
+       __le32 kidx_new_curr_ksop;
+       __le32 err_qlfr;
+       u32 reserved[11];
+} __attribute__((packed, aligned(4)));
+
+struct dek_mgmt_resp {
+       __le32 tag;
+       __le32 status;
+       __le32 kekidx_tbls_dsop;
+       __le32 dekidx;
+       __le32 err_qlfr;
+       u32 reserved[10];
+} __attribute__((packed, aligned(4)));
+
+struct get_phy_profile_resp {
+       __le32 tag;
+       __le32 status;
+       __le32 ppc_phyid;
+       __le32 ppc_specific_rsp[12];
+} __attribute__((packed, aligned(4)));
+
+struct flash_op_ext_resp {
+       __le32 tag;
+       __le32 cmd;
+       __le32 status;
+       __le32 epart_size;
+       __le32 epart_sect_size;
+       u32 reserved[10];
+} __attribute__((packed, aligned(4)));
+
+struct set_phy_profile_resp {
+       __le32 tag;
+       __le32 status;
+       __le32 ppc_phyid;
+       __le32 ppc_specific_rsp[12];
+} __attribute__((packed, aligned(4)));
+
+struct ssp_coalesced_comp_resp {
+       __le32 coal_cnt;
+       __le32 tag0;
+       __le32 ssp_tag0;
+       __le32 tag1;
+       __le32 ssp_tag1;
+       __le32 add_tag_ssp_tag[10];
+} __attribute__((packed, aligned(4)));
+
+/* new outbound structure for spcv - ends */
+
+/* brief data structure for SAS protocol timer configuration page.
+ *
+ */
+struct SASProtocolTimerConfig {
+       __le32 pageCode;                        /* 0 */
+       __le32 MST_MSI;                         /* 1 */
+       __le32 STP_SSP_MCT_TMO;                 /* 2 */
+       __le32 STP_FRM_TMO;                     /* 3 */
+       __le32 STP_IDLE_TMO;                    /* 4 */
+       __le32 OPNRJT_RTRY_INTVL;               /* 5 */
+       __le32 Data_Cmd_OPNRJT_RTRY_TMO;        /* 6 */
+       __le32 Data_Cmd_OPNRJT_RTRY_THR;        /* 7 */
+       __le32 MAX_AIP;                         /* 8 */
+} __attribute__((packed, aligned(4)));
+
+typedef struct SASProtocolTimerConfig SASProtocolTimerConfig_t;
+
+#define NDS_BITS 0x0F
+#define PDS_BITS 0xF0
+
+/*
+ * HW Events type
+ */
+
+#define HW_EVENT_RESET_START                   0x01
+#define HW_EVENT_CHIP_RESET_COMPLETE           0x02
+#define HW_EVENT_PHY_STOP_STATUS               0x03
+#define HW_EVENT_SAS_PHY_UP                    0x04
+#define HW_EVENT_SATA_PHY_UP                   0x05
+#define HW_EVENT_SATA_SPINUP_HOLD              0x06
+#define HW_EVENT_PHY_DOWN                      0x07
+#define HW_EVENT_PORT_INVALID                  0x08
+#define HW_EVENT_BROADCAST_CHANGE              0x09
+#define HW_EVENT_PHY_ERROR                     0x0A
+#define HW_EVENT_BROADCAST_SES                 0x0B
+#define HW_EVENT_INBOUND_CRC_ERROR             0x0C
+#define HW_EVENT_HARD_RESET_RECEIVED           0x0D
+#define HW_EVENT_MALFUNCTION                   0x0E
+#define HW_EVENT_ID_FRAME_TIMEOUT              0x0F
+#define HW_EVENT_BROADCAST_EXP                 0x10
+#define HW_EVENT_PHY_START_STATUS              0x11
+#define HW_EVENT_LINK_ERR_INVALID_DWORD                0x12
+#define HW_EVENT_LINK_ERR_DISPARITY_ERROR      0x13
+#define HW_EVENT_LINK_ERR_CODE_VIOLATION       0x14
+#define HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH  0x15
+#define HW_EVENT_LINK_ERR_PHY_RESET_FAILED     0x16
+#define HW_EVENT_PORT_RECOVERY_TIMER_TMO       0x17
+#define HW_EVENT_PORT_RECOVER                  0x18
+#define HW_EVENT_PORT_RESET_TIMER_TMO          0x19
+#define HW_EVENT_PORT_RESET_COMPLETE           0x20
+#define EVENT_BROADCAST_ASYNCH_EVENT           0x21
+
+/* port state */
+#define PORT_NOT_ESTABLISHED                   0x00
+#define PORT_VALID                             0x01
+#define PORT_LOSTCOMM                          0x02
+#define PORT_IN_RESET                          0x04
+#define PORT_3RD_PARTY_RESET                   0x07
+#define PORT_INVALID                           0x08
+
+/*
+ * SSP/SMP/SATA IO Completion Status values
+ */
+
+#define IO_SUCCESS                             0x00
+#define IO_ABORTED                             0x01
+#define IO_OVERFLOW                            0x02
+#define IO_UNDERFLOW                           0x03
+#define IO_FAILED                              0x04
+#define IO_ABORT_RESET                         0x05
+#define IO_NOT_VALID                           0x06
+#define IO_NO_DEVICE                           0x07
+#define IO_ILLEGAL_PARAMETER                   0x08
+#define IO_LINK_FAILURE                                0x09
+#define IO_PROG_ERROR                          0x0A
+
+#define IO_EDC_IN_ERROR                                0x0B
+#define IO_EDC_OUT_ERROR                       0x0C
+#define IO_ERROR_HW_TIMEOUT                    0x0D
+#define IO_XFER_ERROR_BREAK                    0x0E
+#define IO_XFER_ERROR_PHY_NOT_READY            0x0F
+#define IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED       0x10
+#define IO_OPEN_CNX_ERROR_ZONE_VIOLATION               0x11
+#define IO_OPEN_CNX_ERROR_BREAK                                0x12
+#define IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS                        0x13
+#define IO_OPEN_CNX_ERROR_BAD_DESTINATION              0x14
+#define IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED        0x15
+#define IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY           0x16
+#define IO_OPEN_CNX_ERROR_WRONG_DESTINATION            0x17
+/* This error code 0x18 is not used on SPCv */
+#define IO_OPEN_CNX_ERROR_UNKNOWN_ERROR                        0x18
+#define IO_XFER_ERROR_NAK_RECEIVED                     0x19
+#define IO_XFER_ERROR_ACK_NAK_TIMEOUT                  0x1A
+#define IO_XFER_ERROR_PEER_ABORTED                     0x1B
+#define IO_XFER_ERROR_RX_FRAME                         0x1C
+#define IO_XFER_ERROR_DMA                              0x1D
+#define IO_XFER_ERROR_CREDIT_TIMEOUT                   0x1E
+#define IO_XFER_ERROR_SATA_LINK_TIMEOUT                        0x1F
+#define IO_XFER_ERROR_SATA                             0x20
+
+/* This error code 0x22 is not used on SPCv */
+#define IO_XFER_ERROR_ABORTED_DUE_TO_SRST              0x22
+#define IO_XFER_ERROR_REJECTED_NCQ_MODE                        0x21
+#define IO_XFER_ERROR_ABORTED_NCQ_MODE                 0x23
+#define IO_XFER_OPEN_RETRY_TIMEOUT                     0x24
+/* This error code 0x25 is not used on SPCv */
+#define IO_XFER_SMP_RESP_CONNECTION_ERROR              0x25
+#define IO_XFER_ERROR_UNEXPECTED_PHASE                 0x26
+#define IO_XFER_ERROR_XFER_RDY_OVERRUN                 0x27
+#define IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED            0x28
+#define IO_XFER_ERROR_CMD_ISSUE_ACK_NAK_TIMEOUT                0x30
+
+/* The following error code 0x31 and 0x32 are not using (obsolete) */
+#define IO_XFER_ERROR_CMD_ISSUE_BREAK_BEFORE_ACK_NAK   0x31
+#define IO_XFER_ERROR_CMD_ISSUE_PHY_DOWN_BEFORE_ACK_NAK        0x32
+
+#define IO_XFER_ERROR_OFFSET_MISMATCH                  0x34
+#define IO_XFER_ERROR_XFER_ZERO_DATA_LEN               0x35
+#define IO_XFER_CMD_FRAME_ISSUED                       0x36
+#define IO_ERROR_INTERNAL_SMP_RESOURCE                 0x37
+#define IO_PORT_IN_RESET                               0x38
+#define IO_DS_NON_OPERATIONAL                          0x39
+#define IO_DS_IN_RECOVERY                              0x3A
+#define IO_TM_TAG_NOT_FOUND                            0x3B
+#define IO_XFER_PIO_SETUP_ERROR                                0x3C
+#define IO_SSP_EXT_IU_ZERO_LEN_ERROR                   0x3D
+#define IO_DS_IN_ERROR                                 0x3E
+#define IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY             0x3F
+#define IO_ABORT_IN_PROGRESS                           0x40
+#define IO_ABORT_DELAYED                               0x41
+#define IO_INVALID_LENGTH                              0x42
+
+/********** additional response event values *****************/
+
+#define IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY_ALT         0x43
+#define IO_XFER_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED   0x44
+#define IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_TMO       0x45
+#define IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST                0x46
+#define IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE   0x47
+#define IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED        0x48
+#define IO_DS_INVALID                                  0x49
+/* WARNING: the value is not contiguous from here */
+#define IO_XFER_ERR_LAST_PIO_DATAIN_CRC_ERR    0x52
+#define IO_XFER_DMA_ACTIVATE_TIMEOUT           0x53
+#define IO_XFER_ERROR_INTERNAL_CRC_ERROR       0x54
+#define MPI_IO_RQE_BUSY_FULL                   0x55
+#define IO_XFER_ERR_EOB_DATA_OVERRUN           0x56
+#define IO_XFR_ERROR_INVALID_SSP_RSP_FRAME     0x57
+#define IO_OPEN_CNX_ERROR_OPEN_PREEMPTED       0x58
+
+#define MPI_ERR_IO_RESOURCE_UNAVAILABLE                0x1004
+#define MPI_ERR_ATAPI_DEVICE_BUSY              0x1024
+
+#define IO_XFR_ERROR_DEK_KEY_CACHE_MISS                0x2040
+/*
+ * An encryption IO request failed due to DEK Key Tag mismatch.
+ * The key tag supplied in the encryption IOMB does not match with
+ * the Key Tag in the referenced DEK Entry.
+ */
+#define IO_XFR_ERROR_DEK_KEY_TAG_MISMATCH      0x2041
+#define IO_XFR_ERROR_CIPHER_MODE_INVALID       0x2042
+/*
+ * An encryption I/O request failed because the initial value (IV)
+ * in the unwrapped DEK blob didn't match the IV used to unwrap it.
+ */
+#define IO_XFR_ERROR_DEK_IV_MISMATCH           0x2043
+/* An encryption I/O request failed due to an internal RAM ECC or
+ * interface error while unwrapping the DEK. */
+#define IO_XFR_ERROR_DEK_RAM_INTERFACE_ERROR   0x2044
+/* An encryption I/O request failed due to an internal RAM ECC or
+ * interface error while unwrapping the DEK. */
+#define IO_XFR_ERROR_INTERNAL_RAM              0x2045
+/*
+ * An encryption I/O request failed
+ * because the DEK index specified in the I/O was outside the bounds of
+ * the total number of entries in the host DEK table.
+ */
+#define IO_XFR_ERROR_DEK_INDEX_OUT_OF_BOUNDS0x2046
+
+/* define DIF IO response error status code */
+#define IO_XFR_ERROR_DIF_MISMATCH                      0x3000
+#define IO_XFR_ERROR_DIF_APPLICATION_TAG_MISMATCH      0x3001
+#define IO_XFR_ERROR_DIF_REFERENCE_TAG_MISMATCH                0x3002
+#define IO_XFR_ERROR_DIF_CRC_MISMATCH                  0x3003
+
+/* define operator management response status and error qualifier code */
+#define OPR_MGMT_OP_NOT_SUPPORTED                      0x2060
+#define OPR_MGMT_MPI_ENC_ERR_OPR_PARAM_ILLEGAL         0x2061
+#define OPR_MGMT_MPI_ENC_ERR_OPR_ID_NOT_FOUND          0x2062
+#define OPR_MGMT_MPI_ENC_ERR_OPR_ROLE_NOT_MATCH                0x2063
+#define OPR_MGMT_MPI_ENC_ERR_OPR_MAX_NUM_EXCEEDED      0x2064
+#define OPR_MGMT_MPI_ENC_ERR_KEK_UNWRAP_FAIL           0x2022
+#define OPR_MGMT_MPI_ENC_ERR_NVRAM_OPERATION_FAILURE   0x2023
+/***************** additional response event values ***************/
+
+/* WARNING: This error code must always be the last number.
+ * If you add error code, modify this code also
+ * It is used as an index
+ */
+#define IO_ERROR_UNKNOWN_GENERIC                       0x2023
+
+/* MSGU CONFIGURATION TABLE*/
+
+#define SPCv_MSGU_CFG_TABLE_UPDATE             0x01
+#define SPCv_MSGU_CFG_TABLE_RESET              0x02
+#define SPCv_MSGU_CFG_TABLE_FREEZE             0x04
+#define SPCv_MSGU_CFG_TABLE_UNFREEZE           0x08
+#define MSGU_IBDB_SET                          0x00
+#define MSGU_HOST_INT_STATUS                   0x08
+#define MSGU_HOST_INT_MASK                     0x0C
+#define MSGU_IOPIB_INT_STATUS                  0x18
+#define MSGU_IOPIB_INT_MASK                    0x1C
+#define MSGU_IBDB_CLEAR                                0x20
+
+#define MSGU_MSGU_CONTROL                      0x24
+#define MSGU_ODR                               0x20
+#define MSGU_ODCR                              0x28
+
+#define MSGU_ODMR                              0x30
+#define MSGU_ODMR_U                            0x34
+#define MSGU_ODMR_CLR                          0x38
+#define MSGU_ODMR_CLR_U                                0x3C
+#define MSGU_OD_RSVD                           0x40
+
+#define MSGU_SCRATCH_PAD_0                     0x44
+#define MSGU_SCRATCH_PAD_1                     0x48
+#define MSGU_SCRATCH_PAD_2                     0x4C
+#define MSGU_SCRATCH_PAD_3                     0x50
+#define MSGU_HOST_SCRATCH_PAD_0                        0x54
+#define MSGU_HOST_SCRATCH_PAD_1                        0x58
+#define MSGU_HOST_SCRATCH_PAD_2                        0x5C
+#define MSGU_HOST_SCRATCH_PAD_3                        0x60
+#define MSGU_HOST_SCRATCH_PAD_4                        0x64
+#define MSGU_HOST_SCRATCH_PAD_5                        0x68
+#define MSGU_HOST_SCRATCH_PAD_6                        0x6C
+#define MSGU_HOST_SCRATCH_PAD_7                        0x70
+
+/* bit definition for ODMR register */
+#define ODMR_MASK_ALL                  0xFFFFFFFF/* mask all
+                                       interrupt vector */
+#define ODMR_CLEAR_ALL                 0       /* clear all
+                                       interrupt vector */
+/* bit definition for ODCR register */
+#define ODCR_CLEAR_ALL                 0xFFFFFFFF /* mask all
+                                       interrupt vector*/
+/* MSIX Interupts */
+#define MSIX_TABLE_OFFSET              0x2000
+#define MSIX_TABLE_ELEMENT_SIZE                0x10
+#define MSIX_INTERRUPT_CONTROL_OFFSET  0xC
+#define MSIX_TABLE_BASE                        (MSIX_TABLE_OFFSET + \
+                                       MSIX_INTERRUPT_CONTROL_OFFSET)
+#define MSIX_INTERRUPT_DISABLE         0x1
+#define MSIX_INTERRUPT_ENABLE          0x0
+
+/* state definition for Scratch Pad1 register */
+#define SCRATCH_PAD_RAAE_READY         0x3
+#define SCRATCH_PAD_ILA_READY          0xC
+#define SCRATCH_PAD_BOOT_LOAD_SUCCESS  0x0
+#define SCRATCH_PAD_IOP0_READY         0xC00
+#define SCRATCH_PAD_IOP1_READY         0x3000
+
+/* boot loader state */
+#define SCRATCH_PAD1_BOOTSTATE_MASK            0x70    /* Bit 4-6 */
+#define SCRATCH_PAD1_BOOTSTATE_SUCESS          0x0     /* Load successful */
+#define SCRATCH_PAD1_BOOTSTATE_HDA_SEEPROM     0x10    /* HDA SEEPROM */
+#define SCRATCH_PAD1_BOOTSTATE_HDA_BOOTSTRAP   0x20    /* HDA BootStrap Pins */
+#define SCRATCH_PAD1_BOOTSTATE_HDA_SOFTRESET   0x30    /* HDA Soft Reset */
+#define SCRATCH_PAD1_BOOTSTATE_CRIT_ERROR      0x40    /* HDA critical error */
+#define SCRATCH_PAD1_BOOTSTATE_R1              0x50    /* Reserved */
+#define SCRATCH_PAD1_BOOTSTATE_R2              0x60    /* Reserved */
+#define SCRATCH_PAD1_BOOTSTATE_FATAL           0x70    /* Fatal Error */
+
+ /* state definition for Scratch Pad2 register */
+#define SCRATCH_PAD2_POR               0x00    /* power on state */
+#define SCRATCH_PAD2_SFR               0x01    /* soft reset state */
+#define SCRATCH_PAD2_ERR               0x02    /* error state */
+#define SCRATCH_PAD2_RDY               0x03    /* ready state */
+#define SCRATCH_PAD2_FWRDY_RST         0x04    /* FW rdy for soft reset flag */
+#define SCRATCH_PAD2_IOPRDY_RST                0x08    /* IOP ready for soft reset */
+#define SCRATCH_PAD2_STATE_MASK                0xFFFFFFF4 /* ScratchPad 2
+ Mask, bit1-0 State */
+#define SCRATCH_PAD2_RESERVED          0x000003FC/* Scratch Pad1
+ Reserved bit 2 to 9 */
+
+#define SCRATCH_PAD_ERROR_MASK         0xFFFFFC00 /* Error mask bits */
+#define SCRATCH_PAD_STATE_MASK         0x00000003 /* State Mask bits */
+
+/* main configuration offset - byte offset */
+#define MAIN_SIGNATURE_OFFSET          0x00 /* DWORD 0x00 */
+#define MAIN_INTERFACE_REVISION                0x04 /* DWORD 0x01 */
+#define MAIN_FW_REVISION               0x08 /* DWORD 0x02 */
+#define MAIN_MAX_OUTSTANDING_IO_OFFSET 0x0C /* DWORD 0x03 */
+#define MAIN_MAX_SGL_OFFSET            0x10 /* DWORD 0x04 */
+#define MAIN_CNTRL_CAP_OFFSET          0x14 /* DWORD 0x05 */
+#define MAIN_GST_OFFSET                        0x18 /* DWORD 0x06 */
+#define MAIN_IBQ_OFFSET                        0x1C /* DWORD 0x07 */
+#define MAIN_OBQ_OFFSET                        0x20 /* DWORD 0x08 */
+#define MAIN_IQNPPD_HPPD_OFFSET                0x24 /* DWORD 0x09 */
+
+/* 0x28 - 0x4C - RSVD */
+#define MAIN_EVENT_CRC_CHECK           0x48 /* DWORD 0x12 */
+#define MAIN_EVENT_LOG_ADDR_HI         0x50 /* DWORD 0x14 */
+#define MAIN_EVENT_LOG_ADDR_LO         0x54 /* DWORD 0x15 */
+#define MAIN_EVENT_LOG_BUFF_SIZE       0x58 /* DWORD 0x16 */
+#define MAIN_EVENT_LOG_OPTION          0x5C /* DWORD 0x17 */
+#define MAIN_PCS_EVENT_LOG_ADDR_HI     0x60 /* DWORD 0x18 */
+#define MAIN_PCS_EVENT_LOG_ADDR_LO     0x64 /* DWORD 0x19 */
+#define MAIN_PCS_EVENT_LOG_BUFF_SIZE   0x68 /* DWORD 0x1A */
+#define MAIN_PCS_EVENT_LOG_OPTION      0x6C /* DWORD 0x1B */
+#define MAIN_FATAL_ERROR_INTERRUPT     0x70 /* DWORD 0x1C */
+#define MAIN_FATAL_ERROR_RDUMP0_OFFSET 0x74 /* DWORD 0x1D */
+#define MAIN_FATAL_ERROR_RDUMP0_LENGTH 0x78 /* DWORD 0x1E */
+#define MAIN_FATAL_ERROR_RDUMP1_OFFSET 0x7C /* DWORD 0x1F */
+#define MAIN_FATAL_ERROR_RDUMP1_LENGTH 0x80 /* DWORD 0x20 */
+#define MAIN_GPIO_LED_FLAGS_OFFSET     0x84 /* DWORD 0x21 */
+#define MAIN_ANALOG_SETUP_OFFSET       0x88 /* DWORD 0x22 */
+
+#define MAIN_INT_VECTOR_TABLE_OFFSET   0x8C /* DWORD 0x23 */
+#define MAIN_SAS_PHY_ATTR_TABLE_OFFSET 0x90 /* DWORD 0x24 */
+#define MAIN_PORT_RECOVERY_TIMER       0x94 /* DWORD 0x25 */
+#define MAIN_INT_REASSERTION_DELAY     0x98 /* DWORD 0x26 */
+
+/* Gereral Status Table offset - byte offset */
+#define GST_GSTLEN_MPIS_OFFSET         0x00
+#define GST_IQ_FREEZE_STATE0_OFFSET    0x04
+#define GST_IQ_FREEZE_STATE1_OFFSET    0x08
+#define GST_MSGUTCNT_OFFSET            0x0C
+#define GST_IOPTCNT_OFFSET             0x10
+/* 0x14 - 0x34 - RSVD */
+#define GST_GPIO_INPUT_VAL             0x38
+/* 0x3c - 0x40 - RSVD */
+#define GST_RERRINFO_OFFSET0           0x44
+#define GST_RERRINFO_OFFSET1           0x48
+#define GST_RERRINFO_OFFSET2           0x4c
+#define GST_RERRINFO_OFFSET3           0x50
+#define GST_RERRINFO_OFFSET4           0x54
+#define GST_RERRINFO_OFFSET5           0x58
+#define GST_RERRINFO_OFFSET6           0x5c
+#define GST_RERRINFO_OFFSET7           0x60
+
+/* General Status Table - MPI state */
+#define GST_MPI_STATE_UNINIT           0x00
+#define GST_MPI_STATE_INIT             0x01
+#define GST_MPI_STATE_TERMINATION      0x02
+#define GST_MPI_STATE_ERROR            0x03
+#define GST_MPI_STATE_MASK             0x07
+
+/* Per SAS PHY Attributes */
+
+#define PSPA_PHYSTATE0_OFFSET          0x00 /* Dword V */
+#define PSPA_OB_HW_EVENT_PID0_OFFSET   0x04 /* DWORD V+1 */
+#define PSPA_PHYSTATE1_OFFSET          0x08 /* Dword V+2 */
+#define PSPA_OB_HW_EVENT_PID1_OFFSET   0x0C /* DWORD V+3 */
+#define PSPA_PHYSTATE2_OFFSET          0x10 /* Dword V+4 */
+#define PSPA_OB_HW_EVENT_PID2_OFFSET   0x14 /* DWORD V+5 */
+#define PSPA_PHYSTATE3_OFFSET          0x18 /* Dword V+6 */
+#define PSPA_OB_HW_EVENT_PID3_OFFSET   0x1C /* DWORD V+7 */
+#define PSPA_PHYSTATE4_OFFSET          0x20 /* Dword V+8 */
+#define PSPA_OB_HW_EVENT_PID4_OFFSET   0x24 /* DWORD V+9 */
+#define PSPA_PHYSTATE5_OFFSET          0x28 /* Dword V+10 */
+#define PSPA_OB_HW_EVENT_PID5_OFFSET   0x2C /* DWORD V+11 */
+#define PSPA_PHYSTATE6_OFFSET          0x30 /* Dword V+12 */
+#define PSPA_OB_HW_EVENT_PID6_OFFSET   0x34 /* DWORD V+13 */
+#define PSPA_PHYSTATE7_OFFSET          0x38 /* Dword V+14 */
+#define PSPA_OB_HW_EVENT_PID7_OFFSET   0x3C /* DWORD V+15 */
+#define PSPA_PHYSTATE8_OFFSET          0x40 /* DWORD V+16 */
+#define PSPA_OB_HW_EVENT_PID8_OFFSET   0x44 /* DWORD V+17 */
+#define PSPA_PHYSTATE9_OFFSET          0x48 /* DWORD V+18 */
+#define PSPA_OB_HW_EVENT_PID9_OFFSET   0x4C /* DWORD V+19 */
+#define PSPA_PHYSTATE10_OFFSET         0x50 /* DWORD V+20 */
+#define PSPA_OB_HW_EVENT_PID10_OFFSET  0x54 /* DWORD V+21 */
+#define PSPA_PHYSTATE11_OFFSET         0x58 /* DWORD V+22 */
+#define PSPA_OB_HW_EVENT_PID11_OFFSET  0x5C /* DWORD V+23 */
+#define PSPA_PHYSTATE12_OFFSET         0x60 /* DWORD V+24 */
+#define PSPA_OB_HW_EVENT_PID12_OFFSET  0x64 /* DWORD V+25 */
+#define PSPA_PHYSTATE13_OFFSET         0x68 /* DWORD V+26 */
+#define PSPA_OB_HW_EVENT_PID13_OFFSET  0x6c /* DWORD V+27 */
+#define PSPA_PHYSTATE14_OFFSET         0x70 /* DWORD V+28 */
+#define PSPA_OB_HW_EVENT_PID14_OFFSET  0x74 /* DWORD V+29 */
+#define PSPA_PHYSTATE15_OFFSET         0x78 /* DWORD V+30 */
+#define PSPA_OB_HW_EVENT_PID15_OFFSET  0x7c /* DWORD V+31 */
+/* end PSPA */
+
+/* inbound queue configuration offset - byte offset */
+#define IB_PROPERITY_OFFSET            0x00
+#define IB_BASE_ADDR_HI_OFFSET         0x04
+#define IB_BASE_ADDR_LO_OFFSET         0x08
+#define IB_CI_BASE_ADDR_HI_OFFSET      0x0C
+#define IB_CI_BASE_ADDR_LO_OFFSET      0x10
+#define IB_PIPCI_BAR                   0x14
+#define IB_PIPCI_BAR_OFFSET            0x18
+#define IB_RESERVED_OFFSET             0x1C
+
+/* outbound queue configuration offset - byte offset */
+#define OB_PROPERITY_OFFSET            0x00
+#define OB_BASE_ADDR_HI_OFFSET         0x04
+#define OB_BASE_ADDR_LO_OFFSET         0x08
+#define OB_PI_BASE_ADDR_HI_OFFSET      0x0C
+#define OB_PI_BASE_ADDR_LO_OFFSET      0x10
+#define OB_CIPCI_BAR                   0x14
+#define OB_CIPCI_BAR_OFFSET            0x18
+#define OB_INTERRUPT_COALES_OFFSET     0x1C
+#define OB_DYNAMIC_COALES_OFFSET       0x20
+#define OB_PROPERTY_INT_ENABLE         0x40000000
+
+#define MBIC_NMI_ENABLE_VPE0_IOP       0x000418
+#define MBIC_NMI_ENABLE_VPE0_AAP1      0x000418
+/* PCIE registers - BAR2(0x18), BAR1(win) 0x010000 */
+#define PCIE_EVENT_INTERRUPT_ENABLE    0x003040
+#define PCIE_EVENT_INTERRUPT           0x003044
+#define PCIE_ERROR_INTERRUPT_ENABLE    0x003048
+#define PCIE_ERROR_INTERRUPT           0x00304C
+
+/* SPCV soft reset */
+#define SPC_REG_SOFT_RESET 0x00001000
+#define SPCv_NORMAL_RESET_VALUE                0x1
+
+#define SPCv_SOFT_RESET_READ_MASK              0xC0
+#define SPCv_SOFT_RESET_NO_RESET               0x0
+#define SPCv_SOFT_RESET_NORMAL_RESET_OCCURED   0x40
+#define SPCv_SOFT_RESET_HDA_MODE_OCCURED       0x80
+#define SPCv_SOFT_RESET_CHIP_RESET_OCCURED     0xC0
+
+/* signature definition for host scratch pad0 register */
+#define SPC_SOFT_RESET_SIGNATURE       0x252acbcd
+/* Signature for Soft Reset */
+
+/* SPC Reset register - BAR4(0x20), BAR2(win) (need dynamic mapping) */
+#define SPC_REG_RESET                  0x000000/* reset register */
+
+/* bit definition for SPC_RESET register */
+#define SPC_REG_RESET_OSSP             0x00000001
+#define SPC_REG_RESET_RAAE             0x00000002
+#define SPC_REG_RESET_PCS_SPBC         0x00000004
+#define SPC_REG_RESET_PCS_IOP_SS       0x00000008
+#define SPC_REG_RESET_PCS_AAP1_SS      0x00000010
+#define SPC_REG_RESET_PCS_AAP2_SS      0x00000020
+#define SPC_REG_RESET_PCS_LM           0x00000040
+#define SPC_REG_RESET_PCS              0x00000080
+#define SPC_REG_RESET_GSM              0x00000100
+#define SPC_REG_RESET_DDR2             0x00010000
+#define SPC_REG_RESET_BDMA_CORE                0x00020000
+#define SPC_REG_RESET_BDMA_SXCBI       0x00040000
+#define SPC_REG_RESET_PCIE_AL_SXCBI    0x00080000
+#define SPC_REG_RESET_PCIE_PWR         0x00100000
+#define SPC_REG_RESET_PCIE_SFT         0x00200000
+#define SPC_REG_RESET_PCS_SXCBI                0x00400000
+#define SPC_REG_RESET_LMS_SXCBI                0x00800000
+#define SPC_REG_RESET_PMIC_SXCBI       0x01000000
+#define SPC_REG_RESET_PMIC_CORE                0x02000000
+#define SPC_REG_RESET_PCIE_PC_SXCBI    0x04000000
+#define SPC_REG_RESET_DEVICE           0x80000000
+
+/* registers for BAR Shifting - BAR2(0x18), BAR1(win) */
+#define SPCV_IBW_AXI_TRANSLATION_LOW   0x001010
+
+#define MBIC_AAP1_ADDR_BASE            0x060000
+#define MBIC_IOP_ADDR_BASE             0x070000
+#define GSM_ADDR_BASE                  0x0700000
+/* Dynamic map through Bar4 - 0x00700000 */
+#define GSM_CONFIG_RESET               0x00000000
+#define RAM_ECC_DB_ERR                 0x00000018
+#define GSM_READ_ADDR_PARITY_INDIC     0x00000058
+#define GSM_WRITE_ADDR_PARITY_INDIC    0x00000060
+#define GSM_WRITE_DATA_PARITY_INDIC    0x00000068
+#define GSM_READ_ADDR_PARITY_CHECK     0x00000038
+#define GSM_WRITE_ADDR_PARITY_CHECK    0x00000040
+#define GSM_WRITE_DATA_PARITY_CHECK    0x00000048
+
+#define RB6_ACCESS_REG                 0x6A0000
+#define HDAC_EXEC_CMD                  0x0002
+#define HDA_C_PA                       0xcb
+#define HDA_SEQ_ID_BITS                        0x00ff0000
+#define HDA_GSM_OFFSET_BITS            0x00FFFFFF
+#define HDA_GSM_CMD_OFFSET_BITS                0x42C0
+#define HDA_GSM_RSP_OFFSET_BITS                0x42E0
+
+#define MBIC_AAP1_ADDR_BASE            0x060000
+#define MBIC_IOP_ADDR_BASE             0x070000
+#define GSM_ADDR_BASE                  0x0700000
+#define SPC_TOP_LEVEL_ADDR_BASE                0x000000
+#define GSM_CONFIG_RESET_VALUE         0x00003b00
+#define GPIO_ADDR_BASE                 0x00090000
+#define GPIO_GPIO_0_0UTPUT_CTL_OFFSET  0x0000010c
+
+/* RB6 offset */
+#define SPC_RB6_OFFSET                 0x80C0
+/* Magic number of soft reset for RB6 */
+#define RB6_MAGIC_NUMBER_RST           0x1234
+
+/* Device Register status */
+#define DEVREG_SUCCESS                                 0x00
+#define DEVREG_FAILURE_OUT_OF_RESOURCE                 0x01
+#define DEVREG_FAILURE_DEVICE_ALREADY_REGISTERED       0x02
+#define DEVREG_FAILURE_INVALID_PHY_ID                  0x03
+#define DEVREG_FAILURE_PHY_ID_ALREADY_REGISTERED       0x04
+#define DEVREG_FAILURE_PORT_ID_OUT_OF_RANGE            0x05
+#define DEVREG_FAILURE_PORT_NOT_VALID_STATE            0x06
+#define DEVREG_FAILURE_DEVICE_TYPE_NOT_VALID           0x07
+
+#endif
index 317a7fd..23d6072 100644 (file)
@@ -24,7 +24,9 @@ config SCSI_QLA_FC
 
        Firmware images can be retrieved from:
 
-               ftp://ftp.qlogic.com/outgoing/linux/firmware/
+               http://ldriver.qlogic.com/firmware/
+
+       They are also included in the linux-firmware tree as well.
 
 config TCM_QLA2XXX
        tristate "TCM_QLA2XXX fabric module for Qlogic 2xxx series target mode HBAs"
index 729b743..937fed8 100644 (file)
@@ -3003,12 +3003,10 @@ qlafx00_build_scsi_iocbs(srb_t *sp, struct cmd_type_7_fx00 *cmd_pkt,
 
        /* Set transfer direction */
        if (cmd->sc_data_direction == DMA_TO_DEVICE) {
-               lcmd_pkt->cntrl_flags =
-                   __constant_cpu_to_le16(TMF_WRITE_DATA);
+               lcmd_pkt->cntrl_flags = TMF_WRITE_DATA;
                vha->qla_stats.output_bytes += scsi_bufflen(cmd);
        } else if (cmd->sc_data_direction == DMA_FROM_DEVICE) {
-               lcmd_pkt->cntrl_flags =
-                   __constant_cpu_to_le16(TMF_READ_DATA);
+               lcmd_pkt->cntrl_flags = TMF_READ_DATA;
                vha->qla_stats.input_bytes += scsi_bufflen(cmd);
        }
 
index 5307bf8..ad72c1d 100644 (file)
@@ -644,7 +644,7 @@ qla2x00_sp_free_dma(void *vha, void *ptr)
        qla2x00_rel_sp(sp->fcport->vha, sp);
 }
 
-void
+static void
 qla2x00_sp_compl(void *data, void *ptr, int res)
 {
        struct qla_hw_data *ha = (struct qla_hw_data *)data;
index d182c96..7a3870f 100644 (file)
@@ -1370,7 +1370,7 @@ static void tcm_qla2xxx_free_session(struct qla_tgt_sess *sess)
                dump_stack();
                return;
        }
-       target_wait_for_sess_cmds(se_sess, 0);
+       target_wait_for_sess_cmds(se_sess);
 
        transport_deregister_session_configfs(sess->se_sess);
        transport_deregister_session(sess->se_sess);
index 14fec97..fad71ed 100644 (file)
@@ -507,6 +507,7 @@ static int qla4xxx_send_mbox_iocb(struct scsi_qla_host *ha, struct mrb *mrb,
        mrb->mbox_cmd = in_mbox[0];
        wmb();
 
+       ha->iocb_cnt += mrb->iocb_cnt;
        ha->isp_ops->queue_iocb(ha);
 exit_mbox_iocb:
        spin_unlock_irqrestore(&ha->hardware_lock, flags);
index a47f999..4d231c1 100644 (file)
@@ -2216,14 +2216,14 @@ static int qla4xxx_copy_to_fwddb_param(struct iscsi_bus_flash_session *sess,
        fw_ddb_entry->iscsi_def_time2retain = cpu_to_le16(sess->time2retain);
        fw_ddb_entry->tgt_portal_grp = cpu_to_le16(sess->tpgt);
        fw_ddb_entry->mss = cpu_to_le16(conn->max_segment_size);
-       fw_ddb_entry->tcp_xmt_wsf = cpu_to_le16(conn->tcp_xmit_wsf);
-       fw_ddb_entry->tcp_rcv_wsf = cpu_to_le16(conn->tcp_recv_wsf);
+       fw_ddb_entry->tcp_xmt_wsf = (uint8_t) cpu_to_le32(conn->tcp_xmit_wsf);
+       fw_ddb_entry->tcp_rcv_wsf = (uint8_t) cpu_to_le32(conn->tcp_recv_wsf);
        fw_ddb_entry->ipv4_tos = conn->ipv4_tos;
        fw_ddb_entry->ipv6_flow_lbl = cpu_to_le16(conn->ipv6_flow_label);
        fw_ddb_entry->ka_timeout = cpu_to_le16(conn->keepalive_timeout);
        fw_ddb_entry->lcl_port = cpu_to_le16(conn->local_port);
-       fw_ddb_entry->stat_sn = cpu_to_le16(conn->statsn);
-       fw_ddb_entry->exp_stat_sn = cpu_to_le16(conn->exp_statsn);
+       fw_ddb_entry->stat_sn = cpu_to_le32(conn->statsn);
+       fw_ddb_entry->exp_stat_sn = cpu_to_le32(conn->exp_statsn);
        fw_ddb_entry->ddb_link = cpu_to_le16(sess->discovery_parent_type);
        fw_ddb_entry->chap_tbl_idx = cpu_to_le16(sess->chap_out_idx);
        fw_ddb_entry->tsid = cpu_to_le16(sess->tsid);
@@ -5504,9 +5504,9 @@ static int qla4xxx_sysfs_ddb_is_non_persistent(struct device *dev, void *data)
  * If this is invoked as a result of a userspace call then the entry is marked
  * as nonpersistent using flash_state field.
  **/
-int qla4xxx_sysfs_ddb_tgt_create(struct scsi_qla_host *ha,
-                                struct dev_db_entry *fw_ddb_entry,
-                                uint16_t *idx, int user)
+static int qla4xxx_sysfs_ddb_tgt_create(struct scsi_qla_host *ha,
+                                       struct dev_db_entry *fw_ddb_entry,
+                                       uint16_t *idx, int user)
 {
        struct iscsi_bus_flash_session *fnode_sess = NULL;
        struct iscsi_bus_flash_conn *fnode_conn = NULL;
@@ -5605,6 +5605,7 @@ static int qla4xxx_sysfs_ddb_add(struct Scsi_Host *shost, const char *buf,
                ql4_printk(KERN_ERR, ha,
                           "%s: A non-persistent entry %s found\n",
                           __func__, dev->kobj.name);
+               put_device(dev);
                goto exit_ddb_add;
        }
 
@@ -6112,8 +6113,7 @@ qla4xxx_sysfs_ddb_get_param(struct iscsi_bus_flash_session *fnode_sess,
        int parent_type, parent_index = 0xffff;
        int rc = 0;
 
-       dev = iscsi_find_flashnode_conn(fnode_sess, NULL,
-                                       iscsi_is_flashnode_conn_dev);
+       dev = iscsi_find_flashnode_conn(fnode_sess);
        if (!dev)
                return -EIO;
 
@@ -6276,8 +6276,7 @@ qla4xxx_sysfs_ddb_get_param(struct iscsi_bus_flash_session *fnode_sess,
                        rc = sprintf(buf, "\n");
                break;
        case ISCSI_FLASHNODE_DISCOVERY_PARENT_IDX:
-               if ((fnode_sess->discovery_parent_idx) >= 0  &&
-                   (fnode_sess->discovery_parent_idx < MAX_DDB_ENTRIES))
+               if (fnode_sess->discovery_parent_idx < MAX_DDB_ENTRIES)
                        parent_index = fnode_sess->discovery_parent_idx;
 
                rc = sprintf(buf, "%u\n", parent_index);
@@ -6287,8 +6286,7 @@ qla4xxx_sysfs_ddb_get_param(struct iscsi_bus_flash_session *fnode_sess,
                        parent_type = ISCSI_DISC_PARENT_ISNS;
                else if (fnode_sess->discovery_parent_type == DDB_NO_LINK)
                        parent_type = ISCSI_DISC_PARENT_UNKNOWN;
-               else if (fnode_sess->discovery_parent_type >= 0  &&
-                        fnode_sess->discovery_parent_type < MAX_DDB_ENTRIES)
+               else if (fnode_sess->discovery_parent_type < MAX_DDB_ENTRIES)
                        parent_type = ISCSI_DISC_PARENT_SENDTGT;
                else
                        parent_type = ISCSI_DISC_PARENT_UNKNOWN;
@@ -6349,6 +6347,8 @@ qla4xxx_sysfs_ddb_get_param(struct iscsi_bus_flash_session *fnode_sess,
                rc = -ENOSYS;
                break;
        }
+
+       put_device(dev);
        return rc;
 }
 
@@ -6368,20 +6368,11 @@ qla4xxx_sysfs_ddb_set_param(struct iscsi_bus_flash_session *fnode_sess,
 {
        struct Scsi_Host *shost = iscsi_flash_session_to_shost(fnode_sess);
        struct scsi_qla_host *ha = to_qla_host(shost);
-       struct dev_db_entry *fw_ddb_entry = NULL;
        struct iscsi_flashnode_param_info *fnode_param;
        struct nlattr *attr;
        int rc = QLA_ERROR;
        uint32_t rem = len;
 
-       fw_ddb_entry = kzalloc(sizeof(*fw_ddb_entry), GFP_KERNEL);
-       if (!fw_ddb_entry) {
-               DEBUG2(ql4_printk(KERN_ERR, ha,
-                                 "%s: Unable to allocate ddb buffer\n",
-                                 __func__));
-               return -ENOMEM;
-       }
-
        nla_for_each_attr(attr, data, len, rem) {
                fnode_param = nla_data(attr);
 
@@ -6590,16 +6581,11 @@ static int qla4xxx_sysfs_ddb_delete(struct iscsi_bus_flash_session *fnode_sess)
        struct dev_db_entry *fw_ddb_entry = NULL;
        dma_addr_t fw_ddb_entry_dma;
        uint16_t *ddb_cookie = NULL;
-       size_t ddb_size;
+       size_t ddb_size = 0;
        void *pddb = NULL;
        int target_id;
        int rc = 0;
 
-       if (!fnode_sess) {
-               rc = -EINVAL;
-               goto exit_ddb_del;
-       }
-
        if (fnode_sess->is_boot_target) {
                rc = -EPERM;
                DEBUG2(ql4_printk(KERN_ERR, ha,
@@ -6631,8 +6617,7 @@ static int qla4xxx_sysfs_ddb_delete(struct iscsi_bus_flash_session *fnode_sess)
 
                dev_db_start_offset += (fnode_sess->target_id *
                                       sizeof(*fw_ddb_entry));
-               dev_db_start_offset += (void *)&(fw_ddb_entry->cookie) -
-                                      (void *)fw_ddb_entry;
+               dev_db_start_offset += offsetof(struct dev_db_entry, cookie);
 
                ddb_size = sizeof(*ddb_cookie);
        }
index 83e0fec..fe873cf 100644 (file)
@@ -5,4 +5,4 @@
  * See LICENSE.qla4xxx for copyright and licensing details.
  */
 
-#define QLA4XXX_DRIVER_VERSION "5.03.00-k8"
+#define QLA4XXX_DRIVER_VERSION "5.03.00-k9"
index 5add6f4..0a537a0 100644 (file)
@@ -1997,24 +1997,39 @@ out:
        return ret;
 }
 
-static unsigned int map_state(sector_t lba, unsigned int *num)
+static unsigned long lba_to_map_index(sector_t lba)
+{
+       if (scsi_debug_unmap_alignment) {
+               lba += scsi_debug_unmap_granularity -
+                       scsi_debug_unmap_alignment;
+       }
+       do_div(lba, scsi_debug_unmap_granularity);
+
+       return lba;
+}
+
+static sector_t map_index_to_lba(unsigned long index)
 {
-       unsigned int granularity, alignment, mapped;
-       sector_t block, next, end;
+       return index * scsi_debug_unmap_granularity -
+               scsi_debug_unmap_alignment;
+}
 
-       granularity = scsi_debug_unmap_granularity;
-       alignment = granularity - scsi_debug_unmap_alignment;
-       block = lba + alignment;
-       do_div(block, granularity);
+static unsigned int map_state(sector_t lba, unsigned int *num)
+{
+       sector_t end;
+       unsigned int mapped;
+       unsigned long index;
+       unsigned long next;
 
-       mapped = test_bit(block, map_storep);
+       index = lba_to_map_index(lba);
+       mapped = test_bit(index, map_storep);
 
        if (mapped)
-               next = find_next_zero_bit(map_storep, map_size, block);
+               next = find_next_zero_bit(map_storep, map_size, index);
        else
-               next = find_next_bit(map_storep, map_size, block);
+               next = find_next_bit(map_storep, map_size, index);
 
-       end = next * granularity - scsi_debug_unmap_alignment;
+       end = min_t(sector_t, sdebug_store_sectors,  map_index_to_lba(next));
        *num = end - lba;
 
        return mapped;
@@ -2022,47 +2037,37 @@ static unsigned int map_state(sector_t lba, unsigned int *num)
 
 static void map_region(sector_t lba, unsigned int len)
 {
-       unsigned int granularity, alignment;
        sector_t end = lba + len;
 
-       granularity = scsi_debug_unmap_granularity;
-       alignment = granularity - scsi_debug_unmap_alignment;
-
        while (lba < end) {
-               sector_t block, rem;
-
-               block = lba + alignment;
-               rem = do_div(block, granularity);
+               unsigned long index = lba_to_map_index(lba);
 
-               if (block < map_size)
-                       set_bit(block, map_storep);
+               if (index < map_size)
+                       set_bit(index, map_storep);
 
-               lba += granularity - rem;
+               lba = map_index_to_lba(index + 1);
        }
 }
 
 static void unmap_region(sector_t lba, unsigned int len)
 {
-       unsigned int granularity, alignment;
        sector_t end = lba + len;
 
-       granularity = scsi_debug_unmap_granularity;
-       alignment = granularity - scsi_debug_unmap_alignment;
-
        while (lba < end) {
-               sector_t block, rem;
-
-               block = lba + alignment;
-               rem = do_div(block, granularity);
+               unsigned long index = lba_to_map_index(lba);
 
-               if (rem == 0 && lba + granularity < end && block < map_size) {
-                       clear_bit(block, map_storep);
-                       if (scsi_debug_lbprz)
+               if (lba == map_index_to_lba(index) &&
+                   lba + scsi_debug_unmap_granularity <= end &&
+                   index < map_size) {
+                       clear_bit(index, map_storep);
+                       if (scsi_debug_lbprz) {
                                memset(fake_storep +
-                                      block * scsi_debug_sector_size, 0,
-                                      scsi_debug_sector_size);
+                                      lba * scsi_debug_sector_size, 0,
+                                      scsi_debug_sector_size *
+                                      scsi_debug_unmap_granularity);
+                       }
                }
-               lba += granularity - rem;
+               lba = map_index_to_lba(index + 1);
        }
 }
 
@@ -2089,7 +2094,7 @@ static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba,
 
        write_lock_irqsave(&atomic_rw, iflags);
        ret = do_device_access(SCpnt, devip, lba, num, 1);
-       if (scsi_debug_unmap_granularity)
+       if (scsi_debug_lbp())
                map_region(lba, num);
        write_unlock_irqrestore(&atomic_rw, iflags);
        if (-1 == ret)
@@ -2122,7 +2127,7 @@ static int resp_write_same(struct scsi_cmnd *scmd, unsigned long long lba,
 
        write_lock_irqsave(&atomic_rw, iflags);
 
-       if (unmap && scsi_debug_unmap_granularity) {
+       if (unmap && scsi_debug_lbp()) {
                unmap_region(lba, num);
                goto out;
        }
@@ -2146,7 +2151,7 @@ static int resp_write_same(struct scsi_cmnd *scmd, unsigned long long lba,
                       fake_storep + (lba * scsi_debug_sector_size),
                       scsi_debug_sector_size);
 
-       if (scsi_debug_unmap_granularity)
+       if (scsi_debug_lbp())
                map_region(lba, num);
 out:
        write_unlock_irqrestore(&atomic_rw, iflags);
@@ -3389,8 +3394,6 @@ static int __init scsi_debug_init(void)
 
        /* Logical Block Provisioning */
        if (scsi_debug_lbp()) {
-               unsigned int map_bytes;
-
                scsi_debug_unmap_max_blocks =
                        clamp(scsi_debug_unmap_max_blocks, 0U, 0xffffffffU);
 
@@ -3401,16 +3404,16 @@ static int __init scsi_debug_init(void)
                        clamp(scsi_debug_unmap_granularity, 1U, 0xffffffffU);
 
                if (scsi_debug_unmap_alignment &&
-                   scsi_debug_unmap_granularity < scsi_debug_unmap_alignment) {
+                   scsi_debug_unmap_granularity <=
+                   scsi_debug_unmap_alignment) {
                        printk(KERN_ERR
-                              "%s: ERR: unmap_granularity < unmap_alignment\n",
+                              "%s: ERR: unmap_granularity <= unmap_alignment\n",
                               __func__);
                        return -EINVAL;
                }
 
-               map_size = (sdebug_store_sectors / scsi_debug_unmap_granularity);
-               map_bytes = map_size >> 3;
-               map_storep = vmalloc(map_bytes);
+               map_size = lba_to_map_index(sdebug_store_sectors - 1) + 1;
+               map_storep = vmalloc(BITS_TO_LONGS(map_size) * sizeof(long));
 
                printk(KERN_INFO "scsi_debug_init: %lu provisioning blocks\n",
                       map_size);
@@ -3421,7 +3424,7 @@ static int __init scsi_debug_init(void)
                        goto free_vm;
                }
 
-               memset(map_storep, 0x0, map_bytes);
+               bitmap_zero(map_storep, map_size);
 
                /* Map first 1KB for partition table */
                if (scsi_debug_num_parts)
index c1b05a8..f43de1e 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/interrupt.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
+#include <linux/jiffies.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
@@ -791,32 +792,48 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd,
        struct scsi_device *sdev = scmd->device;
        struct Scsi_Host *shost = sdev->host;
        DECLARE_COMPLETION_ONSTACK(done);
-       unsigned long timeleft;
+       unsigned long timeleft = timeout;
        struct scsi_eh_save ses;
+       const unsigned long stall_for = msecs_to_jiffies(100);
        int rtn;
 
+retry:
        scsi_eh_prep_cmnd(scmd, &ses, cmnd, cmnd_size, sense_bytes);
        shost->eh_action = &done;
 
        scsi_log_send(scmd);
        scmd->scsi_done = scsi_eh_done;
-       shost->hostt->queuecommand(shost, scmd);
-
-       timeleft = wait_for_completion_timeout(&done, timeout);
+       rtn = shost->hostt->queuecommand(shost, scmd);
+       if (rtn) {
+               if (timeleft > stall_for) {
+                       scsi_eh_restore_cmnd(scmd, &ses);
+                       timeleft -= stall_for;
+                       msleep(jiffies_to_msecs(stall_for));
+                       goto retry;
+               }
+               /* signal not to enter either branch of the if () below */
+               timeleft = 0;
+               rtn = NEEDS_RETRY;
+       } else {
+               timeleft = wait_for_completion_timeout(&done, timeout);
+       }
 
        shost->eh_action = NULL;
 
-       scsi_log_completion(scmd, SUCCESS);
+       scsi_log_completion(scmd, rtn);
 
        SCSI_LOG_ERROR_RECOVERY(3,
                printk("%s: scmd: %p, timeleft: %ld\n",
                        __func__, scmd, timeleft));
 
        /*
-        * If there is time left scsi_eh_done got called, and we will
-        * examine the actual status codes to see whether the command
-        * actually did complete normally, else tell the host to forget
-        * about this command.
+        * If there is time left scsi_eh_done got called, and we will examine
+        * the actual status codes to see whether the command actually did
+        * complete normally, else if we have a zero return and no time left,
+        * the command must still be pending, so abort it and return FAILED.
+        * If we never actually managed to issue the command, because
+        * ->queuecommand() kept returning non zero, use the rtn = FAILED
+        * value above (so don't execute either branch of the if)
         */
        if (timeleft) {
                rtn = scsi_eh_completed_normally(scmd);
@@ -837,7 +854,7 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd,
                        rtn = FAILED;
                        break;
                }
-       } else {
+       } else if (!rtn) {
                scsi_abort_eh_cmnd(scmd);
                rtn = FAILED;
        }
index c31187d..86d5220 100644 (file)
@@ -276,11 +276,10 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
 }
 EXPORT_SYMBOL(scsi_execute);
 
-
-int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd,
+int scsi_execute_req_flags(struct scsi_device *sdev, const unsigned char *cmd,
                     int data_direction, void *buffer, unsigned bufflen,
                     struct scsi_sense_hdr *sshdr, int timeout, int retries,
-                    int *resid)
+                    int *resid, int flags)
 {
        char *sense = NULL;
        int result;
@@ -291,14 +290,14 @@ int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd,
                        return DRIVER_ERROR << 24;
        }
        result = scsi_execute(sdev, cmd, data_direction, buffer, bufflen,
-                             sense, timeout, retries, 0, resid);
+                             sense, timeout, retries, flags, resid);
        if (sshdr)
                scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, sshdr);
 
        kfree(sense);
        return result;
 }
-EXPORT_SYMBOL(scsi_execute_req);
+EXPORT_SYMBOL(scsi_execute_req_flags);
 
 /*
  * Function:    scsi_init_cmd_errh()
index 8f6b12c..42539ee 100644 (file)
@@ -144,33 +144,83 @@ static int scsi_bus_restore(struct device *dev)
 
 #ifdef CONFIG_PM_RUNTIME
 
+static int sdev_blk_runtime_suspend(struct scsi_device *sdev,
+                                       int (*cb)(struct device *))
+{
+       int err;
+
+       err = blk_pre_runtime_suspend(sdev->request_queue);
+       if (err)
+               return err;
+       if (cb)
+               err = cb(&sdev->sdev_gendev);
+       blk_post_runtime_suspend(sdev->request_queue, err);
+
+       return err;
+}
+
+static int sdev_runtime_suspend(struct device *dev)
+{
+       const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+       int (*cb)(struct device *) = pm ? pm->runtime_suspend : NULL;
+       struct scsi_device *sdev = to_scsi_device(dev);
+       int err;
+
+       if (sdev->request_queue->dev)
+               return sdev_blk_runtime_suspend(sdev, cb);
+
+       err = scsi_dev_type_suspend(dev, cb);
+       if (err == -EAGAIN)
+               pm_schedule_suspend(dev, jiffies_to_msecs(
+                                       round_jiffies_up_relative(HZ/10)));
+       return err;
+}
+
 static int scsi_runtime_suspend(struct device *dev)
 {
        int err = 0;
-       const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
 
        dev_dbg(dev, "scsi_runtime_suspend\n");
-       if (scsi_is_sdev_device(dev)) {
-               err = scsi_dev_type_suspend(dev,
-                               pm ? pm->runtime_suspend : NULL);
-               if (err == -EAGAIN)
-                       pm_schedule_suspend(dev, jiffies_to_msecs(
-                               round_jiffies_up_relative(HZ/10)));
-       }
+       if (scsi_is_sdev_device(dev))
+               err = sdev_runtime_suspend(dev);
 
        /* Insert hooks here for targets, hosts, and transport classes */
 
        return err;
 }
 
-static int scsi_runtime_resume(struct device *dev)
+static int sdev_blk_runtime_resume(struct scsi_device *sdev,
+                                       int (*cb)(struct device *))
 {
        int err = 0;
+
+       blk_pre_runtime_resume(sdev->request_queue);
+       if (cb)
+               err = cb(&sdev->sdev_gendev);
+       blk_post_runtime_resume(sdev->request_queue, err);
+
+       return err;
+}
+
+static int sdev_runtime_resume(struct device *dev)
+{
+       struct scsi_device *sdev = to_scsi_device(dev);
        const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+       int (*cb)(struct device *) = pm ? pm->runtime_resume : NULL;
+
+       if (sdev->request_queue->dev)
+               return sdev_blk_runtime_resume(sdev, cb);
+       else
+               return scsi_dev_type_resume(dev, cb);
+}
+
+static int scsi_runtime_resume(struct device *dev)
+{
+       int err = 0;
 
        dev_dbg(dev, "scsi_runtime_resume\n");
        if (scsi_is_sdev_device(dev))
-               err = scsi_dev_type_resume(dev, pm ? pm->runtime_resume : NULL);
+               err = sdev_runtime_resume(dev);
 
        /* Insert hooks here for targets, hosts, and transport classes */
 
@@ -185,10 +235,18 @@ static int scsi_runtime_idle(struct device *dev)
 
        /* Insert hooks here for targets, hosts, and transport classes */
 
-       if (scsi_is_sdev_device(dev))
-               err = pm_schedule_suspend(dev, 100);
-       else
+       if (scsi_is_sdev_device(dev)) {
+               struct scsi_device *sdev = to_scsi_device(dev);
+
+               if (sdev->request_queue->dev) {
+                       pm_runtime_mark_last_busy(dev);
+                       err = pm_runtime_autosuspend(dev);
+               } else {
+                       err = pm_runtime_suspend(dev);
+               }
+       } else {
                err = pm_runtime_suspend(dev);
+       }
        return err;
 }
 
index db66357..86f0c5d 100644 (file)
@@ -84,6 +84,7 @@ static int proc_scsi_host_open(struct inode *inode, struct file *file)
 
 static const struct file_operations proc_scsi_fops = {
        .open = proc_scsi_host_open,
+       .release = single_release,
        .read = seq_read,
        .llseek = seq_lseek,
        .write = proc_scsi_host_write
index 47799a3..133926b 100644 (file)
@@ -1019,8 +1019,7 @@ exit_match_index:
 /**
  * iscsi_get_flashnode_by_index -finds flashnode session entry by index
  * @shost: pointer to host data
- * @data: pointer to data containing value to use for comparison
- * @fn: function pointer that does actual comparison
+ * @idx: index to match
  *
  * Finds the flashnode session object for the passed index
  *
@@ -1029,13 +1028,13 @@ exit_match_index:
  *  %NULL on failure
  */
 static struct iscsi_bus_flash_session *
-iscsi_get_flashnode_by_index(struct Scsi_Host *shost, void *data,
-                            int (*fn)(struct device *dev, void *data))
+iscsi_get_flashnode_by_index(struct Scsi_Host *shost, uint32_t idx)
 {
        struct iscsi_bus_flash_session *fnode_sess = NULL;
        struct device *dev;
 
-       dev = device_find_child(&shost->shost_gendev, data, fn);
+       dev = device_find_child(&shost->shost_gendev, &idx,
+                               flashnode_match_index);
        if (dev)
                fnode_sess = iscsi_dev_to_flash_session(dev);
 
@@ -1059,18 +1058,13 @@ struct device *
 iscsi_find_flashnode_sess(struct Scsi_Host *shost, void *data,
                          int (*fn)(struct device *dev, void *data))
 {
-       struct device *dev;
-
-       dev = device_find_child(&shost->shost_gendev, data, fn);
-       return dev;
+       return device_find_child(&shost->shost_gendev, data, fn);
 }
 EXPORT_SYMBOL_GPL(iscsi_find_flashnode_sess);
 
 /**
  * iscsi_find_flashnode_conn - finds flashnode connection entry
  * @fnode_sess: pointer to parent flashnode session entry
- * @data: pointer to data containing value to use for comparison
- * @fn: function pointer that does actual comparison
  *
  * Finds the flashnode connection object comparing the data passed using logic
  * defined in passed function pointer
@@ -1080,14 +1074,10 @@ EXPORT_SYMBOL_GPL(iscsi_find_flashnode_sess);
  *  %NULL on failure
  */
 struct device *
-iscsi_find_flashnode_conn(struct iscsi_bus_flash_session *fnode_sess,
-                         void *data,
-                         int (*fn)(struct device *dev, void *data))
+iscsi_find_flashnode_conn(struct iscsi_bus_flash_session *fnode_sess)
 {
-       struct device *dev;
-
-       dev = device_find_child(&fnode_sess->dev, data, fn);
-       return dev;
+       return device_find_child(&fnode_sess->dev, NULL,
+                                iscsi_is_flashnode_conn_dev);
 }
 EXPORT_SYMBOL_GPL(iscsi_find_flashnode_conn);
 
@@ -2808,7 +2798,7 @@ static int iscsi_set_flashnode_param(struct iscsi_transport *transport,
        struct iscsi_bus_flash_session *fnode_sess;
        struct iscsi_bus_flash_conn *fnode_conn;
        struct device *dev;
-       uint32_t *idx;
+       uint32_t idx;
        int err = 0;
 
        if (!transport->set_flashnode_param) {
@@ -2824,25 +2814,27 @@ static int iscsi_set_flashnode_param(struct iscsi_transport *transport,
                goto put_host;
        }
 
-       idx = &ev->u.set_flashnode.flashnode_idx;
-       fnode_sess = iscsi_get_flashnode_by_index(shost, idx,
-                                                 flashnode_match_index);
+       idx = ev->u.set_flashnode.flashnode_idx;
+       fnode_sess = iscsi_get_flashnode_by_index(shost, idx);
        if (!fnode_sess) {
                pr_err("%s could not find flashnode %u for host no %u\n",
-                      __func__, *idx, ev->u.set_flashnode.host_no);
+                      __func__, idx, ev->u.set_flashnode.host_no);
                err = -ENODEV;
                goto put_host;
        }
 
-       dev = iscsi_find_flashnode_conn(fnode_sess, NULL,
-                                       iscsi_is_flashnode_conn_dev);
+       dev = iscsi_find_flashnode_conn(fnode_sess);
        if (!dev) {
                err = -ENODEV;
-               goto put_host;
+               goto put_sess;
        }
 
        fnode_conn = iscsi_dev_to_flash_conn(dev);
        err = transport->set_flashnode_param(fnode_sess, fnode_conn, data, len);
+       put_device(dev);
+
+put_sess:
+       put_device(&fnode_sess->dev);
 
 put_host:
        scsi_host_put(shost);
@@ -2891,7 +2883,7 @@ static int iscsi_del_flashnode(struct iscsi_transport *transport,
 {
        struct Scsi_Host *shost;
        struct iscsi_bus_flash_session *fnode_sess;
-       uint32_t *idx;
+       uint32_t idx;
        int err = 0;
 
        if (!transport->del_flashnode) {
@@ -2907,17 +2899,17 @@ static int iscsi_del_flashnode(struct iscsi_transport *transport,
                goto put_host;
        }
 
-       idx = &ev->u.del_flashnode.flashnode_idx;
-       fnode_sess = iscsi_get_flashnode_by_index(shost, idx,
-                                                 flashnode_match_index);
+       idx = ev->u.del_flashnode.flashnode_idx;
+       fnode_sess = iscsi_get_flashnode_by_index(shost, idx);
        if (!fnode_sess) {
                pr_err("%s could not find flashnode %u for host no %u\n",
-                      __func__, *idx, ev->u.del_flashnode.host_no);
+                      __func__, idx, ev->u.del_flashnode.host_no);
                err = -ENODEV;
                goto put_host;
        }
 
        err = transport->del_flashnode(fnode_sess);
+       put_device(&fnode_sess->dev);
 
 put_host:
        scsi_host_put(shost);
@@ -2933,7 +2925,7 @@ static int iscsi_login_flashnode(struct iscsi_transport *transport,
        struct iscsi_bus_flash_session *fnode_sess;
        struct iscsi_bus_flash_conn *fnode_conn;
        struct device *dev;
-       uint32_t *idx;
+       uint32_t idx;
        int err = 0;
 
        if (!transport->login_flashnode) {
@@ -2949,25 +2941,27 @@ static int iscsi_login_flashnode(struct iscsi_transport *transport,
                goto put_host;
        }
 
-       idx = &ev->u.login_flashnode.flashnode_idx;
-       fnode_sess = iscsi_get_flashnode_by_index(shost, idx,
-                                                 flashnode_match_index);
+       idx = ev->u.login_flashnode.flashnode_idx;
+       fnode_sess = iscsi_get_flashnode_by_index(shost, idx);
        if (!fnode_sess) {
                pr_err("%s could not find flashnode %u for host no %u\n",
-                      __func__, *idx, ev->u.login_flashnode.host_no);
+                      __func__, idx, ev->u.login_flashnode.host_no);
                err = -ENODEV;
                goto put_host;
        }
 
-       dev = iscsi_find_flashnode_conn(fnode_sess, NULL,
-                                       iscsi_is_flashnode_conn_dev);
+       dev = iscsi_find_flashnode_conn(fnode_sess);
        if (!dev) {
                err = -ENODEV;
-               goto put_host;
+               goto put_sess;
        }
 
        fnode_conn = iscsi_dev_to_flash_conn(dev);
        err = transport->login_flashnode(fnode_sess, fnode_conn);
+       put_device(dev);
+
+put_sess:
+       put_device(&fnode_sess->dev);
 
 put_host:
        scsi_host_put(shost);
@@ -2983,7 +2977,7 @@ static int iscsi_logout_flashnode(struct iscsi_transport *transport,
        struct iscsi_bus_flash_session *fnode_sess;
        struct iscsi_bus_flash_conn *fnode_conn;
        struct device *dev;
-       uint32_t *idx;
+       uint32_t idx;
        int err = 0;
 
        if (!transport->logout_flashnode) {
@@ -2999,26 +2993,28 @@ static int iscsi_logout_flashnode(struct iscsi_transport *transport,
                goto put_host;
        }
 
-       idx = &ev->u.logout_flashnode.flashnode_idx;
-       fnode_sess = iscsi_get_flashnode_by_index(shost, idx,
-                                                 flashnode_match_index);
+       idx = ev->u.logout_flashnode.flashnode_idx;
+       fnode_sess = iscsi_get_flashnode_by_index(shost, idx);
        if (!fnode_sess) {
                pr_err("%s could not find flashnode %u for host no %u\n",
-                      __func__, *idx, ev->u.logout_flashnode.host_no);
+                      __func__, idx, ev->u.logout_flashnode.host_no);
                err = -ENODEV;
                goto put_host;
        }
 
-       dev = iscsi_find_flashnode_conn(fnode_sess, NULL,
-                                       iscsi_is_flashnode_conn_dev);
+       dev = iscsi_find_flashnode_conn(fnode_sess);
        if (!dev) {
                err = -ENODEV;
-               goto put_host;
+               goto put_sess;
        }
 
        fnode_conn = iscsi_dev_to_flash_conn(dev);
 
        err = transport->logout_flashnode(fnode_sess, fnode_conn);
+       put_device(dev);
+
+put_sess:
+       put_device(&fnode_sess->dev);
 
 put_host:
        scsi_host_put(shost);
@@ -3985,8 +3981,10 @@ static __init int iscsi_transport_init(void)
        }
 
        iscsi_eh_timer_workq = create_singlethread_workqueue("iscsi_eh");
-       if (!iscsi_eh_timer_workq)
+       if (!iscsi_eh_timer_workq) {
+               err = -ENOMEM;
                goto release_nls;
+       }
 
        return 0;
 
index e668977..c1c5552 100644 (file)
@@ -142,6 +142,7 @@ sd_store_cache_type(struct device *dev, struct device_attribute *attr,
        char *buffer_data;
        struct scsi_mode_data data;
        struct scsi_sense_hdr sshdr;
+       const char *temp = "temporary ";
        int len;
 
        if (sdp->type != TYPE_DISK)
@@ -150,6 +151,13 @@ sd_store_cache_type(struct device *dev, struct device_attribute *attr,
                 * it's not worth the risk */
                return -EINVAL;
 
+       if (strncmp(buf, temp, sizeof(temp) - 1) == 0) {
+               buf += sizeof(temp) - 1;
+               sdkp->cache_override = 1;
+       } else {
+               sdkp->cache_override = 0;
+       }
+
        for (i = 0; i < ARRAY_SIZE(sd_cache_types); i++) {
                len = strlen(sd_cache_types[i]);
                if (strncmp(sd_cache_types[i], buf, len) == 0 &&
@@ -162,6 +170,13 @@ sd_store_cache_type(struct device *dev, struct device_attribute *attr,
                return -EINVAL;
        rcd = ct & 0x01 ? 1 : 0;
        wce = ct & 0x02 ? 1 : 0;
+
+       if (sdkp->cache_override) {
+               sdkp->WCE = wce;
+               sdkp->RCD = rcd;
+               return count;
+       }
+
        if (scsi_mode_sense(sdp, 0x08, 8, buffer, sizeof(buffer), SD_TIMEOUT,
                            SD_MAX_RETRIES, &data, NULL))
                return -EINVAL;
@@ -1121,10 +1136,6 @@ static int sd_open(struct block_device *bdev, fmode_t mode)
 
        sdev = sdkp->device;
 
-       retval = scsi_autopm_get_device(sdev);
-       if (retval)
-               goto error_autopm;
-
        /*
         * If the device is in error recovery, wait until it is done.
         * If the device is offline, then disallow any access to it.
@@ -1169,8 +1180,6 @@ static int sd_open(struct block_device *bdev, fmode_t mode)
        return 0;
 
 error_out:
-       scsi_autopm_put_device(sdev);
-error_autopm:
        scsi_disk_put(sdkp);
        return retval;  
 }
@@ -1205,7 +1214,6 @@ static void sd_release(struct gendisk *disk, fmode_t mode)
         * XXX is followed by a "rmmod sd_mod"?
         */
 
-       scsi_autopm_put_device(sdev);
        scsi_disk_put(sdkp);
 }
 
@@ -1366,14 +1374,9 @@ static unsigned int sd_check_events(struct gendisk *disk, unsigned int clearing)
        retval = -ENODEV;
 
        if (scsi_block_when_processing_errors(sdp)) {
-               retval = scsi_autopm_get_device(sdp);
-               if (retval)
-                       goto out;
-
                sshdr  = kzalloc(sizeof(*sshdr), GFP_KERNEL);
                retval = scsi_test_unit_ready(sdp, SD_TIMEOUT, SD_MAX_RETRIES,
                                              sshdr);
-               scsi_autopm_put_device(sdp);
        }
 
        /* failed to execute TUR, assume media not present */
@@ -1423,8 +1426,9 @@ static int sd_sync_cache(struct scsi_disk *sdkp)
                 * Leave the rest of the command zero to indicate
                 * flush everything.
                 */
-               res = scsi_execute_req(sdp, cmd, DMA_NONE, NULL, 0, &sshdr,
-                                      SD_FLUSH_TIMEOUT, SD_MAX_RETRIES, NULL);
+               res = scsi_execute_req_flags(sdp, cmd, DMA_NONE, NULL, 0,
+                                            &sshdr, SD_FLUSH_TIMEOUT,
+                                            SD_MAX_RETRIES, NULL, REQ_PM);
                if (res == 0)
                        break;
        }
@@ -2318,6 +2322,10 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer)
        int old_rcd = sdkp->RCD;
        int old_dpofua = sdkp->DPOFUA;
 
+
+       if (sdkp->cache_override)
+               return;
+
        first_len = 4;
        if (sdp->skip_ms_page_8) {
                if (sdp->type == TYPE_RBC)
@@ -2811,6 +2819,7 @@ static void sd_probe_async(void *data, async_cookie_t cookie)
        sdkp->capacity = 0;
        sdkp->media_present = 1;
        sdkp->write_prot = 0;
+       sdkp->cache_override = 0;
        sdkp->WCE = 0;
        sdkp->RCD = 0;
        sdkp->ATO = 0;
@@ -2837,6 +2846,7 @@ static void sd_probe_async(void *data, async_cookie_t cookie)
 
        sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n",
                  sdp->removable ? "removable " : "");
+       blk_pm_runtime_init(sdp->request_queue, dev);
        scsi_autopm_put_device(sdp);
        put_device(&sdkp->dev);
 }
@@ -3020,8 +3030,8 @@ static int sd_start_stop_device(struct scsi_disk *sdkp, int start)
        if (!scsi_device_online(sdp))
                return -ENODEV;
 
-       res = scsi_execute_req(sdp, cmd, DMA_NONE, NULL, 0, &sshdr,
-                              SD_TIMEOUT, SD_MAX_RETRIES, NULL);
+       res = scsi_execute_req_flags(sdp, cmd, DMA_NONE, NULL, 0, &sshdr,
+                              SD_TIMEOUT, SD_MAX_RETRIES, NULL, REQ_PM);
        if (res) {
                sd_printk(KERN_WARNING, sdkp, "START_STOP FAILED\n");
                sd_print_result(sdkp, res);
index 74a1e4c..2386aeb 100644 (file)
@@ -73,6 +73,7 @@ struct scsi_disk {
        u8              protection_type;/* Data Integrity Field */
        u8              provisioning_mode;
        unsigned        ATO : 1;        /* state of disk ATO bit */
+       unsigned        cache_override : 1; /* temp override of WCE,RCD */
        unsigned        WCE : 1;        /* state of disk WCE bit */
        unsigned        RCD : 1;        /* state of disk RCD bit, unused */
        unsigned        DPOFUA : 1;     /* state of disk DPOFUA bit */
index 04998f3..6174ca4 100644 (file)
@@ -93,14 +93,6 @@ static int sd_dif_type1_verify(struct blk_integrity_exchg *bix, csum_fn *fn)
                if (sdt->app_tag == 0xffff)
                        return 0;
 
-               /* Bad ref tag received from disk */
-               if (sdt->ref_tag == 0xffffffff) {
-                       printk(KERN_ERR
-                              "%s: bad phys ref tag on sector %lu\n",
-                              bix->disk_name, (unsigned long)sector);
-                       return -EIO;
-               }
-
                if (be32_to_cpu(sdt->ref_tag) != (sector & 0xffffffff)) {
                        printk(KERN_ERR
                               "%s: ref tag error on sector %lu (rcvd %u)\n",
index 0371047..35faf24 100644 (file)
@@ -57,3 +57,14 @@ config SCSI_UFSHCD_PCI
          If you have a controller with this interface, say Y or M here.
 
          If unsure, say N.
+
+config SCSI_UFSHCD_PLATFORM
+       tristate "Platform bus based UFS Controller support"
+       depends on SCSI_UFSHCD
+       ---help---
+       This selects the UFS host controller support. Select this if
+       you have an UFS controller on Platform bus.
+
+       If you have a controller with this interface, say Y or M here.
+
+         If unsure, say N.
index 9eda0df..1e5bd48 100644 (file)
@@ -1,3 +1,4 @@
 # UFSHCD makefile
 obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o
 obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
+obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o
diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c b/drivers/scsi/ufs/ufshcd-pltfrm.c
new file mode 100644 (file)
index 0000000..03319ac
--- /dev/null
@@ -0,0 +1,217 @@
+/*
+ * Universal Flash Storage Host controller Platform bus based glue driver
+ *
+ * This code is based on drivers/scsi/ufs/ufshcd-pltfrm.c
+ * Copyright (C) 2011-2013 Samsung India Software Operations
+ *
+ * Authors:
+ *     Santosh Yaraganavi <santosh.sy@samsung.com>
+ *     Vinayak Holikatti <h.vinayak@samsung.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.
+ * See the COPYING file in the top-level directory or visit
+ * <http://www.gnu.org/licenses/gpl-2.0.html>
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This program is provided "AS IS" and "WITH ALL FAULTS" and
+ * without warranty of any kind. You are solely responsible for
+ * determining the appropriateness of using and distributing
+ * the program and assume all risks associated with your exercise
+ * of rights with respect to the program, including but not limited
+ * to infringement of third party rights, the risks and costs of
+ * program errors, damage to or loss of data, programs or equipment,
+ * and unavailability or interruption of operations. Under no
+ * circumstances will the contributor of this Program be liable for
+ * any damages of any kind arising from your use or distribution of
+ * this program.
+ */
+
+#include "ufshcd.h"
+#include <linux/platform_device.h>
+
+#ifdef CONFIG_PM
+/**
+ * ufshcd_pltfrm_suspend - suspend power management function
+ * @dev: pointer to device handle
+ *
+ *
+ * Returns 0
+ */
+static int ufshcd_pltfrm_suspend(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct ufs_hba *hba =  platform_get_drvdata(pdev);
+
+       /*
+        * TODO:
+        * 1. Call ufshcd_suspend
+        * 2. Do bus specific power management
+        */
+
+       disable_irq(hba->irq);
+
+       return 0;
+}
+
+/**
+ * ufshcd_pltfrm_resume - resume power management function
+ * @dev: pointer to device handle
+ *
+ * Returns 0
+ */
+static int ufshcd_pltfrm_resume(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct ufs_hba *hba =  platform_get_drvdata(pdev);
+
+       /*
+        * TODO:
+        * 1. Call ufshcd_resume.
+        * 2. Do bus specific wake up
+        */
+
+       enable_irq(hba->irq);
+
+       return 0;
+}
+#else
+#define ufshcd_pltfrm_suspend  NULL
+#define ufshcd_pltfrm_resume   NULL
+#endif
+
+/**
+ * ufshcd_pltfrm_probe - probe routine of the driver
+ * @pdev: pointer to Platform device handle
+ *
+ * Returns 0 on success, non-zero value on failure
+ */
+static int ufshcd_pltfrm_probe(struct platform_device *pdev)
+{
+       struct ufs_hba *hba;
+       void __iomem *mmio_base;
+       struct resource *mem_res;
+       struct resource *irq_res;
+       resource_size_t mem_size;
+       int err;
+       struct device *dev = &pdev->dev;
+
+       mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!mem_res) {
+               dev_err(&pdev->dev,
+                       "Memory resource not available\n");
+               err = -ENODEV;
+               goto out_error;
+       }
+
+       mem_size = resource_size(mem_res);
+       if (!request_mem_region(mem_res->start, mem_size, "ufshcd")) {
+               dev_err(&pdev->dev,
+                       "Cannot reserve the memory resource\n");
+               err = -EBUSY;
+               goto out_error;
+       }
+
+       mmio_base = ioremap_nocache(mem_res->start, mem_size);
+       if (!mmio_base) {
+               dev_err(&pdev->dev, "memory map failed\n");
+               err = -ENOMEM;
+               goto out_release_regions;
+       }
+
+       irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (!irq_res) {
+               dev_err(&pdev->dev, "IRQ resource not available\n");
+               err = -ENODEV;
+               goto out_iounmap;
+       }
+
+       err = dma_set_coherent_mask(dev, dev->coherent_dma_mask);
+       if (err) {
+               dev_err(&pdev->dev, "set dma mask failed\n");
+               goto out_iounmap;
+       }
+
+       err = ufshcd_init(&pdev->dev, &hba, mmio_base, irq_res->start);
+       if (err) {
+               dev_err(&pdev->dev, "Intialization failed\n");
+               goto out_iounmap;
+       }
+
+       platform_set_drvdata(pdev, hba);
+
+       return 0;
+
+out_iounmap:
+       iounmap(mmio_base);
+out_release_regions:
+       release_mem_region(mem_res->start, mem_size);
+out_error:
+       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 resource *mem_res;
+       resource_size_t mem_size;
+       struct ufs_hba *hba =  platform_get_drvdata(pdev);
+
+       disable_irq(hba->irq);
+
+       /* Some buggy controllers raise interrupt after
+        * the resources are removed. So first we unregister the
+        * irq handler and then the resources used by driver
+        */
+
+       free_irq(hba->irq, hba);
+       ufshcd_remove(hba);
+       mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!mem_res)
+               dev_err(&pdev->dev, "ufshcd: Memory resource not available\n");
+       else {
+               mem_size = resource_size(mem_res);
+               release_mem_region(mem_res->start, mem_size);
+       }
+       platform_set_drvdata(pdev, NULL);
+       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,
+};
+
+static struct platform_driver ufshcd_pltfrm_driver = {
+       .probe  = ufshcd_pltfrm_probe,
+       .remove = ufshcd_pltfrm_remove,
+       .driver = {
+               .name   = "ufshcd",
+               .owner  = THIS_MODULE,
+               .pm     = &ufshcd_dev_pm_ops,
+               .of_match_table = ufs_of_match,
+       },
+};
+
+module_platform_driver(ufshcd_pltfrm_driver);
+
+MODULE_AUTHOR("Santosh Yaragnavi <santosh.sy@samsung.com>");
+MODULE_AUTHOR("Vinayak Holikatti <h.vinayak@samsung.com>");
+MODULE_DESCRIPTION("UFS host controller Pltform bus based glue driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(UFSHCD_DRIVER_VERSION);
index 60fd40c..c32a478 100644 (file)
@@ -478,7 +478,7 @@ static void ufshcd_compose_upiu(struct ufshcd_lrb *lrbp)
                ucd_cmd_ptr->header.dword_2 = 0;
 
                ucd_cmd_ptr->exp_data_transfer_len =
-                       cpu_to_be32(lrbp->cmd->transfersize);
+                       cpu_to_be32(lrbp->cmd->sdb.length);
 
                memcpy(ucd_cmd_ptr->cdb,
                       lrbp->cmd->cmnd,
index 787bd2c..380387a 100644 (file)
@@ -526,13 +526,17 @@ static void atmel_spi_next_xfer_pio(struct spi_master *master,
        }
 
        if (xfer->tx_buf)
-               spi_writel(as, TDR, *(u8 *)(xfer->tx_buf));
+               if (xfer->bits_per_word > 8)
+                       spi_writel(as, TDR, *(u16 *)(xfer->tx_buf));
+               else
+                       spi_writel(as, TDR, *(u8 *)(xfer->tx_buf));
        else
                spi_writel(as, TDR, 0);
 
        dev_dbg(master->dev.parent,
-               "  start pio xfer %p: len %u tx %p rx %p\n",
-               xfer, xfer->len, xfer->tx_buf, xfer->rx_buf);
+               "  start pio xfer %p: len %u tx %p rx %p bitpw %d\n",
+               xfer, xfer->len, xfer->tx_buf, xfer->rx_buf,
+               xfer->bits_per_word);
 
        /* Enable relevant interrupts */
        spi_writel(as, IER, SPI_BIT(RDRF) | SPI_BIT(OVRES));
@@ -950,21 +954,39 @@ atmel_spi_pump_pio_data(struct atmel_spi *as, struct spi_transfer *xfer)
 {
        u8              *txp;
        u8              *rxp;
+       u16             *txp16;
+       u16             *rxp16;
        unsigned long   xfer_pos = xfer->len - as->current_remaining_bytes;
 
        if (xfer->rx_buf) {
-               rxp = ((u8 *)xfer->rx_buf) + xfer_pos;
-               *rxp = spi_readl(as, RDR);
+               if (xfer->bits_per_word > 8) {
+                       rxp16 = (u16 *)(((u8 *)xfer->rx_buf) + xfer_pos);
+                       *rxp16 = spi_readl(as, RDR);
+               } else {
+                       rxp = ((u8 *)xfer->rx_buf) + xfer_pos;
+                       *rxp = spi_readl(as, RDR);
+               }
        } else {
                spi_readl(as, RDR);
        }
-
-       as->current_remaining_bytes--;
+       if (xfer->bits_per_word > 8) {
+               as->current_remaining_bytes -= 2;
+               if (as->current_remaining_bytes < 0)
+                       as->current_remaining_bytes = 0;
+       } else {
+               as->current_remaining_bytes--;
+       }
 
        if (as->current_remaining_bytes) {
                if (xfer->tx_buf) {
-                       txp = ((u8 *)xfer->tx_buf) + xfer_pos + 1;
-                       spi_writel(as, TDR, *txp);
+                       if (xfer->bits_per_word > 8) {
+                               txp16 = (u16 *)(((u8 *)xfer->tx_buf)
+                                                       + xfer_pos + 2);
+                               spi_writel(as, TDR, *txp16);
+                       } else {
+                               txp = ((u8 *)xfer->tx_buf) + xfer_pos + 1;
+                               spi_writel(as, TDR, *txp);
+                       }
                } else {
                        spi_writel(as, TDR, 0);
                }
@@ -1378,9 +1400,16 @@ static int atmel_spi_transfer(struct spi_device *spi, struct spi_message *msg)
                        }
                }
 
+               if (xfer->bits_per_word > 8) {
+                       if (xfer->len % 2) {
+                               dev_dbg(&spi->dev, "buffer len should be 16 bits aligned\n");
+                               return -EINVAL;
+                       }
+               }
+
                /* FIXME implement these protocol options!! */
-               if (xfer->speed_hz) {
-                       dev_dbg(&spi->dev, "no protocol options yet\n");
+               if (xfer->speed_hz < spi->max_speed_hz) {
+                       dev_dbg(&spi->dev, "can't change speed in transfer\n");
                        return -ENOPROTOOPT;
                }
 
index 2e8f24a..50b13c9 100644 (file)
@@ -784,7 +784,7 @@ static const struct of_device_id davinci_spi_of_match[] = {
        },
        { },
 };
-MODULE_DEVICE_TABLE(of, davini_spi_of_match);
+MODULE_DEVICE_TABLE(of, davinci_spi_of_match);
 
 /**
  * spi_davinci_get_pdata - Get platform data from DTS binding
index 60cfae5..eab593e 100644 (file)
@@ -89,7 +89,7 @@ static int hspi_status_check_timeout(struct hspi_priv *hspi, u32 mask, u32 val)
                if ((mask & hspi_read(hspi, SPSR)) == val)
                        return 0;
 
-               msleep(20);
+               udelay(10);
        }
 
        dev_err(hspi->dev, "timeout\n");
index d65c000..09df8e2 100644 (file)
@@ -489,11 +489,6 @@ static int tegra_sflash_probe(struct platform_device *pdev)
        tegra_sflash_parse_dt(tsd);
 
        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!r) {
-               dev_err(&pdev->dev, "No IO memory resource\n");
-               ret = -ENODEV;
-               goto exit_free_master;
-       }
        tsd->base = devm_ioremap_resource(&pdev->dev, r);
        if (IS_ERR(tsd->base)) {
                ret = PTR_ERR(tsd->base);
index 35f60bd..637d728 100644 (file)
@@ -1487,7 +1487,7 @@ static int pch_spi_pd_probe(struct platform_device *plat_dev)
        return 0;
 
 err_spi_register_master:
-       free_irq(board_dat->pdev->irq, board_dat);
+       free_irq(board_dat->pdev->irq, data);
 err_request_irq:
        pch_spi_free_resources(board_dat, data);
 err_spi_get_resources:
@@ -1667,6 +1667,7 @@ static int pch_spi_probe(struct pci_dev *pdev,
                pd_dev = platform_device_alloc("pch-spi", i);
                if (!pd_dev) {
                        dev_err(&pdev->dev, "platform_device_alloc failed\n");
+                       retval = -ENOMEM;
                        goto err_platform_device;
                }
                pd_dev_save->pd_save[i] = pd_dev;
index e1d7696..34d18dc 100644 (file)
@@ -267,7 +267,6 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
 {
        struct xilinx_spi *xspi = spi_master_get_devdata(spi->master);
        u32 ipif_ier;
-       u16 cr;
 
        /* We get here with transmitter inhibited */
 
@@ -276,7 +275,6 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
        xspi->remaining_bytes = t->len;
        INIT_COMPLETION(xspi->done);
 
-       xilinx_spi_fill_tx_fifo(xspi);
 
        /* Enable the transmit empty interrupt, which we use to determine
         * progress on the transmission.
@@ -285,12 +283,41 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
        xspi->write_fn(ipif_ier | XSPI_INTR_TX_EMPTY,
                xspi->regs + XIPIF_V123B_IIER_OFFSET);
 
-       /* Start the transfer by not inhibiting the transmitter any longer */
-       cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET) &
-               ~XSPI_CR_TRANS_INHIBIT;
-       xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET);
+       for (;;) {
+               u16 cr;
+               u8 sr;
+
+               xilinx_spi_fill_tx_fifo(xspi);
+
+               /* Start the transfer by not inhibiting the transmitter any
+                * longer
+                */
+               cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET) &
+                                                       ~XSPI_CR_TRANS_INHIBIT;
+               xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET);
+
+               wait_for_completion(&xspi->done);
+
+               /* A transmit has just completed. Process received data and
+                * check for more data to transmit. Always inhibit the
+                * transmitter while the Isr refills the transmit register/FIFO,
+                * or make sure it is stopped if we're done.
+                */
+               cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET);
+               xspi->write_fn(cr | XSPI_CR_TRANS_INHIBIT,
+                              xspi->regs + XSPI_CR_OFFSET);
+
+               /* Read out all the data from the Rx FIFO */
+               sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET);
+               while ((sr & XSPI_SR_RX_EMPTY_MASK) == 0) {
+                       xspi->rx_fn(xspi);
+                       sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET);
+               }
 
-       wait_for_completion(&xspi->done);
+               /* See if there is more data to send */
+               if (!xspi->remaining_bytes > 0)
+                       break;
+       }
 
        /* Disable the transmit empty interrupt */
        xspi->write_fn(ipif_ier, xspi->regs + XIPIF_V123B_IIER_OFFSET);
@@ -314,38 +341,7 @@ static irqreturn_t xilinx_spi_irq(int irq, void *dev_id)
        xspi->write_fn(ipif_isr, xspi->regs + XIPIF_V123B_IISR_OFFSET);
 
        if (ipif_isr & XSPI_INTR_TX_EMPTY) {    /* Transmission completed */
-               u16 cr;
-               u8 sr;
-
-               /* A transmit has just completed. Process received data and
-                * check for more data to transmit. Always inhibit the
-                * transmitter while the Isr refills the transmit register/FIFO,
-                * or make sure it is stopped if we're done.
-                */
-               cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET);
-               xspi->write_fn(cr | XSPI_CR_TRANS_INHIBIT,
-                       xspi->regs + XSPI_CR_OFFSET);
-
-               /* Read out all the data from the Rx FIFO */
-               sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET);
-               while ((sr & XSPI_SR_RX_EMPTY_MASK) == 0) {
-                       xspi->rx_fn(xspi);
-                       sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET);
-               }
-
-               /* See if there is more data to send */
-               if (xspi->remaining_bytes > 0) {
-                       xilinx_spi_fill_tx_fifo(xspi);
-                       /* Start the transfer by not inhibiting the
-                        * transmitter any longer
-                        */
-                       xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET);
-               } else {
-                       /* No more data to send.
-                        * Indicate the transfer is completed.
-                        */
-                       complete(&xspi->done);
-               }
+               complete(&xspi->done);
        }
 
        return IRQ_HANDLED;
index 163fd80..32b7bb1 100644 (file)
@@ -334,7 +334,7 @@ struct spi_device *spi_alloc_device(struct spi_master *master)
        spi->dev.parent = &master->dev;
        spi->dev.bus = &spi_bus_type;
        spi->dev.release = spidev_release;
-       spi->cs_gpio = -EINVAL;
+       spi->cs_gpio = -ENOENT;
        device_initialize(&spi->dev);
        return spi;
 }
@@ -1067,8 +1067,11 @@ static int of_spi_register_master(struct spi_master *master)
        nb = of_gpio_named_count(np, "cs-gpios");
        master->num_chipselect = max(nb, (int)master->num_chipselect);
 
-       if (nb < 1)
+       /* Return error only for an incorrectly formed cs-gpios property */
+       if (nb == 0 || nb == -ENOENT)
                return 0;
+       else if (nb < 0)
+               return nb;
 
        cs = devm_kzalloc(&master->dev,
                          sizeof(int) * master->num_chipselect,
@@ -1079,7 +1082,7 @@ static int of_spi_register_master(struct spi_master *master)
                return -ENOMEM;
 
        for (i = 0; i < master->num_chipselect; i++)
-               cs[i] = -EINVAL;
+               cs[i] = -ENOENT;
 
        for (i = 0; i < nb; i++)
                cs[i] = of_get_named_gpio(np, "cs-gpios", i);
index 4e8a179..aefe820 100644 (file)
@@ -72,10 +72,10 @@ source "drivers/staging/sep/Kconfig"
 
 source "drivers/staging/iio/Kconfig"
 
-source "drivers/staging/zram/Kconfig"
-
 source "drivers/staging/zsmalloc/Kconfig"
 
+source "drivers/staging/zram/Kconfig"
+
 source "drivers/staging/wlags49_h2/Kconfig"
 
 source "drivers/staging/wlags49_h25/Kconfig"
index ceb1c64..6dc27da 100644 (file)
@@ -264,6 +264,8 @@ static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
        }
 
        rv = alarm_do_ioctl(file, cmd, &ts);
+       if (rv)
+               return rv;
 
        switch (ANDROID_ALARM_BASE_CMD(cmd)) {
        case ANDROID_ALARM_GET_TIME(0):
@@ -272,7 +274,7 @@ static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                break;
        }
 
-       return rv;
+       return 0;
 }
 #ifdef CONFIG_COMPAT
 static long alarm_compat_ioctl(struct file *file, unsigned int cmd,
@@ -295,6 +297,8 @@ static long alarm_compat_ioctl(struct file *file, unsigned int cmd,
        }
 
        rv = alarm_do_ioctl(file, cmd, &ts);
+       if (rv)
+               return rv;
 
        switch (ANDROID_ALARM_BASE_CMD(cmd)) {
        case ANDROID_ALARM_GET_TIME(0): /* NOTE: we modified cmd above */
@@ -303,7 +307,7 @@ static long alarm_compat_ioctl(struct file *file, unsigned int cmd,
                break;
        }
 
-       return rv;
+       return 0;
 }
 #endif
 
index b040200..9bd8747 100644 (file)
@@ -242,7 +242,7 @@ static ssize_t do_read_log_to_user(struct logger_log *log,
  * 'log->buffer' which contains the first entry readable by 'euid'
  */
 static size_t get_next_entry_by_uid(struct logger_log *log,
-               size_t off, uid_t euid)
+               size_t off, kuid_t euid)
 {
        while (off != log->w_off) {
                struct logger_entry *entry;
@@ -251,7 +251,7 @@ static size_t get_next_entry_by_uid(struct logger_log *log,
 
                entry = get_entry_header(log, off, &scratch);
 
-               if (entry->euid == euid)
+               if (uid_eq(entry->euid, euid))
                        return off;
 
                next_len = sizeof(struct logger_entry) + entry->len;
index cc6bbd9..70af7d8 100644 (file)
@@ -66,7 +66,7 @@ struct logger_entry {
        __s32           tid;
        __s32           sec;
        __s32           nsec;
-       uid_t           euid;
+       kuid_t          euid;
        char            msg[0];
 };
 
index 7871579..87e852a 100644 (file)
@@ -981,6 +981,7 @@ config COMEDI_ME_DAQ
 
 config COMEDI_NI_6527
        tristate "NI 6527 support"
+       depends on HAS_DMA
        select COMEDI_MITE
        ---help---
          Enable support for the National Instruments 6527 PCI card
@@ -990,6 +991,7 @@ config COMEDI_NI_6527
 
 config COMEDI_NI_65XX
        tristate "NI 65xx static dio PCI card support"
+       depends on HAS_DMA
        select COMEDI_MITE
        ---help---
          Enable support for National Instruments 65xx static dio boards.
@@ -1003,6 +1005,7 @@ config COMEDI_NI_65XX
 
 config COMEDI_NI_660X
        tristate "NI 660x counter/timer PCI card support"
+       depends on HAS_DMA
        select COMEDI_NI_TIOCMD
        ---help---
          Enable support for National Instruments PCI-6601 (ni_660x), PCI-6602,
@@ -1013,6 +1016,7 @@ config COMEDI_NI_660X
 
 config COMEDI_NI_670X
        tristate "NI 670x PCI card support"
+       depends on HAS_DMA
        select COMEDI_MITE
        ---help---
          Enable support for National Instruments PCI-6703 and PCI-6704
@@ -1022,6 +1026,7 @@ config COMEDI_NI_670X
 
 config COMEDI_NI_LABPC_PCI
        tristate "NI Lab-PC PCI-1200 support"
+       depends on HAS_DMA
        select COMEDI_NI_LABPC
        select COMEDI_MITE
        ---help---
@@ -1032,6 +1037,7 @@ config COMEDI_NI_LABPC_PCI
 
 config COMEDI_NI_PCIDIO
        tristate "NI PCI-DIO32HS, PCI-6533, PCI-6534 support"
+       depends on HAS_DMA
        select COMEDI_MITE
        select COMEDI_8255
        ---help---
@@ -1043,6 +1049,7 @@ config COMEDI_NI_PCIDIO
 
 config COMEDI_NI_PCIMIO
        tristate "NI PCI-MIO-E series and M series support"
+       depends on HAS_DMA
        select COMEDI_NI_TIOCMD
        select COMEDI_8255
        select COMEDI_FC
@@ -1095,10 +1102,12 @@ config COMEDI_SSV_DNP
          called ssv_dnp.
 
 config COMEDI_MITE
+       depends on HAS_DMA
        tristate
 
 config COMEDI_NI_TIOCMD
        tristate
+       depends on HAS_DMA
        select COMEDI_NI_TIO
        select COMEDI_MITE
 
index ca70990..d4be0e6 100644 (file)
@@ -51,10 +51,12 @@ static void __comedi_buf_free(struct comedi_device *dev,
                        clear_bit(PG_reserved,
                                  &(virt_to_page(buf->virt_addr)->flags));
                        if (s->async_dma_dir != DMA_NONE) {
+#ifdef CONFIG_HAS_DMA
                                dma_free_coherent(dev->hw_dev,
                                                  PAGE_SIZE,
                                                  buf->virt_addr,
                                                  buf->dma_addr);
+#endif
                        } else {
                                free_page((unsigned long)buf->virt_addr);
                        }
@@ -74,6 +76,12 @@ static void __comedi_buf_alloc(struct comedi_device *dev,
        struct comedi_buf_page *buf;
        unsigned i;
 
+       if (!IS_ENABLED(CONFIG_HAS_DMA) && s->async_dma_dir != DMA_NONE) {
+               dev_err(dev->class_dev,
+                       "dma buffer allocation not supported\n");
+               return;
+       }
+
        async->buf_page_list = vzalloc(sizeof(*buf) * n_pages);
        if (async->buf_page_list)
                pages = vmalloc(sizeof(struct page *) * n_pages);
@@ -84,11 +92,15 @@ static void __comedi_buf_alloc(struct comedi_device *dev,
        for (i = 0; i < n_pages; i++) {
                buf = &async->buf_page_list[i];
                if (s->async_dma_dir != DMA_NONE)
+#ifdef CONFIG_HAS_DMA
                        buf->virt_addr = dma_alloc_coherent(dev->hw_dev,
                                                            PAGE_SIZE,
                                                            &buf->dma_addr,
                                                            GFP_KERNEL |
                                                            __GFP_COMP);
+#else
+                       break;
+#endif
                else
                        buf->virt_addr = (void *)get_zeroed_page(GFP_KERNEL);
                if (!buf->virt_addr)
index 00f2547..924c54c 100644 (file)
@@ -246,9 +246,6 @@ static int resize_async_buffer(struct comedi_device *dev,
                return -EBUSY;
        }
 
-       if (!async->prealloc_buf)
-               return -EINVAL;
-
        /* make sure buffer is an integral number of pages
         * (we round up) */
        new_size = (new_size + PAGE_SIZE - 1) & PAGE_MASK;
index 3d978f3..77a7bb6 100644 (file)
@@ -976,8 +976,7 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
                /* clear flip-flop to make sure 2-byte registers for
                 * count and address get set correctly */
                clear_dma_ff(devpriv->dma_chan);
-               set_dma_addr(devpriv->dma_chan,
-                            virt_to_bus(devpriv->dma_buffer));
+               set_dma_addr(devpriv->dma_chan, devpriv->dma_addr);
                /*  set appropriate size of transfer */
                devpriv->dma_transfer_size = labpc_suggest_transfer_size(cmd);
                if (cmd->stop_src == TRIG_COUNT &&
@@ -1089,7 +1088,7 @@ static void labpc_drain_dma(struct comedi_device *dev)
                devpriv->count -= num_points;
 
        /*  set address and count for next transfer */
-       set_dma_addr(devpriv->dma_chan, virt_to_bus(devpriv->dma_buffer));
+       set_dma_addr(devpriv->dma_chan, devpriv->dma_addr);
        set_dma_count(devpriv->dma_chan, leftover * sample_size);
        release_dma_lock(flags);
 
@@ -1741,6 +1740,9 @@ static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it)
                                unsigned long dma_flags;
 
                                devpriv->dma_chan = dma_chan;
+                               devpriv->dma_addr =
+                                       virt_to_bus(devpriv->dma_buffer);
+
                                dma_flags = claim_dma_lock();
                                disable_dma(devpriv->dma_chan);
                                set_dma_mode(devpriv->dma_chan, DMA_MODE_READ);
index 615f16f..4b691f5 100644 (file)
@@ -82,6 +82,7 @@ struct labpc_private {
        unsigned int divisor_b1;
        unsigned int dma_chan;  /*  dma channel to use */
        u16 *dma_buffer;        /*  buffer ai will dma into */
+       phys_addr_t dma_addr;
        /* transfer size in bytes for current transfer */
        unsigned int dma_transfer_size;
        /* we are using dma/fifo-half-full/etc. */
index a46d579..8c5dee9 100644 (file)
@@ -310,9 +310,11 @@ static int ni_gpct_insn_read(struct comedi_device *dev,
 static int ni_gpct_insn_config(struct comedi_device *dev,
                               struct comedi_subdevice *s,
                               struct comedi_insn *insn, unsigned int *data);
+#ifdef PCIDMA
 static int ni_gpct_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
 static int ni_gpct_cmdtest(struct comedi_device *dev,
                           struct comedi_subdevice *s, struct comedi_cmd *cmd);
+#endif
 static int ni_gpct_cancel(struct comedi_device *dev,
                          struct comedi_subdevice *s);
 static void handle_gpct_interrupt(struct comedi_device *dev,
@@ -4617,9 +4619,7 @@ static int ni_E_init(struct comedi_device *dev)
        for (j = 0; j < NUM_GPCT; ++j) {
                s = &dev->subdevices[NI_GPCT_SUBDEV(j)];
                s->type = COMEDI_SUBD_COUNTER;
-               s->subdev_flags =
-                   SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL | SDF_CMD_READ
-                   /* | SDF_CMD_WRITE */ ;
+               s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL;
                s->n_chan = 3;
                if (board->reg_type & ni_reg_m_series_mask)
                        s->maxdata = 0xffffffff;
@@ -4628,11 +4628,14 @@ static int ni_E_init(struct comedi_device *dev)
                s->insn_read = &ni_gpct_insn_read;
                s->insn_write = &ni_gpct_insn_write;
                s->insn_config = &ni_gpct_insn_config;
+#ifdef PCIDMA
+               s->subdev_flags |= SDF_CMD_READ /* | SDF_CMD_WRITE */;
                s->do_cmd = &ni_gpct_cmd;
                s->len_chanlist = 1;
                s->do_cmdtest = &ni_gpct_cmdtest;
                s->cancel = &ni_gpct_cancel;
                s->async_dma_dir = DMA_BIDIRECTIONAL;
+#endif
                s->private = &devpriv->counter_dev->counters[j];
 
                devpriv->counter_dev->counters[j].chip_index = 0;
@@ -5216,10 +5219,10 @@ static int ni_gpct_insn_write(struct comedi_device *dev,
        return ni_tio_winsn(counter, insn, data);
 }
 
+#ifdef PCIDMA
 static int ni_gpct_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
        int retval;
-#ifdef PCIDMA
        struct ni_gpct *counter = s->private;
 /* const struct comedi_cmd *cmd = &s->async->cmd; */
 
@@ -5233,23 +5236,20 @@ static int ni_gpct_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
        ni_tio_acknowledge_and_confirm(counter, NULL, NULL, NULL, NULL);
        ni_e_series_enable_second_irq(dev, counter->counter_index, 1);
        retval = ni_tio_cmd(counter, s->async);
-#else
-       retval = -ENOTSUPP;
-#endif
        return retval;
 }
+#endif
 
+#ifdef PCIDMA
 static int ni_gpct_cmdtest(struct comedi_device *dev,
                           struct comedi_subdevice *s, struct comedi_cmd *cmd)
 {
-#ifdef PCIDMA
        struct ni_gpct *counter = s->private;
 
        return ni_tio_cmdtest(counter, cmd);
-#else
        return -ENOTSUPP;
-#endif
 }
+#endif
 
 static int ni_gpct_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 {
index f0b4739..d15d9d5 100644 (file)
@@ -2,7 +2,6 @@ config USB_DWC2
        tristate "DesignWare USB2 DRD Core Support"
        depends on USB
        depends on VIRT_TO_BUS
-       select USB_OTG_UTILS
        help
          Say Y or M here if your system has a Dual Role HighSpeed
          USB controller based on the DesignWare HSOTG IP Core.
@@ -39,6 +38,7 @@ config USB_DWC2_TRACK_MISSED_SOFS
        bool "Enable Missed SOF Tracking"
        help
          Say Y here to enable logging of missed SOF events to the dmesg log.
+         WARNING: This feature is still experimental.
          If in doubt, say N.
 
 config USB_DWC2_DEBUG_PERIODIC
index 827ab78..8551cce 100644 (file)
@@ -2804,9 +2804,8 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq,
 
        /* Set device flags indicating whether the HCD supports DMA */
        if (hsotg->core_params->dma_enable > 0) {
-               if (dma_set_mask(hsotg->dev, DMA_BIT_MASK(31)) < 0)
-                       dev_warn(hsotg->dev,
-                                "can't enable workaround for >2GB RAM\n");
+               if (dma_set_mask(hsotg->dev, DMA_BIT_MASK(32)) < 0)
+                       dev_warn(hsotg->dev, "can't set DMA mask\n");
                if (dma_set_coherent_mask(hsotg->dev, DMA_BIT_MASK(31)) < 0)
                        dev_warn(hsotg->dev,
                                 "can't enable workaround for >2GB RAM\n");
index 6e5dbed..e24062f 100644 (file)
@@ -56,8 +56,6 @@
 static void dwc2_track_missed_sofs(struct dwc2_hsotg *hsotg)
 {
 #ifdef CONFIG_USB_DWC2_TRACK_MISSED_SOFS
-#warning Compiling code to track missed SOFs
-
        u16 curr_frame_number = hsotg->frame_number;
 
        if (hsotg->frame_num_idx < FRAME_NUM_ARRAY_SIZE) {
index 1f3d581..44cce2f 100644 (file)
@@ -95,6 +95,14 @@ static int dwc2_driver_probe(struct platform_device *dev)
 
        hsotg->dev = &dev->dev;
 
+       /*
+        * Use reasonable defaults so platforms don't have to provide these.
+        */
+       if (!dev->dev.dma_mask)
+               dev->dev.dma_mask = &dev->dev.coherent_dma_mask;
+       if (!dev->dev.coherent_dma_mask)
+               dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+
        irq = platform_get_irq(dev, 0);
        if (irq < 0) {
                dev_err(&dev->dev, "missing IRQ resource\n");
@@ -102,11 +110,6 @@ static int dwc2_driver_probe(struct platform_device *dev)
        }
 
        res = platform_get_resource(dev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(&dev->dev, "missing memory base resource\n");
-               return -EINVAL;
-       }
-
        hsotg->regs = devm_ioremap_resource(&dev->dev, res);
        if (IS_ERR(hsotg->regs))
                return PTR_ERR(hsotg->regs);
index 3c18efe..6905913 100644 (file)
@@ -39,7 +39,7 @@ if WIMAX_GDM72XX_USB
 
 config WIMAX_GDM72XX_USB_PM
        bool "Enable power managerment support"
-       depends on USB_SUSPEND
+       depends on PM_RUNTIME
 
 endif # WIMAX_GDM72XX_USB
 
index 2856b8f..163c638 100644 (file)
@@ -690,7 +690,6 @@ static void mxs_lradc_trigger_remove(struct iio_dev *iio)
 static int mxs_lradc_buffer_preenable(struct iio_dev *iio)
 {
        struct mxs_lradc *lradc = iio_priv(iio);
-       struct iio_buffer *buffer = iio->buffer;
        int ret = 0, chan, ofs = 0;
        unsigned long enable = 0;
        uint32_t ctrl4_set = 0;
@@ -698,7 +697,7 @@ static int mxs_lradc_buffer_preenable(struct iio_dev *iio)
        uint32_t ctrl1_irq = 0;
        const uint32_t chan_value = LRADC_CH_ACCUMULATE |
                ((LRADC_DELAY_TIMER_LOOP - 1) << LRADC_CH_NUM_SAMPLES_OFFSET);
-       const int len = bitmap_weight(buffer->scan_mask, LRADC_MAX_TOTAL_CHANS);
+       const int len = bitmap_weight(iio->active_scan_mask, LRADC_MAX_TOTAL_CHANS);
 
        if (!len)
                return -EINVAL;
@@ -725,7 +724,7 @@ static int mxs_lradc_buffer_preenable(struct iio_dev *iio)
                lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
        writel(0xff, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR);
 
-       for_each_set_bit(chan, buffer->scan_mask, LRADC_MAX_TOTAL_CHANS) {
+       for_each_set_bit(chan, iio->active_scan_mask, LRADC_MAX_TOTAL_CHANS) {
                ctrl4_set |= chan << LRADC_CTRL4_LRADCSELECT_OFFSET(ofs);
                ctrl4_clr |= LRADC_CTRL4_LRADCSELECT_MASK(ofs);
                ctrl1_irq |= LRADC_CTRL1_LRADC_IRQ_EN(ofs);
index d060f25..c99f890 100644 (file)
@@ -1869,6 +1869,7 @@ static int tsl2x7x_probe(struct i2c_client *clientp,
                dev_info(&chip->client->dev,
                                "%s: i2c device found does not match expected id\n",
                                __func__);
+               ret = -EINVAL;
                goto fail1;
        }
 
@@ -1907,7 +1908,7 @@ static int tsl2x7x_probe(struct i2c_client *clientp,
                if (ret) {
                        dev_err(&clientp->dev,
                                "%s: irq request failed", __func__);
-                       goto fail2;
+                       goto fail1;
                }
        }
 
@@ -1920,17 +1921,17 @@ static int tsl2x7x_probe(struct i2c_client *clientp,
        if (ret) {
                dev_err(&clientp->dev,
                        "%s: iio registration failed\n", __func__);
-               goto fail1;
+               goto fail2;
        }
 
        dev_info(&clientp->dev, "%s Light sensor found.\n", id->name);
 
        return 0;
 
-fail1:
+fail2:
        if (clientp->irq)
                free_irq(clientp->irq, indio_dev);
-fail2:
+fail1:
        iio_device_free(indio_dev);
 
        return ret;
index 8c9e403..ef699f7 100644 (file)
@@ -1,6 +1,7 @@
 config DRM_IMX
        tristate "DRM Support for Freescale i.MX"
        select DRM_KMS_HELPER
+       select VIDEOMODE_HELPERS
        select DRM_GEM_CMA_HELPER
        select DRM_KMS_CMA_HELPER
        depends on DRM && (ARCH_MXC || ARCH_MULTIPLATFORM)
@@ -19,10 +20,12 @@ config DRM_IMX_FB_HELPER
 config DRM_IMX_PARALLEL_DISPLAY
        tristate "Support for parallel displays"
        depends on DRM_IMX
+       select VIDEOMODE_HELPERS
 
 config DRM_IMX_TVE
        tristate "Support for TV and VGA displays"
        depends on DRM_IMX
+       select REGMAP_MMIO
        help
          Choose this to enable the internal Television Encoder (TVe)
          found on i.MX53 processors.
@@ -30,6 +33,7 @@ config DRM_IMX_TVE
 config DRM_IMX_IPUV3_CORE
        tristate "IPUv3 core support"
        depends on DRM_IMX
+       depends on RESET_CONTROLLER
        help
          Choose this if you have a i.MX5/6 system and want
          to use the IPU. This option only enables IPU base
@@ -38,5 +42,6 @@ config DRM_IMX_IPUV3_CORE
 config DRM_IMX_IPUV3
        tristate "DRM Support for i.MX IPUv3"
        depends on DRM_IMX
+       depends on DRM_IMX_IPUV3_CORE
        help
          Choose this if you have a i.MX5 or i.MX6 processor.
index ac16344..03892de 100644 (file)
@@ -670,7 +670,9 @@ static int imx_tve_probe(struct platform_device *pdev)
        tve->dac_reg = devm_regulator_get(&pdev->dev, "dac");
        if (!IS_ERR(tve->dac_reg)) {
                regulator_set_voltage(tve->dac_reg, 2750000, 2750000);
-               regulator_enable(tve->dac_reg);
+               ret = regulator_enable(tve->dac_reg);
+               if (ret)
+                       return ret;
        }
 
        tve->clk = devm_clk_get(&pdev->dev, "tve");
index ea61c86..ff5c633 100644 (file)
@@ -316,31 +316,14 @@ static int ipu_crtc_mode_set(struct drm_crtc *crtc,
 
 static void ipu_crtc_handle_pageflip(struct ipu_crtc *ipu_crtc)
 {
-       struct drm_pending_vblank_event *e;
-       struct timeval now;
        unsigned long flags;
        struct drm_device *drm = ipu_crtc->base.dev;
 
        spin_lock_irqsave(&drm->event_lock, flags);
-
-       e = ipu_crtc->page_flip_event;
-       if (!e) {
-               spin_unlock_irqrestore(&drm->event_lock, flags);
-               return;
-       }
-
-       do_gettimeofday(&now);
-       e->event.sequence = 0;
-       e->event.tv_sec = now.tv_sec;
-       e->event.tv_usec = now.tv_usec;
+       if (ipu_crtc->page_flip_event)
+               drm_send_vblank_event(drm, -1, ipu_crtc->page_flip_event);
        ipu_crtc->page_flip_event = NULL;
-
        imx_drm_crtc_vblank_put(ipu_crtc->imx_crtc);
-
-       list_add_tail(&e->base.link, &e->base.file_priv->event_list);
-
-       wake_up_interruptible(&e->base.file_priv->event_wait);
-
        spin_unlock_irqrestore(&drm->event_lock, flags);
 }
 
index ec32776..df6569b 100644 (file)
@@ -1,6 +1,7 @@
 config SOLO6X10
        tristate "Softlogic 6x10 MPEG codec cards"
        depends on PCI && VIDEO_DEV && SND && I2C
+       depends on FONTS
        select VIDEOBUF2_DMA_SG
        select VIDEOBUF2_DMA_CONTIG
        select SND_PCM
index a88959f..197c393 100644 (file)
@@ -123,6 +123,20 @@ int nvec_register_notifier(struct nvec_chip *nvec, struct notifier_block *nb,
 }
 EXPORT_SYMBOL_GPL(nvec_register_notifier);
 
+/**
+ * nvec_unregister_notifier - Unregister a notifier with nvec
+ * @nvec: A &struct nvec_chip
+ * @nb: The notifier block to unregister
+ *
+ * Unregisters a notifier with @nvec. The notifier will be removed from the
+ * atomic notifier chain.
+ */
+int nvec_unregister_notifier(struct nvec_chip *nvec, struct notifier_block *nb)
+{
+       return atomic_notifier_chain_unregister(&nvec->notifier_list, nb);
+}
+EXPORT_SYMBOL_GPL(nvec_unregister_notifier);
+
 /**
  * nvec_status_notifier - The final notifier
  *
@@ -185,7 +199,7 @@ static struct nvec_msg *nvec_msg_alloc(struct nvec_chip *nvec,
  *
  * Free the given message
  */
-inline void nvec_msg_free(struct nvec_chip *nvec, struct nvec_msg *msg)
+void nvec_msg_free(struct nvec_chip *nvec, struct nvec_msg *msg)
 {
        if (msg != &nvec->tx_scratch)
                dev_vdbg(nvec->dev, "INFO: Free %ti\n", msg - nvec->msg_pool);
@@ -800,11 +814,6 @@ static int tegra_nvec_probe(struct platform_device *pdev)
        }
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(&pdev->dev, "no mem resource?\n");
-               return -ENODEV;
-       }
-
        base = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(base))
                return PTR_ERR(base);
@@ -815,7 +824,7 @@ static int tegra_nvec_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
-       i2c_clk = clk_get(&pdev->dev, "div-clk");
+       i2c_clk = devm_clk_get(&pdev->dev, "div-clk");
        if (IS_ERR(i2c_clk)) {
                dev_err(nvec->dev, "failed to get controller clock\n");
                return -ENODEV;
@@ -902,8 +911,11 @@ static int tegra_nvec_remove(struct platform_device *pdev)
 
        nvec_toggle_global_events(nvec, false);
        mfd_remove_devices(nvec->dev);
+       nvec_unregister_notifier(nvec, &nvec->nvec_status_notifier);
        cancel_work_sync(&nvec->rx_work);
        cancel_work_sync(&nvec->tx_work);
+       /* FIXME: needs check wether nvec is responsible for power off */
+       pm_power_off = NULL;
 
        return 0;
 }
index b7a14bc..2b1316d 100644 (file)
@@ -197,9 +197,8 @@ extern int nvec_register_notifier(struct nvec_chip *nvec,
                                  struct notifier_block *nb,
                                  unsigned int events);
 
-extern int nvec_unregister_notifier(struct device *dev,
-                                   struct notifier_block *nb,
-                                   unsigned int events);
+extern int nvec_unregister_notifier(struct nvec_chip *dev,
+                                   struct notifier_block *nb);
 
 extern void nvec_msg_free(struct nvec_chip *nvec, struct nvec_msg *msg);
 
index 7445ce6..a0ec52a 100644 (file)
@@ -169,8 +169,15 @@ fail:
 
 static int nvec_kbd_remove(struct platform_device *pdev)
 {
+       struct nvec_chip *nvec = dev_get_drvdata(pdev->dev.parent);
+       char disable_kbd[] = { NVEC_KBD, DISABLE_KBD },
+            uncnfg_wake_key_reporting[] = { NVEC_KBD, CNFG_WAKE_KEY_REPORTING,
+                                               false };
+       nvec_write_async(nvec, uncnfg_wake_key_reporting, 3);
+       nvec_write_async(nvec, disable_kbd, 2);
+       nvec_unregister_notifier(nvec, &keys_dev.notifier);
+
        input_unregister_device(keys_dev.input);
-       input_free_device(keys_dev.input);
 
        return 0;
 }
@@ -188,4 +195,5 @@ module_platform_driver(nvec_kbd_driver);
 
 MODULE_AUTHOR("Marc Dietrich <marvin24@gmx.de>");
 MODULE_DESCRIPTION("NVEC keyboard driver");
+MODULE_ALIAS("platform:nvec-kbd");
 MODULE_LICENSE("GPL");
index 296f7b9..aacfcd6 100644 (file)
@@ -414,6 +414,7 @@ static int nvec_power_remove(struct platform_device *pdev)
        struct nvec_power *power = platform_get_drvdata(pdev);
 
        cancel_delayed_work_sync(&power->poller);
+       nvec_unregister_notifier(power->nvec, &power->notifier);
        switch (pdev->id) {
        case AC:
                power_supply_unregister(&nvec_psy);
index aff6b9b..06dbb02 100644 (file)
@@ -106,7 +106,7 @@ static int nvec_mouse_probe(struct platform_device *pdev)
        struct serio *ser_dev;
        char mouse_reset[] = { NVEC_PS2, SEND_COMMAND, PSMOUSE_RST, 3 };
 
-       ser_dev = devm_kzalloc(&pdev->dev, sizeof(struct serio), GFP_KERNEL);
+       ser_dev = kzalloc(sizeof(struct serio), GFP_KERNEL);
        if (ser_dev == NULL)
                return -ENOMEM;
 
@@ -133,6 +133,11 @@ static int nvec_mouse_probe(struct platform_device *pdev)
 
 static int nvec_mouse_remove(struct platform_device *pdev)
 {
+       struct nvec_chip *nvec = dev_get_drvdata(pdev->dev.parent);
+
+       ps2_sendcommand(ps2_dev.ser_dev, DISABLE_MOUSE);
+       ps2_stopstreaming(ps2_dev.ser_dev);
+       nvec_unregister_notifier(nvec, &ps2_dev.notifier);
        serio_unregister_port(ps2_dev.ser_dev);
 
        return 0;
@@ -179,4 +184,5 @@ module_platform_driver(nvec_mouse_driver);
 
 MODULE_DESCRIPTION("NVEC mouse driver");
 MODULE_AUTHOR("Marc Dietrich <marvin24@gmx.de>");
+MODULE_ALIAS("platform:nvec-mouse");
 MODULE_LICENSE("GPL");
index 185b676..aab945a 100644 (file)
@@ -1,6 +1,6 @@
 config DX_SEP
        tristate "Discretix SEP driver"
-       depends on PCI
+       depends on PCI && CRYPTO
        help
          Discretix SEP driver; used for the security processor subsystem
          on board the Intel Mobile Internet Device and adds SEP availability
index fe667dd..386362c 100644 (file)
@@ -1087,7 +1087,11 @@ static int synaptics_rmi4_resume(struct device *dev)
        unsigned char intr_status;
        struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
 
-       regulator_enable(rmi4_data->regulator);
+       retval = regulator_enable(rmi4_data->regulator);
+       if (retval) {
+               dev_err(dev, "Regulator enable failed (%d)\n", retval);
+               return retval;
+       }
 
        enable_irq(rmi4_data->i2c_client->irq);
        rmi4_data->touch_stopped = false;
index f4f1bf7..c699a30 100644 (file)
@@ -133,7 +133,7 @@ static int hostap_disable_hostapd(struct vnt_private *pDevice, int rtnl_locked)
             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Netdevice %s unregistered\n",
                       pDevice->dev->name, pDevice->apdev->name);
        }
-       kfree(pDevice->apdev);
+       free_netdev(pDevice->apdev);
        pDevice->apdev = NULL;
     pDevice->bEnable8021x = false;
     pDevice->bEnableHostWEP = false;
index c335808..d0cf7d8 100644 (file)
@@ -1345,9 +1345,12 @@ int iwctl_siwpower(struct net_device *dev, struct iw_request_info *info,
                return rc;
        }
 
+       spin_lock_irq(&pDevice->lock);
+
        if (wrq->disabled) {
                pDevice->ePSMode = WMAC_POWER_CAM;
                PSvDisablePowerSaving(pDevice);
+               spin_unlock_irq(&pDevice->lock);
                return rc;
        }
        if ((wrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
@@ -1358,6 +1361,9 @@ int iwctl_siwpower(struct net_device *dev, struct iw_request_info *info,
                pDevice->ePSMode = WMAC_POWER_FAST;
                PSvEnablePowerSaving((void *)pDevice, pMgmt->wListenInterval);
        }
+
+       spin_unlock_irq(&pDevice->lock);
+
        switch (wrq->flags & IW_POWER_MODE) {
        case IW_POWER_UNICAST_R:
                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWPOWER: IW_POWER_UNICAST_R \n");
index e1f91d5..a858666 100644 (file)
 #ifndef _ZCACHE_RAMSTER_H_
 #define _ZCACHE_RAMSTER_H_
 
-#ifdef CONFIG_RAMSTER_MODULE
-#define CONFIG_RAMSTER
-#endif
-
 #ifdef CONFIG_RAMSTER
 #include "ramster/ramster.h"
 #else
index 327e4f0..5b26ee9 100644 (file)
@@ -1,6 +1,8 @@
 #include <linux/atomic.h>
 #include "debug.h"
 
+ssize_t ramster_foreign_eph_pages;
+ssize_t ramster_foreign_pers_pages;
 #ifdef CONFIG_DEBUG_FS
 #include <linux/debugfs.h>
 
diff --git a/drivers/staging/zcache/ramster/ramster-howto.txt b/drivers/staging/zcache/ramster/ramster-howto.txt
new file mode 100644 (file)
index 0000000..7b1ee3b
--- /dev/null
@@ -0,0 +1,366 @@
+                       RAMSTER HOW-TO
+
+Author: Dan Magenheimer
+Ramster maintainer: Konrad Wilk <konrad.wilk@oracle.com>
+
+This is a HOWTO document for ramster which, as of this writing, is in
+the kernel as a subdirectory of zcache in drivers/staging, called ramster.
+(Zcache can be built with or without ramster functionality.)  If enabled
+and properly configured, ramster allows memory capacity load balancing
+across multiple machines in a cluster.  Further, the ramster code serves
+as an example of asynchronous access for zcache (as well as cleancache and
+frontswap) that may prove useful for future transcendent memory
+implementations, such as KVM and NVRAM.  While ramster works today on
+any network connection that supports kernel sockets, its features may
+become more interesting on future high-speed fabrics/interconnects.
+
+Ramster requires both kernel and userland support.  The userland support,
+called ramster-tools, is known to work with EL6-based distros, but is a
+set of poorly-hacked slightly-modified cluster tools based on ocfs2, which
+includes an init file, a config file, and a userland binary that interfaces
+to the kernel.  This state of userland support reflects the abysmal userland
+skills of this suitably-embarrassed author; any help/patches to turn
+ramster-tools into more distributable rpms/debs useful for a wider range
+of distros would be appreciated.  The source RPM that can be used as a
+starting point is available at:
+    http://oss.oracle.com/projects/tmem/files/RAMster/ 
+
+As a result of this author's ignorance, userland setup described in this
+HOWTO assumes an EL6 distro and is described in EL6 syntax.  Apologies
+if this offends anyone!
+
+Kernel support has only been tested on x86_64.  Systems with an active
+ocfs2 filesystem should work, but since ramster leverages a lot of
+code from ocfs2, there may be latent issues.  A kernel configuration that
+includes CONFIG_OCFS2_FS should build OK, and should certainly run OK
+if no ocfs2 filesystem is mounted.
+
+This HOWTO demonstrates memory capacity load balancing for a two-node
+cluster, where one node called the "local" node becomes overcommitted
+and the other node called the "remote" node provides additional RAM
+capacity for use by the local node.  Ramster is capable of more complex
+topologies; see the last section titled "ADVANCED RAMSTER TOPOLOGIES".
+
+If you find any terms in this HOWTO unfamiliar or don't understand the
+motivation for ramster, the following LWN reading is recommended:
+-- Transcendent Memory in a Nutshell (lwn.net/Articles/454795)
+-- The future calculus of memory management (lwn.net/Articles/475681)
+And since ramster is built on top of zcache, this article may be helpful:
+-- In-kernel memory compression (lwn.net/Articles/545244)
+
+Now that you've memorized the contents of those articles, let's get started!
+
+A. PRELIMINARY
+
+1) Install two x86_64 Linux systems that are known to work when
+   upgraded to a recent upstream Linux kernel version.
+
+On each system:
+
+2) Configure, build and install, then boot Linux, just to ensure it
+   can be done with an unmodified upstream kernel.  Confirm you booted
+   the upstream kernel with "uname -a".
+
+3) If you plan to do any performance testing or unless you plan to
+   test only swapping, the "WasActive" patch is also highly recommended.
+   (Search lkml.org for WasActive, apply the patch, rebuild your kernel.)
+   For a demo or simple testing, the patch can be ignored.
+
+4) Install ramster-tools as root.  An x86_64 rpm for EL6-based systems
+   can be found at:
+    http://oss.oracle.com/projects/tmem/files/RAMster/ 
+   (Sorry but for now, non-EL6 users must recreate ramster-tools on
+   their own from source.  See above.)
+
+5) Ensure that debugfs is mounted at each boot.  Examples below assume it
+   is mounted at /sys/kernel/debug.
+
+B. BUILDING RAMSTER INTO THE KERNEL
+
+Do the following on each system:
+
+1) Using the kernel configuration mechanism of your choice, change
+   your config to include:
+
+       CONFIG_CLEANCACHE=y
+       CONFIG_FRONTSWAP=y
+       CONFIG_STAGING=y
+       CONFIG_CONFIGFS_FS=y # NOTE: MUST BE y, not m
+       CONFIG_ZCACHE=y
+       CONFIG_RAMSTER=y
+
+   For a linux-3.10 or later kernel, you should also set:
+
+       CONFIG_ZCACHE_DEBUG=y
+       CONFIG_RAMSTER_DEBUG=y
+
+   Before building the kernel please doublecheck your kernel config
+   file to ensure all of the settings are correct.
+
+2) Build this kernel and change your boot file (e.g. /etc/grub.conf)
+   so that the new kernel will boot.
+
+3) Add "zcache" and "ramster" as kernel boot parameters for the new kernel.
+
+4) Reboot each system approximately simultaneously.
+
+5) Check dmesg to ensure there are some messages from ramster, prefixed
+   by "ramster:"
+
+       # dmesg | grep ramster
+
+   You should also see a lot of files in:
+
+       # ls /sys/kernel/debug/zcache
+       # ls /sys/kernel/debug/ramster
+
+   These are mostly counters for various zcache and ramster activities.
+   You should also see files in:
+
+       # ls /sys/kernel/mm/ramster
+
+   These are sysfs files that control ramster as we shall see.
+
+   Ramster now will act as a single-system zcache on each system
+   but doesn't yet know anything about the cluster so can't yet do
+   anything remotely.
+
+C. CONFIGURING THE RAMSTER CLUSTER
+
+This part can be error prone unless you are familiar with clustering
+filesystems.  We need to describe the cluster in a /etc/ramster.conf
+file and the init scripts that parse it are extremely picky about
+the syntax.
+
+1) Create a /etc/ramster.conf file and ensure it is identical on both
+   systems.  This file mimics the ocfs2 format and there is a good amount
+   of documentation that can be searched for ocfs2.conf, but you can use:
+
+       cluster:
+               name = ramster
+               node_count = 2
+       node:
+               name = system1
+               cluster = ramster
+               number = 0
+               ip_address = my.ip.ad.r1
+               ip_port = 7777
+       node:
+               name = system2
+               cluster = ramster
+               number = 1
+               ip_address = my.ip.ad.r2
+               ip_port = 7777
+
+   You must ensure that the "name" field in the file exactly matches
+   the output of "hostname" on each system; if "hostname" shows a
+   fully-qualified hostname, ensure the name is fully qualified in
+   /etc/ramster.conf.  Obviously, substitute my.ip.ad.rx with proper
+   ip addresses.
+
+2) Enable the ramster service and configure it.  If you used the
+   EL6 ramster-tools, this would be:
+
+       # chkconfig --add ramster
+       # service ramster configure
+
+   Set "load on boot" to "y", cluster to start is "ramster" (or whatever
+   name you chose in ramster.conf), heartbeat dead threshold as "500",
+   network idle timeout as "1000000".  Leave the others as default.
+
+3) Reboot both systems.  After reboot, try (assuming EL6 ramster-tools):
+
+       # service ramster status
+
+   You should see "Checking RAMSTER cluster "ramster": Online".  If you do
+   not, something is wrong and ramster will not work.  Note that you
+   should also see that the driver for "configfs" is loaded and mounted,
+   the driver for ocfs2_dlmfs is not loaded, and some numbers for network
+   parameters.  You will also see "Checking RAMSTER heartbeat: Not active".
+   That's all OK.
+
+4) Now you need to start the cluster heartbeat; the cluster is not "up"
+   until all nodes detect a heartbeat.  In a real cluster, heartbeat detection
+   is done via a cluster filesystem, but ramster doesn't require one.  Some
+   hack-y kernel code in ramster can start the heartbeat for you though if
+   you tell it what nodes are "up".  To enable the heartbeat, do:
+
+       # echo 0 > /sys/kernel/mm/ramster/manual_node_up
+       # echo 1 > /sys/kernel/mm/ramster/manual_node_up
+
+   This must be done on BOTH nodes and, to avoid timeouts, must be done
+   approximately concurrently on both nodes.  On an EL6 system, it is
+   convenient to put these lines in /etc/rc.local.  To confirm that the
+   cluster is now up, on both systems do:
+
+       # dmesg | grep ramster
+
+   You should see ramster "Accepted connection" messages in dmesg on both
+   nodes after this.  Note that if you check userland status again with
+
+       # service ramster status
+
+   you will still see "Checking RAMSTER heartbeat: Not active".  That's
+   still OK... the ramster kernel heartbeat hack doesn't communicate to
+   userland.
+
+5) You now must tell each node the node to which it should "remotify" pages.
+   On this two node cluster, we will assume the "local" node, node 0, has
+   memory overcommitted and will use ramster to utilize RAM capacity on
+   the "remote node", node 1.  To configure this, on node 0, you do:
+
+       # echo 1 > /sys/kernel/mm/ramster/remote_target_nodenum
+
+   You should see "ramster: node 1 set as remotification target" in dmesg
+   on node 0.  Again, on EL6, /etc/rc.local is a good place to put this
+   on node 0 so you don't forget to do it at each boot.
+
+6) One more step:  By default, the ramster code does not "remotify" any
+   pages; this is primarily for testing purposes, but sometimes it is
+   useful.  This may change in the future, but for now, on node 0, you do:
+
+       # echo 1 > /sys/kernel/mm/ramster/pers_remotify_enable
+       # echo 1 > /sys/kernel/mm/ramster/eph_remotify_enable
+
+   The first enables remotifying swap (persistent, aka frontswap) pages,
+   the second enables remotifying of page cache (ephemeral, cleancache)
+   pages.
+
+   On EL6, these lines can also be put in /etc/rc.local (AFTER the
+   node_up lines), or at the beginning of a script that runs a workload.
+
+7) Note that most testing has been done with both/all machines booted
+   roughly simultaneously to avoid cluster timeouts.  Ideally, you should
+   do this too unless you are trying to break ramster rather than just
+   use it. ;-)
+
+D. TESTING RAMSTER
+
+1) Note that ramster has no value unless pages get "remotified".  For
+   swap/frontswap/persistent pages, this doesn't happen unless/until
+   the workload would cause swapping to occur, at which point pages
+   are put into frontswap/zcache, and the remotification thread starts
+   working.  To get to the point where the system swaps, you either
+   need a workload for which the working set exceeds the RAM in the
+   system; or you need to somehow reduce the amount of RAM one of
+   the system sees.  This latter is easy when testing in a VM, but
+   harder on physical systems.  In some cases, "mem=xxxM" on the
+   kernel command line restricts memory, but for some values of xxx
+   the kernel may fail to boot.  One may also try creating a fixed
+   RAMdisk, doing nothing with it, but ensuring that it eats up a fixed
+   amount of RAM.
+
+2) To see if ramster is working, on the "remote node", node 1, try:
+
+       # grep . /sys/kernel/debug/ramster/foreign_*
+        # # note, that is space-dot-space between grep and the pathname
+
+   to monitor the number (and max) ephemeral and persistent pages
+   that ramster has sent.  If these stay at zero, ramster is not working
+   either because the workload on the local node (node 0) isn't creating
+   enough memory pressure or because "remotifying" isn't working.  On the
+   local system, node 0, you can watch lots of useful information also.
+   Try:
+
+       grep . /sys/kernel/debug/zcache/*pageframes* \
+               /sys/kernel/debug/zcache/*zbytes* \
+               /sys/kernel/debug/zcache/*zpages* \
+               /sys/kernel/debug/ramster/*remote*
+
+   Of particular note are the remote_*_pages_succ_get counters.  These
+   show how many disk reads and/or disk writes have been avoided on the
+   overcommitted local system by storing pages remotely using ramster.
+
+   At the risk of information overload, you can also grep:
+
+        /sys/kernel/debug/cleancache/* and /sys/kernel/debug/frontswap/*
+
+   These show, for example, how many disk reads and/or disk writes have
+   been avoided by using zcache to optimize RAM on the local system.
+
+
+AUTOMATIC SWAP REPATRIATION
+
+You may notice that while the systems are idle, the foreign persistent
+page count on the remote machine slowly decreases.  This is because
+ramster implements "frontswap selfshrinking":  When possible, swap
+pages that have been remotified are slowly repatriated to the local
+machine.  This is so that local RAM can be used when possible and
+so that, in case of remote machine crash, the probability of loss
+of data is reduced.
+
+REBOOTING / POWEROFF
+
+If a system is shut down while some of its swap pages still reside
+on a remote system, the system may lock up during the shutdown
+sequence.  This will occur if the network is shut down before the
+swap mechansim is shut down, which is the default ordering on many
+distros.  To avoid this annoying problem, simply shut off the swap
+subsystem before starting the shutdown sequence, e.g.:
+
+       # swapoff -a
+       # reboot
+
+Ideally, this swapoff-before-ifdown ordering should be enforced permanently
+using shutdown scripts.
+
+KNOWN PROBLEMS
+
+1) You may periodically see messages such as:
+
+    ramster_r2net, message length problem
+
+   This is harmless but indicates that a node is sending messages
+   containing compressed pages that exceed the maximum for zcache
+   (PAGE_SIZE*15/16).  The sender side needs to be fixed.
+
+2) If you see a "No longer connected to node..." message or a "No connection
+   established with node X after N seconds", it is possible you may
+   be in an unrecoverable state.  If you are certain all of the
+   appropriate cluster configuration steps described above have been
+   performed, try rebooting the two servers concurrently to see if
+   the cluster starts.
+
+   Note that "Connection to node... shutdown, state 7" is an intermediate
+   connection state.  As long as you later see "Accepted connection", the
+   intermediate states are harmless.
+
+3) There are known issues in counting certain values.  As a result
+   you may see periodic warnings from the kernel.  Almost always you
+   will see "ramster: bad accounting for XXX".  There are also "WARN_ONCE"
+   messages.  If you see kernel warnings with a tombstone, please report
+   them.  They are harmless but reflect bugs that need to be eventually fixed.
+
+ADVANCED RAMSTER TOPOLOGIES
+
+The kernel code for ramster can support up to eight nodes in a cluster,
+but no testing has been done with more than three nodes.
+
+In the example described above, the "remote" node serves as a RAM
+overflow for the "local" node.  This can be made symmetric by appropriate
+settings of the sysfs remote_target_nodenum file.  For example, by setting:
+
+       # echo 1 > /sys/kernel/mm/ramster/remote_target_nodenum
+
+on node 0, and
+
+       # echo 0 > /sys/kernel/mm/ramster/remote_target_nodenum
+
+on node 1, each node can serve as a RAM overflow for the other.
+
+For more than two nodes, a "RAM server" can be configured.  For a
+three node system, set:
+
+       # echo 0 > /sys/kernel/mm/ramster/remote_target_nodenum
+
+on node 1, and
+
+       # echo 0 > /sys/kernel/mm/ramster/remote_target_nodenum
+
+on node 2.  Then node 0 is a RAM server for node 1 and node 2.
+
+In this implementation of ramster, any remote node is potentially a single
+point of failure (SPOF).  Though the probability of failure is reduced
+by automatic swap repatriation (see above), a proposed future enhancement
+to ramster improves high-availability for the cluster by sending a copy
+of each page of date to two other nodes.  Patches welcome!
index b18b887..a937ce1 100644 (file)
@@ -66,8 +66,6 @@ static int ramster_remote_target_nodenum __read_mostly = -1;
 
 /* Used by this code. */
 long ramster_flnodes;
-ssize_t ramster_foreign_eph_pages;
-ssize_t ramster_foreign_pers_pages;
 /* FIXME frontswap selfshrinking knobs in debugfs? */
 
 static LIST_HEAD(ramster_rem_op_list);
@@ -399,14 +397,18 @@ void ramster_count_foreign_pages(bool eph, int count)
                        inc_ramster_foreign_eph_pages();
                } else {
                        dec_ramster_foreign_eph_pages();
+#ifdef CONFIG_RAMSTER_DEBUG
                        WARN_ON_ONCE(ramster_foreign_eph_pages < 0);
+#endif
                }
        } else {
                if (count > 0) {
                        inc_ramster_foreign_pers_pages();
                } else {
                        dec_ramster_foreign_pers_pages();
+#ifdef CONFIG_RAMSTER_DEBUG
                        WARN_ON_ONCE(ramster_foreign_pers_pages < 0);
+#endif
                }
        }
 }
index 522cb8e..dcceed2 100644 (file)
@@ -1922,15 +1922,15 @@ out:
 
 #ifdef CONFIG_ZCACHE_MODULE
 #ifdef CONFIG_RAMSTER
-module_param(ramster_enabled, int, S_IRUGO);
+module_param(ramster_enabled, bool, S_IRUGO);
 module_param(disable_frontswap_selfshrink, int, S_IRUGO);
 #endif
-module_param(disable_cleancache, int, S_IRUGO);
-module_param(disable_frontswap, int, S_IRUGO);
+module_param(disable_cleancache, bool, S_IRUGO);
+module_param(disable_frontswap, bool, S_IRUGO);
 #ifdef FRONTSWAP_HAS_EXCLUSIVE_GETS
 module_param(frontswap_has_exclusive_gets, bool, S_IRUGO);
 #endif
-module_param(disable_frontswap_ignore_nonactive, int, S_IRUGO);
+module_param(disable_frontswap_ignore_nonactive, bool, S_IRUGO);
 module_param(zcache_comp_name, charp, S_IRUGO);
 module_init(zcache_init);
 MODULE_LICENSE("GPL");
index ffbc6a9..d7705e5 100644 (file)
@@ -651,7 +651,7 @@ static int iscsit_add_reject(
        cmd->buf_ptr = kmemdup(buf, ISCSI_HDR_LEN, GFP_KERNEL);
        if (!cmd->buf_ptr) {
                pr_err("Unable to allocate memory for cmd->buf_ptr\n");
-               iscsit_release_cmd(cmd);
+               iscsit_free_cmd(cmd, false);
                return -1;
        }
 
@@ -697,7 +697,7 @@ int iscsit_add_reject_from_cmd(
        cmd->buf_ptr = kmemdup(buf, ISCSI_HDR_LEN, GFP_KERNEL);
        if (!cmd->buf_ptr) {
                pr_err("Unable to allocate memory for cmd->buf_ptr\n");
-               iscsit_release_cmd(cmd);
+               iscsit_free_cmd(cmd, false);
                return -1;
        }
 
@@ -1250,7 +1250,7 @@ static u32 iscsit_do_crypto_hash_sg(
 
 static void iscsit_do_crypto_hash_buf(
        struct hash_desc *hash,
-       unsigned char *buf,
+       const void *buf,
        u32 payload_length,
        u32 padding,
        u8 *pad_bytes,
@@ -1743,7 +1743,7 @@ int iscsit_handle_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
        return 0;
 out:
        if (cmd)
-               iscsit_release_cmd(cmd);
+               iscsit_free_cmd(cmd, false);
 ping_out:
        kfree(ping_data);
        return ret;
@@ -2251,7 +2251,7 @@ iscsit_handle_logout_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
        if (conn->conn_state != TARG_CONN_STATE_LOGGED_IN) {
                pr_err("Received logout request on connection that"
                        " is not in logged in state, ignoring request.\n");
-               iscsit_release_cmd(cmd);
+               iscsit_free_cmd(cmd, false);
                return 0;
        }
 
@@ -2524,9 +2524,8 @@ static int iscsit_send_conn_drop_async_message(
        if (conn->conn_ops->HeaderDigest) {
                u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN];
 
-               iscsit_do_crypto_hash_buf(&conn->conn_tx_hash,
-                               (unsigned char *)hdr, ISCSI_HDR_LEN,
-                               0, NULL, (u8 *)header_digest);
+               iscsit_do_crypto_hash_buf(&conn->conn_tx_hash, hdr,
+                               ISCSI_HDR_LEN, 0, NULL, (u8 *)header_digest);
 
                cmd->tx_size += ISCSI_CRC_LEN;
                pr_debug("Attaching CRC32C HeaderDigest to"
@@ -2662,9 +2661,8 @@ static int iscsit_send_datain(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
        if (conn->conn_ops->HeaderDigest) {
                u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN];
 
-               iscsit_do_crypto_hash_buf(&conn->conn_tx_hash,
-                               (unsigned char *)cmd->pdu, ISCSI_HDR_LEN,
-                               0, NULL, (u8 *)header_digest);
+               iscsit_do_crypto_hash_buf(&conn->conn_tx_hash, cmd->pdu,
+                               ISCSI_HDR_LEN, 0, NULL, (u8 *)header_digest);
 
                iov[0].iov_len += ISCSI_CRC_LEN;
                tx_size += ISCSI_CRC_LEN;
@@ -2841,9 +2839,8 @@ iscsit_send_logout(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
        if (conn->conn_ops->HeaderDigest) {
                u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN];
 
-               iscsit_do_crypto_hash_buf(&conn->conn_tx_hash,
-                               (unsigned char *)&cmd->pdu[0], ISCSI_HDR_LEN,
-                               0, NULL, (u8 *)header_digest);
+               iscsit_do_crypto_hash_buf(&conn->conn_tx_hash, &cmd->pdu[0],
+                               ISCSI_HDR_LEN, 0, NULL, (u8 *)header_digest);
 
                iov[0].iov_len += ISCSI_CRC_LEN;
                tx_size += ISCSI_CRC_LEN;
@@ -2900,9 +2897,8 @@ static int iscsit_send_unsolicited_nopin(
        if (conn->conn_ops->HeaderDigest) {
                u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN];
 
-               iscsit_do_crypto_hash_buf(&conn->conn_tx_hash,
-                               (unsigned char *)hdr, ISCSI_HDR_LEN,
-                               0, NULL, (u8 *)header_digest);
+               iscsit_do_crypto_hash_buf(&conn->conn_tx_hash, hdr,
+                               ISCSI_HDR_LEN, 0, NULL, (u8 *)header_digest);
 
                tx_size += ISCSI_CRC_LEN;
                pr_debug("Attaching CRC32C HeaderDigest to"
@@ -2949,9 +2945,8 @@ iscsit_send_nopin(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
        if (conn->conn_ops->HeaderDigest) {
                u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN];
 
-               iscsit_do_crypto_hash_buf(&conn->conn_tx_hash,
-                               (unsigned char *)hdr, ISCSI_HDR_LEN,
-                               0, NULL, (u8 *)header_digest);
+               iscsit_do_crypto_hash_buf(&conn->conn_tx_hash, hdr,
+                               ISCSI_HDR_LEN, 0, NULL, (u8 *)header_digest);
 
                iov[0].iov_len += ISCSI_CRC_LEN;
                tx_size += ISCSI_CRC_LEN;
@@ -3040,9 +3035,8 @@ static int iscsit_send_r2t(
        if (conn->conn_ops->HeaderDigest) {
                u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN];
 
-               iscsit_do_crypto_hash_buf(&conn->conn_tx_hash,
-                               (unsigned char *)hdr, ISCSI_HDR_LEN,
-                               0, NULL, (u8 *)header_digest);
+               iscsit_do_crypto_hash_buf(&conn->conn_tx_hash, hdr,
+                               ISCSI_HDR_LEN, 0, NULL, (u8 *)header_digest);
 
                cmd->iov_misc[0].iov_len += ISCSI_CRC_LEN;
                tx_size += ISCSI_CRC_LEN;
@@ -3256,9 +3250,8 @@ static int iscsit_send_response(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
        if (conn->conn_ops->HeaderDigest) {
                u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN];
 
-               iscsit_do_crypto_hash_buf(&conn->conn_tx_hash,
-                               (unsigned char *)cmd->pdu, ISCSI_HDR_LEN,
-                               0, NULL, (u8 *)header_digest);
+               iscsit_do_crypto_hash_buf(&conn->conn_tx_hash, cmd->pdu,
+                               ISCSI_HDR_LEN, 0, NULL, (u8 *)header_digest);
 
                iov[0].iov_len += ISCSI_CRC_LEN;
                tx_size += ISCSI_CRC_LEN;
@@ -3329,9 +3322,8 @@ iscsit_send_task_mgt_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
        if (conn->conn_ops->HeaderDigest) {
                u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN];
 
-               iscsit_do_crypto_hash_buf(&conn->conn_tx_hash,
-                               (unsigned char *)hdr, ISCSI_HDR_LEN,
-                               0, NULL, (u8 *)header_digest);
+               iscsit_do_crypto_hash_buf(&conn->conn_tx_hash, hdr,
+                               ISCSI_HDR_LEN, 0, NULL, (u8 *)header_digest);
 
                cmd->iov_misc[0].iov_len += ISCSI_CRC_LEN;
                tx_size += ISCSI_CRC_LEN;
@@ -3504,9 +3496,8 @@ static int iscsit_send_text_rsp(
        if (conn->conn_ops->HeaderDigest) {
                u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN];
 
-               iscsit_do_crypto_hash_buf(&conn->conn_tx_hash,
-                               (unsigned char *)hdr, ISCSI_HDR_LEN,
-                               0, NULL, (u8 *)header_digest);
+               iscsit_do_crypto_hash_buf(&conn->conn_tx_hash, hdr,
+                               ISCSI_HDR_LEN, 0, NULL, (u8 *)header_digest);
 
                iov[0].iov_len += ISCSI_CRC_LEN;
                tx_size += ISCSI_CRC_LEN;
@@ -3557,11 +3548,11 @@ static int iscsit_send_reject(
        struct iscsi_cmd *cmd,
        struct iscsi_conn *conn)
 {
-       u32 iov_count = 0, tx_size = 0;
-       struct iscsi_reject *hdr;
+       struct iscsi_reject *hdr = (struct iscsi_reject *)&cmd->pdu[0];
        struct kvec *iov;
+       u32 iov_count = 0, tx_size;
 
-       iscsit_build_reject(cmd, conn, (struct iscsi_reject *)&cmd->pdu[0]);
+       iscsit_build_reject(cmd, conn, hdr);
 
        iov = &cmd->iov_misc[0];
        iov[iov_count].iov_base = cmd->pdu;
@@ -3574,9 +3565,8 @@ static int iscsit_send_reject(
        if (conn->conn_ops->HeaderDigest) {
                u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN];
 
-               iscsit_do_crypto_hash_buf(&conn->conn_tx_hash,
-                               (unsigned char *)hdr, ISCSI_HDR_LEN,
-                               0, NULL, (u8 *)header_digest);
+               iscsit_do_crypto_hash_buf(&conn->conn_tx_hash, hdr,
+                               ISCSI_HDR_LEN, 0, NULL, (u8 *)header_digest);
 
                iov[0].iov_len += ISCSI_CRC_LEN;
                tx_size += ISCSI_CRC_LEN;
@@ -3585,9 +3575,8 @@ static int iscsit_send_reject(
        }
 
        if (conn->conn_ops->DataDigest) {
-               iscsit_do_crypto_hash_buf(&conn->conn_tx_hash,
-                               (unsigned char *)cmd->buf_ptr, ISCSI_HDR_LEN,
-                               0, NULL, (u8 *)&cmd->data_crc);
+               iscsit_do_crypto_hash_buf(&conn->conn_tx_hash, cmd->buf_ptr,
+                               ISCSI_HDR_LEN, 0, NULL, (u8 *)&cmd->data_crc);
 
                iov[iov_count].iov_base = &cmd->data_crc;
                iov[iov_count++].iov_len  = ISCSI_CRC_LEN;
@@ -3676,7 +3665,7 @@ iscsit_immediate_queue(struct iscsi_conn *conn, struct iscsi_cmd *cmd, int state
                list_del(&cmd->i_conn_node);
                spin_unlock_bh(&conn->cmd_lock);
 
-               iscsit_free_cmd(cmd);
+               iscsit_free_cmd(cmd, false);
                break;
        case ISTATE_SEND_NOPIN_WANT_RESPONSE:
                iscsit_mod_nopin_response_timer(conn);
@@ -4133,7 +4122,7 @@ static void iscsit_release_commands_from_conn(struct iscsi_conn *conn)
 
                iscsit_increment_maxcmdsn(cmd, sess);
 
-               iscsit_free_cmd(cmd);
+               iscsit_free_cmd(cmd, true);
 
                spin_lock_bh(&conn->cmd_lock);
        }
index 7816af6..40d9dbc 100644 (file)
@@ -823,7 +823,7 @@ static int iscsit_attach_ooo_cmdsn(
                /*
                 * CmdSN is greater than the tail of the list.
                 */
-               if (ooo_tail->cmdsn < ooo_cmdsn->cmdsn)
+               if (iscsi_sna_lt(ooo_tail->cmdsn, ooo_cmdsn->cmdsn))
                        list_add_tail(&ooo_cmdsn->ooo_list,
                                        &sess->sess_ooo_cmdsn_list);
                else {
@@ -833,11 +833,12 @@ static int iscsit_attach_ooo_cmdsn(
                         */
                        list_for_each_entry(ooo_tmp, &sess->sess_ooo_cmdsn_list,
                                                ooo_list) {
-                               if (ooo_tmp->cmdsn < ooo_cmdsn->cmdsn)
+                               if (iscsi_sna_lt(ooo_tmp->cmdsn, ooo_cmdsn->cmdsn))
                                        continue;
 
+                               /* Insert before this entry */
                                list_add(&ooo_cmdsn->ooo_list,
-                                       &ooo_tmp->ooo_list);
+                                       ooo_tmp->ooo_list.prev);
                                break;
                        }
                }
index ba6091b..45a5afd 100644 (file)
@@ -143,7 +143,7 @@ void iscsit_free_connection_recovery_entires(struct iscsi_session *sess)
                        list_del(&cmd->i_conn_node);
                        cmd->conn = NULL;
                        spin_unlock(&cr->conn_recovery_cmd_lock);
-                       iscsit_free_cmd(cmd);
+                       iscsit_free_cmd(cmd, true);
                        spin_lock(&cr->conn_recovery_cmd_lock);
                }
                spin_unlock(&cr->conn_recovery_cmd_lock);
@@ -165,7 +165,7 @@ void iscsit_free_connection_recovery_entires(struct iscsi_session *sess)
                        list_del(&cmd->i_conn_node);
                        cmd->conn = NULL;
                        spin_unlock(&cr->conn_recovery_cmd_lock);
-                       iscsit_free_cmd(cmd);
+                       iscsit_free_cmd(cmd, true);
                        spin_lock(&cr->conn_recovery_cmd_lock);
                }
                spin_unlock(&cr->conn_recovery_cmd_lock);
@@ -248,7 +248,7 @@ void iscsit_discard_cr_cmds_by_expstatsn(
                iscsit_remove_cmd_from_connection_recovery(cmd, sess);
 
                spin_unlock(&cr->conn_recovery_cmd_lock);
-               iscsit_free_cmd(cmd);
+               iscsit_free_cmd(cmd, true);
                spin_lock(&cr->conn_recovery_cmd_lock);
        }
        spin_unlock(&cr->conn_recovery_cmd_lock);
@@ -302,7 +302,7 @@ int iscsit_discard_unacknowledged_ooo_cmdsns_for_conn(struct iscsi_conn *conn)
                list_del(&cmd->i_conn_node);
 
                spin_unlock_bh(&conn->cmd_lock);
-               iscsit_free_cmd(cmd);
+               iscsit_free_cmd(cmd, true);
                spin_lock_bh(&conn->cmd_lock);
        }
        spin_unlock_bh(&conn->cmd_lock);
@@ -355,7 +355,7 @@ int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn)
 
                        list_del(&cmd->i_conn_node);
                        spin_unlock_bh(&conn->cmd_lock);
-                       iscsit_free_cmd(cmd);
+                       iscsit_free_cmd(cmd, true);
                        spin_lock_bh(&conn->cmd_lock);
                        continue;
                }
@@ -375,7 +375,7 @@ int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn)
                     iscsi_sna_gte(cmd->cmd_sn, conn->sess->exp_cmd_sn)) {
                        list_del(&cmd->i_conn_node);
                        spin_unlock_bh(&conn->cmd_lock);
-                       iscsit_free_cmd(cmd);
+                       iscsit_free_cmd(cmd, true);
                        spin_lock_bh(&conn->cmd_lock);
                        continue;
                }
index f690be9..e382221 100644 (file)
@@ -436,7 +436,7 @@ int iscsi_create_default_params(struct iscsi_param_list **param_list_ptr)
        /*
         * Extra parameters for ISER from RFC-5046
         */
-       param = iscsi_set_default_param(pl, RDMAEXTENTIONS, INITIAL_RDMAEXTENTIONS,
+       param = iscsi_set_default_param(pl, RDMAEXTENSIONS, INITIAL_RDMAEXTENSIONS,
                        PHASE_OPERATIONAL, SCOPE_SESSION_WIDE, SENDER_BOTH,
                        TYPERANGE_BOOL_AND, USE_LEADING_ONLY);
        if (!param)
@@ -529,7 +529,7 @@ int iscsi_set_keys_to_negotiate(
                        SET_PSTATE_NEGOTIATE(param);
                } else if (!strcmp(param->name, OFMARKINT)) {
                        SET_PSTATE_NEGOTIATE(param);
-               } else if (!strcmp(param->name, RDMAEXTENTIONS)) {
+               } else if (!strcmp(param->name, RDMAEXTENSIONS)) {
                        if (iser == true)
                                SET_PSTATE_NEGOTIATE(param);
                } else if (!strcmp(param->name, INITIATORRECVDATASEGMENTLENGTH)) {
@@ -580,7 +580,7 @@ int iscsi_set_keys_irrelevant_for_discovery(
                        param->state &= ~PSTATE_NEGOTIATE;
                else if (!strcmp(param->name, OFMARKINT))
                        param->state &= ~PSTATE_NEGOTIATE;
-               else if (!strcmp(param->name, RDMAEXTENTIONS))
+               else if (!strcmp(param->name, RDMAEXTENSIONS))
                        param->state &= ~PSTATE_NEGOTIATE;
                else if (!strcmp(param->name, INITIATORRECVDATASEGMENTLENGTH))
                        param->state &= ~PSTATE_NEGOTIATE;
@@ -758,9 +758,9 @@ static int iscsi_add_notunderstood_response(
        }
        INIT_LIST_HEAD(&extra_response->er_list);
 
-       strncpy(extra_response->key, key, strlen(key) + 1);
-       strncpy(extra_response->value, NOTUNDERSTOOD,
-                       strlen(NOTUNDERSTOOD) + 1);
+       strlcpy(extra_response->key, key, sizeof(extra_response->key));
+       strlcpy(extra_response->value, NOTUNDERSTOOD,
+               sizeof(extra_response->value));
 
        list_add_tail(&extra_response->er_list,
                        &param_list->extra_response_list);
@@ -1629,8 +1629,6 @@ int iscsi_decode_text_input(
 
                if (phase & PHASE_SECURITY) {
                        if (iscsi_check_for_auth_key(key) > 0) {
-                               char *tmpptr = key + strlen(key);
-                               *tmpptr = '=';
                                kfree(tmpbuf);
                                return 1;
                        }
@@ -1977,7 +1975,7 @@ void iscsi_set_session_parameters(
                        ops->SessionType = !strcmp(param->value, DISCOVERY);
                        pr_debug("SessionType:                  %s\n",
                                param->value);
-               } else if (!strcmp(param->name, RDMAEXTENTIONS)) {
+               } else if (!strcmp(param->name, RDMAEXTENSIONS)) {
                        ops->RDMAExtensions = !strcmp(param->value, YES);
                        pr_debug("RDMAExtensions:               %s\n",
                                param->value);
index f31b9c4..a47046a 100644 (file)
@@ -1,8 +1,10 @@
 #ifndef ISCSI_PARAMETERS_H
 #define ISCSI_PARAMETERS_H
 
+#include <scsi/iscsi_proto.h>
+
 struct iscsi_extra_response {
-       char key[64];
+       char key[KEY_MAXLEN];
        char value[32];
        struct list_head er_list;
 } ____cacheline_aligned;
@@ -91,7 +93,7 @@ extern void iscsi_set_session_parameters(struct iscsi_sess_ops *,
 /*
  * Parameter names of iSCSI Extentions for RDMA (iSER).  See RFC-5046
  */
-#define RDMAEXTENTIONS                 "RDMAExtensions"
+#define RDMAEXTENSIONS                 "RDMAExtensions"
 #define INITIATORRECVDATASEGMENTLENGTH "InitiatorRecvDataSegmentLength"
 #define TARGETRECVDATASEGMENTLENGTH    "TargetRecvDataSegmentLength"
 
@@ -142,7 +144,7 @@ extern void iscsi_set_session_parameters(struct iscsi_sess_ops *,
 /*
  * Initial values for iSER parameters following RFC-5046 Section 6
  */
-#define INITIAL_RDMAEXTENTIONS                 NO
+#define INITIAL_RDMAEXTENSIONS                 NO
 #define INITIAL_INITIATORRECVDATASEGMENTLENGTH "262144"
 #define INITIAL_TARGETRECVDATASEGMENTLENGTH    "8192"
 
index 2cc6c9a..08a3bac 100644 (file)
@@ -676,40 +676,56 @@ void iscsit_free_queue_reqs_for_conn(struct iscsi_conn *conn)
 
 void iscsit_release_cmd(struct iscsi_cmd *cmd)
 {
-       struct iscsi_conn *conn = cmd->conn;
-
-       iscsit_free_r2ts_from_list(cmd);
-       iscsit_free_all_datain_reqs(cmd);
-
        kfree(cmd->buf_ptr);
        kfree(cmd->pdu_list);
        kfree(cmd->seq_list);
        kfree(cmd->tmr_req);
        kfree(cmd->iov_data);
 
-       if (conn) {
+       kmem_cache_free(lio_cmd_cache, cmd);
+}
+
+static void __iscsit_free_cmd(struct iscsi_cmd *cmd, bool scsi_cmd,
+                             bool check_queues)
+{
+       struct iscsi_conn *conn = cmd->conn;
+
+       if (scsi_cmd) {
+               if (cmd->data_direction == DMA_TO_DEVICE) {
+                       iscsit_stop_dataout_timer(cmd);
+                       iscsit_free_r2ts_from_list(cmd);
+               }
+               if (cmd->data_direction == DMA_FROM_DEVICE)
+                       iscsit_free_all_datain_reqs(cmd);
+       }
+
+       if (conn && check_queues) {
                iscsit_remove_cmd_from_immediate_queue(cmd, conn);
                iscsit_remove_cmd_from_response_queue(cmd, conn);
        }
-
-       kmem_cache_free(lio_cmd_cache, cmd);
 }
 
-void iscsit_free_cmd(struct iscsi_cmd *cmd)
+void iscsit_free_cmd(struct iscsi_cmd *cmd, bool shutdown)
 {
+       struct se_cmd *se_cmd = NULL;
+       int rc;
        /*
         * Determine if a struct se_cmd is associated with
         * this struct iscsi_cmd.
         */
        switch (cmd->iscsi_opcode) {
        case ISCSI_OP_SCSI_CMD:
-               if (cmd->data_direction == DMA_TO_DEVICE)
-                       iscsit_stop_dataout_timer(cmd);
+               se_cmd = &cmd->se_cmd;
+               __iscsit_free_cmd(cmd, true, shutdown);
                /*
                 * Fallthrough
                 */
        case ISCSI_OP_SCSI_TMFUNC:
-               transport_generic_free_cmd(&cmd->se_cmd, 1);
+               rc = transport_generic_free_cmd(&cmd->se_cmd, 1);
+               if (!rc && shutdown && se_cmd && se_cmd->se_sess) {
+                       __iscsit_free_cmd(cmd, true, shutdown);
+                       target_put_sess_cmd(se_cmd->se_sess, se_cmd);
+               }
                break;
        case ISCSI_OP_REJECT:
                /*
@@ -718,11 +734,19 @@ void iscsit_free_cmd(struct iscsi_cmd *cmd)
                 * associated cmd->se_cmd needs to be released.
                 */
                if (cmd->se_cmd.se_tfo != NULL) {
-                       transport_generic_free_cmd(&cmd->se_cmd, 1);
+                       se_cmd = &cmd->se_cmd;
+                       __iscsit_free_cmd(cmd, true, shutdown);
+
+                       rc = transport_generic_free_cmd(&cmd->se_cmd, 1);
+                       if (!rc && shutdown && se_cmd->se_sess) {
+                               __iscsit_free_cmd(cmd, true, shutdown);
+                               target_put_sess_cmd(se_cmd->se_sess, se_cmd);
+                       }
                        break;
                }
                /* Fall-through */
        default:
+               __iscsit_free_cmd(cmd, false, shutdown);
                cmd->release_cmd(cmd);
                break;
        }
index 4f8e01a..a442265 100644 (file)
@@ -29,7 +29,7 @@ extern void iscsit_remove_cmd_from_tx_queues(struct iscsi_cmd *, struct iscsi_co
 extern bool iscsit_conn_all_queues_empty(struct iscsi_conn *);
 extern void iscsit_free_queue_reqs_for_conn(struct iscsi_conn *);
 extern void iscsit_release_cmd(struct iscsi_cmd *);
-extern void iscsit_free_cmd(struct iscsi_cmd *);
+extern void iscsit_free_cmd(struct iscsi_cmd *, bool);
 extern int iscsit_check_session_usage_count(struct iscsi_session *);
 extern void iscsit_dec_session_usage_count(struct iscsi_session *);
 extern void iscsit_inc_session_usage_count(struct iscsi_session *);
index 43b7ac6..4a8bd36 100644 (file)
@@ -1584,6 +1584,13 @@ static struct target_core_configfs_attribute target_core_attr_dev_udev_path = {
        .store  = target_core_store_dev_udev_path,
 };
 
+static ssize_t target_core_show_dev_enable(void *p, char *page)
+{
+       struct se_device *dev = p;
+
+       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,
@@ -1609,8 +1616,8 @@ static ssize_t target_core_store_dev_enable(
 static struct target_core_configfs_attribute target_core_attr_dev_enable = {
        .attr   = { .ca_owner = THIS_MODULE,
                    .ca_name = "enable",
-                   .ca_mode = S_IWUSR },
-       .show   = NULL,
+                   .ca_mode =  S_IRUGO | S_IWUSR },
+       .show   = target_core_show_dev_enable,
        .store  = target_core_store_dev_enable,
 };
 
index 2e4d655..4630481 100644 (file)
@@ -68,7 +68,6 @@ transport_lookup_cmd_lun(struct se_cmd *se_cmd, u32 unpacked_lun)
                struct se_dev_entry *deve = se_cmd->se_deve;
 
                deve->total_cmds++;
-               deve->total_bytes += se_cmd->data_length;
 
                if ((se_cmd->data_direction == DMA_TO_DEVICE) &&
                    (deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY)) {
@@ -85,8 +84,6 @@ transport_lookup_cmd_lun(struct se_cmd *se_cmd, u32 unpacked_lun)
                else if (se_cmd->data_direction == DMA_FROM_DEVICE)
                        deve->read_bytes += se_cmd->data_length;
 
-               deve->deve_cmds++;
-
                se_lun = deve->se_lun;
                se_cmd->se_lun = deve->se_lun;
                se_cmd->pr_res_key = deve->pr_res_key;
@@ -275,17 +272,6 @@ int core_free_device_list_for_node(
        return 0;
 }
 
-void core_dec_lacl_count(struct se_node_acl *se_nacl, struct se_cmd *se_cmd)
-{
-       struct se_dev_entry *deve;
-       unsigned long flags;
-
-       spin_lock_irqsave(&se_nacl->device_list_lock, flags);
-       deve = se_nacl->device_list[se_cmd->orig_fe_lun];
-       deve->deve_cmds--;
-       spin_unlock_irqrestore(&se_nacl->device_list_lock, flags);
-}
-
 void core_update_device_list_access(
        u32 mapped_lun,
        u32 lun_access,
index 58ed683..b11890d 100644 (file)
@@ -153,10 +153,7 @@ static int fd_configure_device(struct se_device *dev)
                struct request_queue *q = bdev_get_queue(inode->i_bdev);
                unsigned long long dev_size;
 
-               dev->dev_attrib.hw_block_size =
-                       bdev_logical_block_size(inode->i_bdev);
-               dev->dev_attrib.hw_max_sectors = queue_max_hw_sectors(q);
-
+               fd_dev->fd_block_size = bdev_logical_block_size(inode->i_bdev);
                /*
                 * Determine the number of bytes from i_size_read() minus
                 * one (1) logical sector from underlying struct block_device
@@ -203,9 +200,7 @@ static int fd_configure_device(struct se_device *dev)
                        goto fail;
                }
 
-               dev->dev_attrib.hw_block_size = FD_BLOCKSIZE;
-               dev->dev_attrib.hw_max_sectors = FD_MAX_SECTORS;
-
+               fd_dev->fd_block_size = FD_BLOCKSIZE;
                /*
                 * Limit UNMAP emulation to 8k Number of LBAs (NoLB)
                 */
@@ -224,8 +219,8 @@ static int fd_configure_device(struct se_device *dev)
                dev->dev_attrib.max_write_same_len = 0x1000;
        }
 
-       fd_dev->fd_block_size = dev->dev_attrib.hw_block_size;
-
+       dev->dev_attrib.hw_block_size = fd_dev->fd_block_size;
+       dev->dev_attrib.hw_max_sectors = FD_MAX_SECTORS;
        dev->dev_attrib.hw_queue_depth = FD_MAX_DEVICE_QUEUE_DEPTH;
 
        if (fd_dev->fbd_flags & FDBD_HAS_BUFFERED_IO_WCE) {
@@ -699,11 +694,12 @@ static sector_t fd_get_blocks(struct se_device *dev)
         * to handle underlying block_device resize operations.
         */
        if (S_ISBLK(i->i_mode))
-               dev_size = (i_size_read(i) - fd_dev->fd_block_size);
+               dev_size = i_size_read(i);
        else
                dev_size = fd_dev->fd_dev_size;
 
-       return div_u64(dev_size, dev->dev_attrib.block_size);
+       return div_u64(dev_size - dev->dev_attrib.block_size,
+                      dev->dev_attrib.block_size);
 }
 
 static struct sbc_ops fd_sbc_ops = {
index 07f5f94..aa1620a 100644 (file)
@@ -615,6 +615,8 @@ iblock_execute_rw(struct se_cmd *cmd)
                                rw = WRITE_FUA;
                        else if (!(q->flush_flags & REQ_FLUSH))
                                rw = WRITE_FUA;
+                       else
+                               rw = WRITE;
                } else {
                        rw = WRITE;
                }
index 853bab6..18d49df 100644 (file)
@@ -8,7 +8,6 @@ extern struct t10_alua_lu_gp *default_lu_gp;
 struct se_dev_entry *core_get_se_deve_from_rtpi(struct se_node_acl *, u16);
 int    core_free_device_list_for_node(struct se_node_acl *,
                struct se_portal_group *);
-void   core_dec_lacl_count(struct se_node_acl *, struct se_cmd *);
 void   core_update_device_list_access(u32, u32, struct se_node_acl *);
 int    core_enable_device_list_for_node(struct se_lun *, struct se_lun_acl *,
                u32, u32, struct se_node_acl *, struct se_portal_group *);
index e0b3c37..0921a64 100644 (file)
@@ -291,6 +291,11 @@ rd_execute_rw(struct se_cmd *cmd)
        u32 src_len;
        u64 tmp;
 
+       if (dev->rd_flags & RDF_NULLIO) {
+               target_complete_cmd(cmd, SAM_STAT_GOOD);
+               return 0;
+       }
+
        tmp = cmd->t_task_lba * se_dev->dev_attrib.block_size;
        rd_offset = do_div(tmp, PAGE_SIZE);
        rd_page = tmp;
@@ -373,11 +378,12 @@ rd_execute_rw(struct se_cmd *cmd)
 }
 
 enum {
-       Opt_rd_pages, Opt_err
+       Opt_rd_pages, Opt_rd_nullio, Opt_err
 };
 
 static match_table_t tokens = {
        {Opt_rd_pages, "rd_pages=%d"},
+       {Opt_rd_nullio, "rd_nullio=%d"},
        {Opt_err, NULL}
 };
 
@@ -408,6 +414,14 @@ static ssize_t rd_set_configfs_dev_params(struct se_device *dev,
                                " Count: %u\n", rd_dev->rd_page_count);
                        rd_dev->rd_flags |= RDF_HAS_PAGE_COUNT;
                        break;
+               case Opt_rd_nullio:
+                       match_int(args, &arg);
+                       if (arg != 1)
+                               break;
+
+                       pr_debug("RAMDISK: Setting NULLIO flag: %d\n", arg);
+                       rd_dev->rd_flags |= RDF_NULLIO;
+                       break;
                default:
                        break;
                }
@@ -424,8 +438,9 @@ static ssize_t rd_show_configfs_dev_params(struct se_device *dev, char *b)
        ssize_t bl = sprintf(b, "TCM RamDisk ID: %u  RamDisk Makeup: rd_mcp\n",
                        rd_dev->rd_dev_id);
        bl += sprintf(b + bl, "        PAGES/PAGE_SIZE: %u*%lu"
-                       "  SG_table_count: %u\n", rd_dev->rd_page_count,
-                       PAGE_SIZE, rd_dev->sg_table_count);
+                       "  SG_table_count: %u  nullio: %d\n", rd_dev->rd_page_count,
+                       PAGE_SIZE, rd_dev->sg_table_count,
+                       !!(rd_dev->rd_flags & RDF_NULLIO));
        return bl;
 }
 
index 933b38b..1789d1e 100644 (file)
@@ -22,6 +22,7 @@ struct rd_dev_sg_table {
 } ____cacheline_aligned;
 
 #define RDF_HAS_PAGE_COUNT     0x01
+#define RDF_NULLIO             0x02
 
 struct rd_dev {
        struct se_device dev;
index f8388b4..21e3158 100644 (file)
@@ -65,7 +65,7 @@ static void transport_complete_task_attr(struct se_cmd *cmd);
 static void transport_handle_queue_full(struct se_cmd *cmd,
                struct se_device *dev);
 static int transport_generic_get_mem(struct se_cmd *cmd);
-static void transport_put_cmd(struct se_cmd *cmd);
+static int transport_put_cmd(struct se_cmd *cmd);
 static void target_complete_ok_work(struct work_struct *work);
 
 int init_se_kmem_caches(void)
@@ -221,6 +221,7 @@ struct se_session *transport_init_session(void)
        INIT_LIST_HEAD(&se_sess->sess_list);
        INIT_LIST_HEAD(&se_sess->sess_acl_list);
        INIT_LIST_HEAD(&se_sess->sess_cmd_list);
+       INIT_LIST_HEAD(&se_sess->sess_wait_list);
        spin_lock_init(&se_sess->sess_cmd_lock);
        kref_init(&se_sess->sess_kref);
 
@@ -1943,7 +1944,7 @@ static inline void transport_free_pages(struct se_cmd *cmd)
  * This routine unconditionally frees a command, and reference counting
  * or list removal must be done in the caller.
  */
-static void transport_release_cmd(struct se_cmd *cmd)
+static int transport_release_cmd(struct se_cmd *cmd)
 {
        BUG_ON(!cmd->se_tfo);
 
@@ -1955,11 +1956,11 @@ static void transport_release_cmd(struct se_cmd *cmd)
         * If this cmd has been setup with target_get_sess_cmd(), drop
         * the kref and call ->release_cmd() in kref callback.
         */
-        if (cmd->check_release != 0) {
-               target_put_sess_cmd(cmd->se_sess, cmd);
-               return;
-       }
+        if (cmd->check_release != 0)
+               return target_put_sess_cmd(cmd->se_sess, cmd);
+
        cmd->se_tfo->release_cmd(cmd);
+       return 1;
 }
 
 /**
@@ -1968,7 +1969,7 @@ static void transport_release_cmd(struct se_cmd *cmd)
  *
  * This routine releases our reference to the command and frees it if possible.
  */
-static void transport_put_cmd(struct se_cmd *cmd)
+static int transport_put_cmd(struct se_cmd *cmd)
 {
        unsigned long flags;
 
@@ -1976,7 +1977,7 @@ static void transport_put_cmd(struct se_cmd *cmd)
        if (atomic_read(&cmd->t_fe_count) &&
            !atomic_dec_and_test(&cmd->t_fe_count)) {
                spin_unlock_irqrestore(&cmd->t_state_lock, flags);
-               return;
+               return 0;
        }
 
        if (cmd->transport_state & CMD_T_DEV_ACTIVE) {
@@ -1986,8 +1987,7 @@ static void transport_put_cmd(struct se_cmd *cmd)
        spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 
        transport_free_pages(cmd);
-       transport_release_cmd(cmd);
-       return;
+       return transport_release_cmd(cmd);
 }
 
 void *transport_kmap_data_sg(struct se_cmd *cmd)
@@ -2152,24 +2152,25 @@ static void transport_write_pending_qf(struct se_cmd *cmd)
        }
 }
 
-void transport_generic_free_cmd(struct se_cmd *cmd, int wait_for_tasks)
+int transport_generic_free_cmd(struct se_cmd *cmd, int wait_for_tasks)
 {
+       int ret = 0;
+
        if (!(cmd->se_cmd_flags & SCF_SE_LUN_CMD)) {
                if (wait_for_tasks && (cmd->se_cmd_flags & SCF_SCSI_TMR_CDB))
                         transport_wait_for_tasks(cmd);
 
-               transport_release_cmd(cmd);
+               ret = transport_release_cmd(cmd);
        } else {
                if (wait_for_tasks)
                        transport_wait_for_tasks(cmd);
 
-               core_dec_lacl_count(cmd->se_sess->se_node_acl, cmd);
-
                if (cmd->se_lun)
                        transport_lun_remove_cmd(cmd);
 
-               transport_put_cmd(cmd);
+               ret = transport_put_cmd(cmd);
        }
+       return ret;
 }
 EXPORT_SYMBOL(transport_generic_free_cmd);
 
@@ -2213,21 +2214,19 @@ static void target_release_cmd_kref(struct kref *kref)
 {
        struct se_cmd *se_cmd = container_of(kref, struct se_cmd, cmd_kref);
        struct se_session *se_sess = se_cmd->se_sess;
-       unsigned long flags;
 
-       spin_lock_irqsave(&se_sess->sess_cmd_lock, flags);
        if (list_empty(&se_cmd->se_cmd_list)) {
-               spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
+               spin_unlock(&se_sess->sess_cmd_lock);
                se_cmd->se_tfo->release_cmd(se_cmd);
                return;
        }
        if (se_sess->sess_tearing_down && se_cmd->cmd_wait_set) {
-               spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
+               spin_unlock(&se_sess->sess_cmd_lock);
                complete(&se_cmd->cmd_wait_comp);
                return;
        }
        list_del(&se_cmd->se_cmd_list);
-       spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
+       spin_unlock(&se_sess->sess_cmd_lock);
 
        se_cmd->se_tfo->release_cmd(se_cmd);
 }
@@ -2238,7 +2237,8 @@ static void target_release_cmd_kref(struct kref *kref)
  */
 int target_put_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd)
 {
-       return kref_put(&se_cmd->cmd_kref, target_release_cmd_kref);
+       return kref_put_spinlock_irqsave(&se_cmd->cmd_kref, target_release_cmd_kref,
+                       &se_sess->sess_cmd_lock);
 }
 EXPORT_SYMBOL(target_put_sess_cmd);
 
@@ -2253,11 +2253,14 @@ void target_sess_cmd_list_set_waiting(struct se_session *se_sess)
        unsigned long flags;
 
        spin_lock_irqsave(&se_sess->sess_cmd_lock, flags);
-
-       WARN_ON(se_sess->sess_tearing_down);
+       if (se_sess->sess_tearing_down) {
+               spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
+               return;
+       }
        se_sess->sess_tearing_down = 1;
+       list_splice_init(&se_sess->sess_cmd_list, &se_sess->sess_wait_list);
 
-       list_for_each_entry(se_cmd, &se_sess->sess_cmd_list, se_cmd_list)
+       list_for_each_entry(se_cmd, &se_sess->sess_wait_list, se_cmd_list)
                se_cmd->cmd_wait_set = 1;
 
        spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
@@ -2266,44 +2269,32 @@ EXPORT_SYMBOL(target_sess_cmd_list_set_waiting);
 
 /* target_wait_for_sess_cmds - Wait for outstanding descriptors
  * @se_sess:    session to wait for active I/O
- * @wait_for_tasks:    Make extra transport_wait_for_tasks call
  */
-void target_wait_for_sess_cmds(
-       struct se_session *se_sess,
-       int wait_for_tasks)
+void target_wait_for_sess_cmds(struct se_session *se_sess)
 {
        struct se_cmd *se_cmd, *tmp_cmd;
-       bool rc = false;
+       unsigned long flags;
 
        list_for_each_entry_safe(se_cmd, tmp_cmd,
-                               &se_sess->sess_cmd_list, se_cmd_list) {
+                               &se_sess->sess_wait_list, se_cmd_list) {
                list_del(&se_cmd->se_cmd_list);
 
                pr_debug("Waiting for se_cmd: %p t_state: %d, fabric state:"
                        " %d\n", se_cmd, se_cmd->t_state,
                        se_cmd->se_tfo->get_cmd_state(se_cmd));
 
-               if (wait_for_tasks) {
-                       pr_debug("Calling transport_wait_for_tasks se_cmd: %p t_state: %d,"
-                               " fabric state: %d\n", se_cmd, se_cmd->t_state,
-                               se_cmd->se_tfo->get_cmd_state(se_cmd));
-
-                       rc = transport_wait_for_tasks(se_cmd);
-
-                       pr_debug("After transport_wait_for_tasks se_cmd: %p t_state: %d,"
-                               " fabric state: %d\n", se_cmd, se_cmd->t_state,
-                               se_cmd->se_tfo->get_cmd_state(se_cmd));
-               }
-
-               if (!rc) {
-                       wait_for_completion(&se_cmd->cmd_wait_comp);
-                       pr_debug("After cmd_wait_comp: se_cmd: %p t_state: %d"
-                               " fabric state: %d\n", se_cmd, se_cmd->t_state,
-                               se_cmd->se_tfo->get_cmd_state(se_cmd));
-               }
+               wait_for_completion(&se_cmd->cmd_wait_comp);
+               pr_debug("After cmd_wait_comp: se_cmd: %p t_state: %d"
+                       " fabric state: %d\n", se_cmd, se_cmd->t_state,
+                       se_cmd->se_tfo->get_cmd_state(se_cmd));
 
                se_cmd->se_tfo->release_cmd(se_cmd);
        }
+
+       spin_lock_irqsave(&se_sess->sess_cmd_lock, flags);
+       WARN_ON(!list_empty(&se_sess->sess_cmd_list));
+       spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
+
 }
 EXPORT_SYMBOL(target_wait_for_sess_cmds);
 
index 5b4d75f..54ffd64 100644 (file)
@@ -169,21 +169,11 @@ static int armada_thermal_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(&pdev->dev, "Failed to get platform resource\n");
-               return -ENODEV;
-       }
-
        priv->sensor = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(priv->sensor))
                return PTR_ERR(priv->sensor);
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-       if (!res) {
-               dev_err(&pdev->dev, "Failed to get platform resource\n");
-               return -ENODEV;
-       }
-
        priv->control = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(priv->control))
                return PTR_ERR(priv->control);
index 4b15a5f..a088d13 100644 (file)
@@ -149,10 +149,6 @@ static int dove_thermal_probe(struct platform_device *pdev)
                return PTR_ERR(priv->sensor);
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-       if (!res) {
-               dev_err(&pdev->dev, "Failed to get platform resource\n");
-               return -ENODEV;
-       }
        priv->control = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(priv->control))
                return PTR_ERR(priv->control);
index d20ce9e..788b1dd 100644 (file)
@@ -925,11 +925,6 @@ static int exynos_tmu_probe(struct platform_device *pdev)
        INIT_WORK(&data->irq_work, exynos_tmu_work);
 
        data->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!data->mem) {
-               dev_err(&pdev->dev, "Failed to get platform resource\n");
-               return -ENOENT;
-       }
-
        data->base = devm_ioremap_resource(&pdev->dev, data->mem);
        if (IS_ERR(data->base))
                return PTR_ERR(data->base);
index 6d0c27c..9bffcec 100644 (file)
@@ -859,6 +859,7 @@ error:
  */
 static void __exit ehv_bc_exit(void)
 {
+       platform_driver_unregister(&ehv_bc_tty_driver);
        tty_unregister_driver(ehv_bc_driver);
        put_tty_driver(ehv_bc_driver);
        kfree(bcs);
index 71d6eb2..4c4a236 100644 (file)
@@ -1618,8 +1618,12 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
                                if (ip->type == PORT_16550A)
                                        me->fifo[p] = 1;
 
-                               opmode = inb(ip->opmode_ioaddr)>>((p % 4) * 2);
-                               opmode &= OP_MODE_MASK;
+                               if (ip->board->chip_flag == MOXA_MUST_MU860_HWID) {
+                                       opmode = inb(ip->opmode_ioaddr)>>((p % 4) * 2);
+                                       opmode &= OP_MODE_MASK;
+                               } else {
+                                       opmode = RS232_MODE;
+                               }
                                me->iftype[p] = opmode;
                                mutex_unlock(&port->mutex);
                        }
@@ -1676,6 +1680,9 @@ static int mxser_ioctl(struct tty_struct *tty,
                int shiftbit;
                unsigned char val, mask;
 
+               if (info->board->chip_flag != MOXA_MUST_MU860_HWID)
+                       return -EFAULT;
+
                p = tty->index % 4;
                if (cmd == MOXA_SET_OP_MODE) {
                        if (get_user(opmode, (int __user *) argp))
index d655416..6c7fe90 100644 (file)
@@ -1573,6 +1573,14 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
                        ldata->real_raw = 0;
        }
        n_tty_set_room(tty);
+       /*
+        * Fix tty hang when I_IXON(tty) is cleared, but the tty
+        * been stopped by STOP_CHAR(tty) before it.
+        */
+       if (!I_IXON(tty) && old && (old->c_iflag & IXON) && !tty->flow_stopped) {
+               start_tty(tty);
+       }
+
        /* The termios change make the tty ready for I/O */
        wake_up_interruptible(&tty->write_wait);
        wake_up_interruptible(&tty->read_wait);
index 82d35c5..354564e 100644 (file)
@@ -150,12 +150,14 @@ static Word_t aiop_intr_bits[AIOP_CTL_SIZE] = {
        AIOP_INTR_BIT_3
 };
 
+#ifdef CONFIG_PCI
 static Word_t upci_aiop_intr_bits[AIOP_CTL_SIZE] = {
        UPCI_AIOP_INTR_BIT_0,
        UPCI_AIOP_INTR_BIT_1,
        UPCI_AIOP_INTR_BIT_2,
        UPCI_AIOP_INTR_BIT_3
 };
+#endif
 
 static Byte_t RData[RDATASIZE] = {
        0x00, 0x09, 0xf6, 0x82,
@@ -227,7 +229,6 @@ static unsigned long nextLineNumber;
 static int __init init_ISA(int i);
 static void rp_wait_until_sent(struct tty_struct *tty, int timeout);
 static void rp_flush_buffer(struct tty_struct *tty);
-static void rmSpeakerReset(CONTROLLER_T * CtlP, unsigned long model);
 static unsigned char GetLineNumber(int ctrl, int aiop, int ch);
 static unsigned char SetLineNumber(int ctrl, int aiop, int ch);
 static void rp_start(struct tty_struct *tty);
@@ -241,11 +242,6 @@ static void sDisInterrupts(CHANNEL_T * ChP, Word_t Flags);
 static void sModemReset(CONTROLLER_T * CtlP, int chan, int on);
 static void sPCIModemReset(CONTROLLER_T * CtlP, int chan, int on);
 static int sWriteTxPrioByte(CHANNEL_T * ChP, Byte_t Data);
-static int sPCIInitController(CONTROLLER_T * CtlP, int CtlNum,
-                             ByteIO_t * AiopIOList, int AiopIOListSize,
-                             WordIO_t ConfigIO, int IRQNum, Byte_t Frequency,
-                             int PeriodicOnly, int altChanRingIndicator,
-                             int UPCIRingInd);
 static int sInitController(CONTROLLER_T * CtlP, int CtlNum, ByteIO_t MudbacIO,
                           ByteIO_t * AiopIOList, int AiopIOListSize,
                           int IRQNum, Byte_t Frequency, int PeriodicOnly);
@@ -1775,6 +1771,145 @@ static DEFINE_PCI_DEVICE_TABLE(rocket_pci_ids) = {
 };
 MODULE_DEVICE_TABLE(pci, rocket_pci_ids);
 
+/*  Resets the speaker controller on RocketModem II and III devices */
+static void rmSpeakerReset(CONTROLLER_T * CtlP, unsigned long model)
+{
+       ByteIO_t addr;
+
+       /* RocketModem II speaker control is at the 8th port location of offset 0x40 */
+       if ((model == MODEL_RP4M) || (model == MODEL_RP6M)) {
+               addr = CtlP->AiopIO[0] + 0x4F;
+               sOutB(addr, 0);
+       }
+
+       /* RocketModem III speaker control is at the 1st port location of offset 0x80 */
+       if ((model == MODEL_UPCI_RM3_8PORT)
+           || (model == MODEL_UPCI_RM3_4PORT)) {
+               addr = CtlP->AiopIO[0] + 0x88;
+               sOutB(addr, 0);
+       }
+}
+
+/***************************************************************************
+Function: sPCIInitController
+Purpose:  Initialization of controller global registers and controller
+          structure.
+Call:     sPCIInitController(CtlP,CtlNum,AiopIOList,AiopIOListSize,
+                          IRQNum,Frequency,PeriodicOnly)
+          CONTROLLER_T *CtlP; Ptr to controller structure
+          int CtlNum; Controller number
+          ByteIO_t *AiopIOList; List of I/O addresses for each AIOP.
+             This list must be in the order the AIOPs will be found on the
+             controller.  Once an AIOP in the list is not found, it is
+             assumed that there are no more AIOPs on the controller.
+          int AiopIOListSize; Number of addresses in AiopIOList
+          int IRQNum; Interrupt Request number.  Can be any of the following:
+                         0: Disable global interrupts
+                         3: IRQ 3
+                         4: IRQ 4
+                         5: IRQ 5
+                         9: IRQ 9
+                         10: IRQ 10
+                         11: IRQ 11
+                         12: IRQ 12
+                         15: IRQ 15
+          Byte_t Frequency: A flag identifying the frequency
+                   of the periodic interrupt, can be any one of the following:
+                      FREQ_DIS - periodic interrupt disabled
+                      FREQ_137HZ - 137 Hertz
+                      FREQ_69HZ - 69 Hertz
+                      FREQ_34HZ - 34 Hertz
+                      FREQ_17HZ - 17 Hertz
+                      FREQ_9HZ - 9 Hertz
+                      FREQ_4HZ - 4 Hertz
+                   If IRQNum is set to 0 the Frequency parameter is
+                   overidden, it is forced to a value of FREQ_DIS.
+          int PeriodicOnly: 1 if all interrupts except the periodic
+                               interrupt are to be blocked.
+                            0 is both the periodic interrupt and
+                               other channel interrupts are allowed.
+                            If IRQNum is set to 0 the PeriodicOnly parameter is
+                               overidden, it is forced to a value of 0.
+Return:   int: Number of AIOPs on the controller, or CTLID_NULL if controller
+               initialization failed.
+
+Comments:
+          If periodic interrupts are to be disabled but AIOP interrupts
+          are allowed, set Frequency to FREQ_DIS and PeriodicOnly to 0.
+
+          If interrupts are to be completely disabled set IRQNum to 0.
+
+          Setting Frequency to FREQ_DIS and PeriodicOnly to 1 is an
+          invalid combination.
+
+          This function performs initialization of global interrupt modes,
+          but it does not actually enable global interrupts.  To enable
+          and disable global interrupts use functions sEnGlobalInt() and
+          sDisGlobalInt().  Enabling of global interrupts is normally not
+          done until all other initializations are complete.
+
+          Even if interrupts are globally enabled, they must also be
+          individually enabled for each channel that is to generate
+          interrupts.
+
+Warnings: No range checking on any of the parameters is done.
+
+          No context switches are allowed while executing this function.
+
+          After this function all AIOPs on the controller are disabled,
+          they can be enabled with sEnAiop().
+*/
+static int sPCIInitController(CONTROLLER_T * CtlP, int CtlNum,
+                             ByteIO_t * AiopIOList, int AiopIOListSize,
+                             WordIO_t ConfigIO, int IRQNum, Byte_t Frequency,
+                             int PeriodicOnly, int altChanRingIndicator,
+                             int UPCIRingInd)
+{
+       int i;
+       ByteIO_t io;
+
+       CtlP->AltChanRingIndicator = altChanRingIndicator;
+       CtlP->UPCIRingInd = UPCIRingInd;
+       CtlP->CtlNum = CtlNum;
+       CtlP->CtlID = CTLID_0001;       /* controller release 1 */
+       CtlP->BusType = isPCI;  /* controller release 1 */
+
+       if (ConfigIO) {
+               CtlP->isUPCI = 1;
+               CtlP->PCIIO = ConfigIO + _PCI_9030_INT_CTRL;
+               CtlP->PCIIO2 = ConfigIO + _PCI_9030_GPIO_CTRL;
+               CtlP->AiopIntrBits = upci_aiop_intr_bits;
+       } else {
+               CtlP->isUPCI = 0;
+               CtlP->PCIIO =
+                   (WordIO_t) ((ByteIO_t) AiopIOList[0] + _PCI_INT_FUNC);
+               CtlP->AiopIntrBits = aiop_intr_bits;
+       }
+
+       sPCIControllerEOI(CtlP);        /* clear EOI if warm init */
+       /* Init AIOPs */
+       CtlP->NumAiop = 0;
+       for (i = 0; i < AiopIOListSize; i++) {
+               io = AiopIOList[i];
+               CtlP->AiopIO[i] = (WordIO_t) io;
+               CtlP->AiopIntChanIO[i] = io + _INT_CHAN;
+
+               CtlP->AiopID[i] = sReadAiopID(io);      /* read AIOP ID */
+               if (CtlP->AiopID[i] == AIOPID_NULL)     /* if AIOP does not exist */
+                       break;  /* done looking for AIOPs */
+
+               CtlP->AiopNumChan[i] = sReadAiopNumChan((WordIO_t) io); /* num channels in AIOP */
+               sOutW((WordIO_t) io + _INDX_ADDR, _CLK_PRE);    /* clock prescaler */
+               sOutB(io + _INDX_DATA, sClockPrescale);
+               CtlP->NumAiop++;        /* bump count of AIOPs */
+       }
+
+       if (CtlP->NumAiop == 0)
+               return (-1);
+       else
+               return (CtlP->NumAiop);
+}
+
 /*
  *  Called when a PCI card is found.  Retrieves and stores model information,
  *  init's aiopic and serial port hardware.
@@ -2519,147 +2654,6 @@ static int sInitController(CONTROLLER_T * CtlP, int CtlNum, ByteIO_t MudbacIO,
                return (CtlP->NumAiop);
 }
 
-#ifdef CONFIG_PCI
-/***************************************************************************
-Function: sPCIInitController
-Purpose:  Initialization of controller global registers and controller
-          structure.
-Call:     sPCIInitController(CtlP,CtlNum,AiopIOList,AiopIOListSize,
-                          IRQNum,Frequency,PeriodicOnly)
-          CONTROLLER_T *CtlP; Ptr to controller structure
-          int CtlNum; Controller number
-          ByteIO_t *AiopIOList; List of I/O addresses for each AIOP.
-             This list must be in the order the AIOPs will be found on the
-             controller.  Once an AIOP in the list is not found, it is
-             assumed that there are no more AIOPs on the controller.
-          int AiopIOListSize; Number of addresses in AiopIOList
-          int IRQNum; Interrupt Request number.  Can be any of the following:
-                         0: Disable global interrupts
-                         3: IRQ 3
-                         4: IRQ 4
-                         5: IRQ 5
-                         9: IRQ 9
-                         10: IRQ 10
-                         11: IRQ 11
-                         12: IRQ 12
-                         15: IRQ 15
-          Byte_t Frequency: A flag identifying the frequency
-                   of the periodic interrupt, can be any one of the following:
-                      FREQ_DIS - periodic interrupt disabled
-                      FREQ_137HZ - 137 Hertz
-                      FREQ_69HZ - 69 Hertz
-                      FREQ_34HZ - 34 Hertz
-                      FREQ_17HZ - 17 Hertz
-                      FREQ_9HZ - 9 Hertz
-                      FREQ_4HZ - 4 Hertz
-                   If IRQNum is set to 0 the Frequency parameter is
-                   overidden, it is forced to a value of FREQ_DIS.
-          int PeriodicOnly: 1 if all interrupts except the periodic
-                               interrupt are to be blocked.
-                            0 is both the periodic interrupt and
-                               other channel interrupts are allowed.
-                            If IRQNum is set to 0 the PeriodicOnly parameter is
-                               overidden, it is forced to a value of 0.
-Return:   int: Number of AIOPs on the controller, or CTLID_NULL if controller
-               initialization failed.
-
-Comments:
-          If periodic interrupts are to be disabled but AIOP interrupts
-          are allowed, set Frequency to FREQ_DIS and PeriodicOnly to 0.
-
-          If interrupts are to be completely disabled set IRQNum to 0.
-
-          Setting Frequency to FREQ_DIS and PeriodicOnly to 1 is an
-          invalid combination.
-
-          This function performs initialization of global interrupt modes,
-          but it does not actually enable global interrupts.  To enable
-          and disable global interrupts use functions sEnGlobalInt() and
-          sDisGlobalInt().  Enabling of global interrupts is normally not
-          done until all other initializations are complete.
-
-          Even if interrupts are globally enabled, they must also be
-          individually enabled for each channel that is to generate
-          interrupts.
-
-Warnings: No range checking on any of the parameters is done.
-
-          No context switches are allowed while executing this function.
-
-          After this function all AIOPs on the controller are disabled,
-          they can be enabled with sEnAiop().
-*/
-static int sPCIInitController(CONTROLLER_T * CtlP, int CtlNum,
-                             ByteIO_t * AiopIOList, int AiopIOListSize,
-                             WordIO_t ConfigIO, int IRQNum, Byte_t Frequency,
-                             int PeriodicOnly, int altChanRingIndicator,
-                             int UPCIRingInd)
-{
-       int i;
-       ByteIO_t io;
-
-       CtlP->AltChanRingIndicator = altChanRingIndicator;
-       CtlP->UPCIRingInd = UPCIRingInd;
-       CtlP->CtlNum = CtlNum;
-       CtlP->CtlID = CTLID_0001;       /* controller release 1 */
-       CtlP->BusType = isPCI;  /* controller release 1 */
-
-       if (ConfigIO) {
-               CtlP->isUPCI = 1;
-               CtlP->PCIIO = ConfigIO + _PCI_9030_INT_CTRL;
-               CtlP->PCIIO2 = ConfigIO + _PCI_9030_GPIO_CTRL;
-               CtlP->AiopIntrBits = upci_aiop_intr_bits;
-       } else {
-               CtlP->isUPCI = 0;
-               CtlP->PCIIO =
-                   (WordIO_t) ((ByteIO_t) AiopIOList[0] + _PCI_INT_FUNC);
-               CtlP->AiopIntrBits = aiop_intr_bits;
-       }
-
-       sPCIControllerEOI(CtlP);        /* clear EOI if warm init */
-       /* Init AIOPs */
-       CtlP->NumAiop = 0;
-       for (i = 0; i < AiopIOListSize; i++) {
-               io = AiopIOList[i];
-               CtlP->AiopIO[i] = (WordIO_t) io;
-               CtlP->AiopIntChanIO[i] = io + _INT_CHAN;
-
-               CtlP->AiopID[i] = sReadAiopID(io);      /* read AIOP ID */
-               if (CtlP->AiopID[i] == AIOPID_NULL)     /* if AIOP does not exist */
-                       break;  /* done looking for AIOPs */
-
-               CtlP->AiopNumChan[i] = sReadAiopNumChan((WordIO_t) io); /* num channels in AIOP */
-               sOutW((WordIO_t) io + _INDX_ADDR, _CLK_PRE);    /* clock prescaler */
-               sOutB(io + _INDX_DATA, sClockPrescale);
-               CtlP->NumAiop++;        /* bump count of AIOPs */
-       }
-
-       if (CtlP->NumAiop == 0)
-               return (-1);
-       else
-               return (CtlP->NumAiop);
-}
-
-/*  Resets the speaker controller on RocketModem II and III devices */
-static void rmSpeakerReset(CONTROLLER_T * CtlP, unsigned long model)
-{
-       ByteIO_t addr;
-
-       /* RocketModem II speaker control is at the 8th port location of offset 0x40 */
-       if ((model == MODEL_RP4M) || (model == MODEL_RP6M)) {
-               addr = CtlP->AiopIO[0] + 0x4F;
-               sOutB(addr, 0);
-       }
-
-       /* RocketModem III speaker control is at the 1st port location of offset 0x80 */
-       if ((model == MODEL_UPCI_RM3_8PORT)
-           || (model == MODEL_UPCI_RM3_4PORT)) {
-               addr = CtlP->AiopIO[0] + 0x88;
-               sOutB(addr, 0);
-       }
-}
-#endif
-
 /***************************************************************************
 Function: sReadAiopID
 Purpose:  Read the AIOP idenfication number directly from an AIOP.
index 46528d5..86c00b1 100644 (file)
@@ -2755,7 +2755,7 @@ static void __init serial8250_isa_init_ports(void)
        if (nr_uarts > UART_NR)
                nr_uarts = UART_NR;
 
-       for (i = 0; i < UART_NR; i++) {
+       for (i = 0; i < nr_uarts; i++) {
                struct uart_8250_port *up = &serial8250_ports[i];
                struct uart_port *port = &up->port;
 
@@ -2916,7 +2916,7 @@ static int __init serial8250_console_setup(struct console *co, char *options)
         * if so, search for the first available port that does have
         * console support.
         */
-       if (co->index >= UART_NR)
+       if (co->index >= nr_uarts)
                co->index = 0;
        port = &serial8250_ports[co->index].port;
        if (!port->iobase && !port->membase)
@@ -2957,7 +2957,7 @@ int serial8250_find_port(struct uart_port *p)
        int line;
        struct uart_port *port;
 
-       for (line = 0; line < UART_NR; line++) {
+       for (line = 0; line < nr_uarts; line++) {
                port = &serial8250_ports[line].port;
                if (uart_match_port(p, port))
                        return line;
@@ -3110,7 +3110,7 @@ static int serial8250_remove(struct platform_device *dev)
 {
        int i;
 
-       for (i = 0; i < UART_NR; i++) {
+       for (i = 0; i < nr_uarts; i++) {
                struct uart_8250_port *up = &serial8250_ports[i];
 
                if (up->port.dev == &dev->dev)
@@ -3178,7 +3178,7 @@ static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port *
        /*
         * First, find a port entry which matches.
         */
-       for (i = 0; i < UART_NR; i++)
+       for (i = 0; i < nr_uarts; i++)
                if (uart_match_port(&serial8250_ports[i].port, port))
                        return &serial8250_ports[i];
 
@@ -3187,7 +3187,7 @@ static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port *
         * free entry.  We look for one which hasn't been previously
         * used (indicated by zero iobase).
         */
-       for (i = 0; i < UART_NR; i++)
+       for (i = 0; i < nr_uarts; i++)
                if (serial8250_ports[i].port.type == PORT_UNKNOWN &&
                    serial8250_ports[i].port.iobase == 0)
                        return &serial8250_ports[i];
@@ -3196,7 +3196,7 @@ static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port *
         * That also failed.  Last resort is to find any entry which
         * doesn't have a real port associated with it.
         */
-       for (i = 0; i < UART_NR; i++)
+       for (i = 0; i < nr_uarts; i++)
                if (serial8250_ports[i].port.type == PORT_UNKNOWN)
                        return &serial8250_ports[i];
 
index beaa283..d07b6af 100644 (file)
@@ -338,7 +338,8 @@ static int dw8250_runtime_suspend(struct device *dev)
 {
        struct dw8250_data *data = dev_get_drvdata(dev);
 
-       clk_disable_unprepare(data->clk);
+       if (!IS_ERR(data->clk))
+               clk_disable_unprepare(data->clk);
 
        return 0;
 }
@@ -347,7 +348,8 @@ static int dw8250_runtime_resume(struct device *dev)
 {
        struct dw8250_data *data = dev_get_drvdata(dev);
 
-       clk_prepare_enable(data->clk);
+       if (!IS_ERR(data->clk))
+               clk_prepare_enable(data->clk);
 
        return 0;
 }
@@ -367,6 +369,7 @@ MODULE_DEVICE_TABLE(of, dw8250_of_match);
 static const struct acpi_device_id dw8250_acpi_match[] = {
        { "INT33C4", 0 },
        { "INT33C5", 0 },
+       { "80860F0A", 0 },
        { },
 };
 MODULE_DEVICE_TABLE(acpi, dw8250_acpi_match);
index 8ab70a6..e2774f9 100644 (file)
@@ -332,7 +332,7 @@ static void pl011_dma_probe_initcall(struct device *dev, struct uart_amba_port *
                dmaengine_slave_config(chan, &rx_conf);
                uap->dmarx.chan = chan;
 
-               if (plat->dma_rx_poll_enable) {
+               if (plat && plat->dma_rx_poll_enable) {
                        /* Set poll rate if specified. */
                        if (plat->dma_rx_poll_rate) {
                                uap->dmarx.auto_poll_rate = false;
index 147c9e1..8cdfbd3 100644 (file)
@@ -761,6 +761,8 @@ static int imx_startup(struct uart_port *port)
 
        temp = readl(sport->port.membase + UCR2);
        temp |= (UCR2_RXEN | UCR2_TXEN);
+       if (!sport->have_rtscts)
+               temp |= UCR2_IRTS;
        writel(temp, sport->port.membase + UCR2);
 
        if (USE_IRDA(sport)) {
index e956377..65be0c0 100644 (file)
@@ -707,8 +707,10 @@ static int __init mcf_init(void)
        if (rc)
                return rc;
        rc = platform_driver_register(&mcf_platform_driver);
-       if (rc)
+       if (rc) {
+               uart_unregister_driver(&mcf_driver);
                return rc;
+       }
        return 0;
 }
 
index 018bad9..f51b280 100644 (file)
@@ -1497,18 +1497,23 @@ mpc52xx_uart_init(void)
        if (psc_ops && psc_ops->fifoc_init) {
                ret = psc_ops->fifoc_init();
                if (ret)
-                       return ret;
+                       goto err_init;
        }
 
        ret = platform_driver_register(&mpc52xx_uart_of_driver);
        if (ret) {
                printk(KERN_ERR "%s: platform_driver_register failed (%i)\n",
                       __FILE__, ret);
-               uart_unregister_driver(&mpc52xx_uart_driver);
-               return ret;
+               goto err_reg;
        }
 
        return 0;
+err_reg:
+       if (psc_ops && psc_ops->fifoc_uninit)
+               psc_ops->fifoc_uninit();
+err_init:
+       uart_unregister_driver(&mpc52xx_uart_driver);
+       return ret;
 }
 
 static void __exit
index 77287c5..549c70a 100644 (file)
@@ -199,7 +199,7 @@ static void nwpserial_shutdown(struct uart_port *port)
        dcr_write(up->dcr_host, UART_IER, up->ier);
 
        /* free irq */
-       free_irq(up->port.irq, port);
+       free_irq(up->port.irq, up);
 }
 
 static int nwpserial_verify_port(struct uart_port *port,
index 30d4f7a..f0b9f6b 100644 (file)
@@ -202,26 +202,6 @@ static int serial_omap_get_context_loss_count(struct uart_omap_port *up)
        return pdata->get_context_loss_count(up->dev);
 }
 
-static void serial_omap_set_forceidle(struct uart_omap_port *up)
-{
-       struct omap_uart_port_info *pdata = up->dev->platform_data;
-
-       if (!pdata || !pdata->set_forceidle)
-               return;
-
-       pdata->set_forceidle(up->dev);
-}
-
-static void serial_omap_set_noidle(struct uart_omap_port *up)
-{
-       struct omap_uart_port_info *pdata = up->dev->platform_data;
-
-       if (!pdata || !pdata->set_noidle)
-               return;
-
-       pdata->set_noidle(up->dev);
-}
-
 static void serial_omap_enable_wakeup(struct uart_omap_port *up, bool enable)
 {
        struct omap_uart_port_info *pdata = up->dev->platform_data;
@@ -298,8 +278,6 @@ static void serial_omap_stop_tx(struct uart_port *port)
                serial_out(up, UART_IER, up->ier);
        }
 
-       serial_omap_set_forceidle(up);
-
        pm_runtime_mark_last_busy(up->dev);
        pm_runtime_put_autosuspend(up->dev);
 }
@@ -364,7 +342,6 @@ static void serial_omap_start_tx(struct uart_port *port)
 
        pm_runtime_get_sync(up->dev);
        serial_omap_enable_ier_thri(up);
-       serial_omap_set_noidle(up);
        pm_runtime_mark_last_busy(up->dev);
        pm_runtime_put_autosuspend(up->dev);
 }
index 074b919..0c8a9fa 100644 (file)
@@ -1166,6 +1166,18 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
                ourport->tx_irq = ret;
 
        ourport->clk    = clk_get(&platdev->dev, "uart");
+       if (IS_ERR(ourport->clk)) {
+               pr_err("%s: Controller clock not found\n",
+                               dev_name(&platdev->dev));
+               return PTR_ERR(ourport->clk);
+       }
+
+       ret = clk_prepare_enable(ourport->clk);
+       if (ret) {
+               pr_err("uart: clock failed to prepare+enable: %d\n", ret);
+               clk_put(ourport->clk);
+               return ret;
+       }
 
        /* Keep all interrupts masked and cleared */
        if (s3c24xx_serial_has_interrupt_mask(port)) {
@@ -1180,6 +1192,7 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
 
        /* reset the fifos (and setup the uart) */
        s3c24xx_serial_resetport(port, cfg);
+       clk_disable_unprepare(ourport->clk);
        return 0;
 }
 
@@ -1803,6 +1816,7 @@ static int __init s3c24xx_serial_modinit(void)
 
 static void __exit s3c24xx_serial_modexit(void)
 {
+       platform_driver_unregister(&samsung_serial_driver);
        uart_unregister_driver(&s3c24xx_uart_drv);
 }
 
index 6953dc8..a4fdce7 100644 (file)
@@ -60,24 +60,22 @@ static void tty_audit_buf_put(struct tty_audit_buf *buf)
                tty_audit_buf_free(buf);
 }
 
-static void tty_audit_log(const char *description, struct task_struct *tsk,
-                         kuid_t loginuid, unsigned sessionid, int major,
-                         int minor, unsigned char *data, size_t size)
+static void tty_audit_log(const char *description, int major, int minor,
+                         unsigned char *data, size_t size)
 {
        struct audit_buffer *ab;
+       struct task_struct *tsk = current;
+       uid_t uid = from_kuid(&init_user_ns, task_uid(tsk));
+       uid_t loginuid = from_kuid(&init_user_ns, audit_get_loginuid(tsk));
+       u32 sessionid = audit_get_sessionid(tsk);
 
        ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_TTY);
        if (ab) {
                char name[sizeof(tsk->comm)];
-               kuid_t uid = task_uid(tsk);
-
-               audit_log_format(ab, "%s pid=%u uid=%u auid=%u ses=%u "
-                                "major=%d minor=%d comm=", description,
-                                tsk->pid,
-                                from_kuid(&init_user_ns, uid),
-                                from_kuid(&init_user_ns, loginuid),
-                                sessionid,
-                                major, minor);
+
+               audit_log_format(ab, "%s pid=%u uid=%u auid=%u ses=%u major=%d"
+                                " minor=%d comm=", description, tsk->pid, uid,
+                                loginuid, sessionid, major, minor);
                get_task_comm(name, tsk);
                audit_log_untrustedstring(ab, name);
                audit_log_format(ab, " data=");
@@ -90,11 +88,9 @@ static void tty_audit_log(const char *description, struct task_struct *tsk,
  *     tty_audit_buf_push      -       Push buffered data out
  *
  *     Generate an audit message from the contents of @buf, which is owned by
- *     @tsk with @loginuid.  @buf->mutex must be locked.
+ *     the current task.  @buf->mutex must be locked.
  */
-static void tty_audit_buf_push(struct task_struct *tsk, kuid_t loginuid,
-                              unsigned int sessionid,
-                              struct tty_audit_buf *buf)
+static void tty_audit_buf_push(struct tty_audit_buf *buf)
 {
        if (buf->valid == 0)
                return;
@@ -102,24 +98,10 @@ static void tty_audit_buf_push(struct task_struct *tsk, kuid_t loginuid,
                buf->valid = 0;
                return;
        }
-       tty_audit_log("tty", tsk, loginuid, sessionid, buf->major, buf->minor,
-                     buf->data, buf->valid);
+       tty_audit_log("tty", buf->major, buf->minor, buf->data, buf->valid);
        buf->valid = 0;
 }
 
-/**
- *     tty_audit_buf_push_current      -       Push buffered data out
- *
- *     Generate an audit message from the contents of @buf, which is owned by
- *     the current task.  @buf->mutex must be locked.
- */
-static void tty_audit_buf_push_current(struct tty_audit_buf *buf)
-{
-       kuid_t auid = audit_get_loginuid(current);
-       unsigned int sessionid = audit_get_sessionid(current);
-       tty_audit_buf_push(current, auid, sessionid, buf);
-}
-
 /**
  *     tty_audit_exit  -       Handle a task exit
  *
@@ -130,15 +112,13 @@ void tty_audit_exit(void)
 {
        struct tty_audit_buf *buf;
 
-       spin_lock_irq(&current->sighand->siglock);
        buf = current->signal->tty_audit_buf;
        current->signal->tty_audit_buf = NULL;
-       spin_unlock_irq(&current->sighand->siglock);
        if (!buf)
                return;
 
        mutex_lock(&buf->mutex);
-       tty_audit_buf_push_current(buf);
+       tty_audit_buf_push(buf);
        mutex_unlock(&buf->mutex);
 
        tty_audit_buf_put(buf);
@@ -151,9 +131,8 @@ void tty_audit_exit(void)
  */
 void tty_audit_fork(struct signal_struct *sig)
 {
-       spin_lock_irq(&current->sighand->siglock);
        sig->audit_tty = current->signal->audit_tty;
-       spin_unlock_irq(&current->sighand->siglock);
+       sig->audit_tty_log_passwd = current->signal->audit_tty_log_passwd;
 }
 
 /**
@@ -163,20 +142,21 @@ void tty_audit_tiocsti(struct tty_struct *tty, char ch)
 {
        struct tty_audit_buf *buf;
        int major, minor, should_audit;
+       unsigned long flags;
 
-       spin_lock_irq(&current->sighand->siglock);
+       spin_lock_irqsave(&current->sighand->siglock, flags);
        should_audit = current->signal->audit_tty;
        buf = current->signal->tty_audit_buf;
        if (buf)
                atomic_inc(&buf->count);
-       spin_unlock_irq(&current->sighand->siglock);
+       spin_unlock_irqrestore(&current->sighand->siglock, flags);
 
        major = tty->driver->major;
        minor = tty->driver->minor_start + tty->index;
        if (buf) {
                mutex_lock(&buf->mutex);
                if (buf->major == major && buf->minor == minor)
-                       tty_audit_buf_push_current(buf);
+                       tty_audit_buf_push(buf);
                mutex_unlock(&buf->mutex);
                tty_audit_buf_put(buf);
        }
@@ -187,24 +167,20 @@ void tty_audit_tiocsti(struct tty_struct *tty, char ch)
 
                auid = audit_get_loginuid(current);
                sessionid = audit_get_sessionid(current);
-               tty_audit_log("ioctl=TIOCSTI", current, auid, sessionid, major,
-                             minor, &ch, 1);
+               tty_audit_log("ioctl=TIOCSTI", major, minor, &ch, 1);
        }
 }
 
 /**
- * tty_audit_push_task -       Flush task's pending audit data
- * @tsk:               task pointer
- * @loginuid:          sender login uid
- * @sessionid:         sender session id
+ * tty_audit_push_current -    Flush current's pending audit data
  *
- * Called with a ref on @tsk held. Try to lock sighand and get a
- * reference to the tty audit buffer if available.
+ * Try to lock sighand and get a reference to the tty audit buffer if available.
  * Flush the buffer or return an appropriate error code.
  */
-int tty_audit_push_task(struct task_struct *tsk, kuid_t loginuid, u32 sessionid)
+int tty_audit_push_current(void)
 {
        struct tty_audit_buf *buf = ERR_PTR(-EPERM);
+       struct task_struct *tsk = current;
        unsigned long flags;
 
        if (!lock_task_sighand(tsk, &flags))
@@ -225,7 +201,7 @@ int tty_audit_push_task(struct task_struct *tsk, kuid_t loginuid, u32 sessionid)
                return PTR_ERR(buf);
 
        mutex_lock(&buf->mutex);
-       tty_audit_buf_push(tsk, loginuid, sessionid, buf);
+       tty_audit_buf_push(buf);
        mutex_unlock(&buf->mutex);
 
        tty_audit_buf_put(buf);
@@ -243,10 +219,11 @@ static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty,
                unsigned icanon)
 {
        struct tty_audit_buf *buf, *buf2;
+       unsigned long flags;
 
        buf = NULL;
        buf2 = NULL;
-       spin_lock_irq(&current->sighand->siglock);
+       spin_lock_irqsave(&current->sighand->siglock, flags);
        if (likely(!current->signal->audit_tty))
                goto out;
        buf = current->signal->tty_audit_buf;
@@ -254,7 +231,7 @@ static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty,
                atomic_inc(&buf->count);
                goto out;
        }
-       spin_unlock_irq(&current->sighand->siglock);
+       spin_unlock_irqrestore(&current->sighand->siglock, flags);
 
        buf2 = tty_audit_buf_alloc(tty->driver->major,
                                   tty->driver->minor_start + tty->index,
@@ -264,7 +241,7 @@ static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty,
                return NULL;
        }
 
-       spin_lock_irq(&current->sighand->siglock);
+       spin_lock_irqsave(&current->sighand->siglock, flags);
        if (!current->signal->audit_tty)
                goto out;
        buf = current->signal->tty_audit_buf;
@@ -276,7 +253,7 @@ static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty,
        atomic_inc(&buf->count);
        /* Fall through */
  out:
-       spin_unlock_irq(&current->sighand->siglock);
+       spin_unlock_irqrestore(&current->sighand->siglock, flags);
        if (buf2)
                tty_audit_buf_free(buf2);
        return buf;
@@ -292,10 +269,18 @@ void tty_audit_add_data(struct tty_struct *tty, unsigned char *data,
 {
        struct tty_audit_buf *buf;
        int major, minor;
+       int audit_log_tty_passwd;
+       unsigned long flags;
 
        if (unlikely(size == 0))
                return;
 
+       spin_lock_irqsave(&current->sighand->siglock, flags);
+       audit_log_tty_passwd = current->signal->audit_tty_log_passwd;
+       spin_unlock_irqrestore(&current->sighand->siglock, flags);
+       if (!audit_log_tty_passwd && icanon && !L_ECHO(tty))
+               return;
+
        if (tty->driver->type == TTY_DRIVER_TYPE_PTY
            && tty->driver->subtype == PTY_TYPE_MASTER)
                return;
@@ -309,7 +294,7 @@ void tty_audit_add_data(struct tty_struct *tty, unsigned char *data,
        minor = tty->driver->minor_start + tty->index;
        if (buf->major != major || buf->minor != minor
            || buf->icanon != icanon) {
-               tty_audit_buf_push_current(buf);
+               tty_audit_buf_push(buf);
                buf->major = major;
                buf->minor = minor;
                buf->icanon = icanon;
@@ -325,7 +310,7 @@ void tty_audit_add_data(struct tty_struct *tty, unsigned char *data,
                data += run;
                size -= run;
                if (buf->valid == N_TTY_BUF_SIZE)
-                       tty_audit_buf_push_current(buf);
+                       tty_audit_buf_push(buf);
        } while (size != 0);
        mutex_unlock(&buf->mutex);
        tty_audit_buf_put(buf);
@@ -339,16 +324,17 @@ void tty_audit_add_data(struct tty_struct *tty, unsigned char *data,
 void tty_audit_push(struct tty_struct *tty)
 {
        struct tty_audit_buf *buf;
+       unsigned long flags;
 
-       spin_lock_irq(&current->sighand->siglock);
+       spin_lock_irqsave(&current->sighand->siglock, flags);
        if (likely(!current->signal->audit_tty)) {
-               spin_unlock_irq(&current->sighand->siglock);
+               spin_unlock_irqrestore(&current->sighand->siglock, flags);
                return;
        }
        buf = current->signal->tty_audit_buf;
        if (buf)
                atomic_inc(&buf->count);
-       spin_unlock_irq(&current->sighand->siglock);
+       spin_unlock_irqrestore(&current->sighand->siglock, flags);
 
        if (buf) {
                int major, minor;
@@ -357,7 +343,7 @@ void tty_audit_push(struct tty_struct *tty)
                minor = tty->driver->minor_start + tty->index;
                mutex_lock(&buf->mutex);
                if (buf->major == major && buf->minor == minor)
-                       tty_audit_buf_push_current(buf);
+                       tty_audit_buf_push(buf);
                mutex_unlock(&buf->mutex);
                tty_audit_buf_put(buf);
        }
index fbd447b..740202d 100644 (file)
@@ -779,7 +779,6 @@ int vc_allocate(unsigned int currcons)      /* return 0 on success */
                con_set_default_unimap(vc);
            vc->vc_screenbuf = kmalloc(vc->vc_screenbuf_size, GFP_KERNEL);
            if (!vc->vc_screenbuf) {
-               tty_port_destroy(&vc->port);
                kfree(vc);
                vc_cons[currcons].d = NULL;
                return -ENOMEM;
@@ -986,26 +985,25 @@ static int vt_resize(struct tty_struct *tty, struct winsize *ws)
        return ret;
 }
 
-void vc_deallocate(unsigned int currcons)
+struct vc_data *vc_deallocate(unsigned int currcons)
 {
+       struct vc_data *vc = NULL;
+
        WARN_CONSOLE_UNLOCKED();
 
        if (vc_cons_allocated(currcons)) {
-               struct vc_data *vc = vc_cons[currcons].d;
-               struct vt_notifier_param param = { .vc = vc };
+               struct vt_notifier_param param;
 
+               param.vc = vc = vc_cons[currcons].d;
                atomic_notifier_call_chain(&vt_notifier_list, VT_DEALLOCATE, &param);
                vcs_remove_sysfs(currcons);
                vc->vc_sw->con_deinit(vc);
                put_pid(vc->vt_pid);
                module_put(vc->vc_sw->owner);
                kfree(vc->vc_screenbuf);
-               if (currcons >= MIN_NR_CONSOLES) {
-                       tty_port_destroy(&vc->port);
-                       kfree(vc);
-               }
                vc_cons[currcons].d = NULL;
        }
+       return vc;
 }
 
 /*
index 98ff173..fc2c06c 100644 (file)
@@ -283,6 +283,51 @@ do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud, int perm, struct vc_
        return 0;
 }
 
+/* deallocate a single console, if possible (leave 0) */
+static int vt_disallocate(unsigned int vc_num)
+{
+       struct vc_data *vc = NULL;
+       int ret = 0;
+
+       if (!vc_num)
+               return 0;
+
+       console_lock();
+       if (VT_BUSY(vc_num))
+               ret = -EBUSY;
+       else
+               vc = vc_deallocate(vc_num);
+       console_unlock();
+
+       if (vc && vc_num >= MIN_NR_CONSOLES) {
+               tty_port_destroy(&vc->port);
+               kfree(vc);
+       }
+
+       return ret;
+}
+
+/* deallocate all unused consoles, but leave 0 */
+static void vt_disallocate_all(void)
+{
+       struct vc_data *vc[MAX_NR_CONSOLES];
+       int i;
+
+       console_lock();
+       for (i = 1; i < MAX_NR_CONSOLES; i++)
+               if (!VT_BUSY(i))
+                       vc[i] = vc_deallocate(i);
+               else
+                       vc[i] = NULL;
+       console_unlock();
+
+       for (i = 1; i < MAX_NR_CONSOLES; i++) {
+               if (vc[i] && i >= MIN_NR_CONSOLES) {
+                       tty_port_destroy(&vc[i]->port);
+                       kfree(vc[i]);
+               }
+       }
+}
 
 
 /*
@@ -769,24 +814,10 @@ int vt_ioctl(struct tty_struct *tty,
                        ret = -ENXIO;
                        break;
                }
-               if (arg == 0) {
-                   /* deallocate all unused consoles, but leave 0 */
-                       console_lock();
-                       for (i=1; i<MAX_NR_CONSOLES; i++)
-                               if (! VT_BUSY(i))
-                                       vc_deallocate(i);
-                       console_unlock();
-               } else {
-                       /* deallocate a single console, if possible */
-                       arg--;
-                       if (VT_BUSY(arg))
-                               ret = -EBUSY;
-                       else if (arg) {                       /* leave 0 */
-                               console_lock();
-                               vc_deallocate(arg);
-                               console_unlock();
-                       }
-               }
+               if (arg == 0)
+                       vt_disallocate_all();
+               else
+                       ret = vt_disallocate(--arg);
                break;
 
        case VT_RESIZE:
index e92eeaf..5295be0 100644 (file)
@@ -45,6 +45,7 @@ config UIO_PDRV_GENIRQ
 
 config UIO_DMEM_GENIRQ
        tristate "Userspace platform driver with generic irq and dynamic memory"
+       depends on HAS_DMA
        help
          Platform driver for Userspace I/O devices, including generic
          interrupt handling code. Shared interrupts are not supported.
index b7eb86a..8a7eb77 100644 (file)
@@ -686,7 +686,8 @@ static int cxacru_cm_get_array(struct cxacru_data *instance, enum cxacru_cm_requ
 {
        int ret, len;
        __le32 *buf;
-       int offb, offd;
+       int offb;
+       unsigned int offd;
        const int stride = CMD_PACKET_SIZE / (4 * 2) - 1;
        int buflen =  ((size - 1) / stride + 1 + size * 2) * 4;
 
index 608a2ae..b2df442 100644 (file)
@@ -20,7 +20,7 @@ config USB_CHIPIDEA_UDC
 config USB_CHIPIDEA_HOST
        bool "ChipIdea host controller"
        depends on USB=y || USB=USB_CHIPIDEA
-       depends on USB_EHCI_HCD
+       depends on USB_EHCI_HCD=y
        select USB_EHCI_ROOT_HUB_TT
        help
          Say Y here to enable host controller functionality of the
index 8faec9d..73f9d5f 100644 (file)
@@ -173,17 +173,10 @@ static int ci13xxx_imx_probe(struct platform_device *pdev)
 
        ci13xxx_imx_platdata.phy = data->phy;
 
-       if (!pdev->dev.dma_mask) {
-               pdev->dev.dma_mask = devm_kzalloc(&pdev->dev,
-                                     sizeof(*pdev->dev.dma_mask), GFP_KERNEL);
-               if (!pdev->dev.dma_mask) {
-                       ret = -ENOMEM;
-                       dev_err(&pdev->dev, "Failed to alloc dma_mask!\n");
-                       goto err;
-               }
-               *pdev->dev.dma_mask = DMA_BIT_MASK(32);
-               dma_set_coherent_mask(&pdev->dev, *pdev->dev.dma_mask);
-       }
+       if (!pdev->dev.dma_mask)
+               pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
+       if (!pdev->dev.coherent_dma_mask)
+               pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
 
        if (usbmisc_ops && usbmisc_ops->init) {
                ret = usbmisc_ops->init(&pdev->dev);
index 450107e..49b098b 100644 (file)
@@ -370,11 +370,6 @@ static int ci_hdrc_probe(struct platform_device *pdev)
        }
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(dev, "missing resource\n");
-               return -ENODEV;
-       }
-
        base = devm_ioremap_resource(dev, res);
        if (IS_ERR(base))
                return PTR_ERR(base);
index 8772b36..db535b0 100644 (file)
@@ -51,7 +51,7 @@ config USB_DYNAMIC_MINORS
 
 config USB_OTG
        bool "OTG support"
-       depends on USB_SUSPEND
+       depends on PM_RUNTIME
        default n
        help
          The most notable feature of USB OTG is support for a
index caefc80..c88c4fb 100644 (file)
@@ -1287,9 +1287,13 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
                        goto error;
                }
                for (totlen = u = 0; u < uurb->number_of_packets; u++) {
-                       /* arbitrary limit,
-                        * sufficient for USB 2.0 high-bandwidth iso */
-                       if (isopkt[u].length > 8192) {
+                       /*
+                        * arbitrary limit need for USB 3.0
+                        * bMaxBurst (0~15 allowed, 1~16 packets)
+                        * bmAttributes (bit 1:0, mult 0~2, 1~3 packets)
+                        * sizemax: 1024 * 16 * 3 = 49152
+                        */
+                       if (isopkt[u].length > 49152) {
                                ret = -EINVAL;
                                goto error;
                        }
index ab5638d..a635988 100644 (file)
@@ -88,6 +88,9 @@ static const struct usb_device_id usb_quirk_list[] = {
        /* Edirol SD-20 */
        { USB_DEVICE(0x0582, 0x0027), .driver_info = USB_QUIRK_RESET_RESUME },
 
+       /* Alcor Micro Corp. Hub */
+       { USB_DEVICE(0x058f, 0x9254), .driver_info = USB_QUIRK_RESET_RESUME },
+
        /* appletouch */
        { USB_DEVICE(0x05ac, 0x021a), .driver_info = USB_QUIRK_RESET_RESUME },
 
index ea5ee9c..757aa18 100644 (file)
@@ -19,21 +19,21 @@ choice
 
 config USB_DWC3_HOST
        bool "Host only mode"
-       depends on USB
+       depends on USB=y || USB=USB_DWC3
        help
          Select this when you want to use DWC3 in host mode only,
          thereby the gadget feature will be regressed.
 
 config USB_DWC3_GADGET
        bool "Gadget only mode"
-       depends on USB_GADGET
+       depends on USB_GADGET=y || USB_GADGET=USB_DWC3
        help
          Select this when you want to use DWC3 in gadget mode only,
          thereby the host feature will be regressed.
 
 config USB_DWC3_DUAL_ROLE
        bool "Dual Role mode"
-       depends on (USB && USB_GADGET)
+       depends on ((USB=y || USB=USB_DWC3) && (USB_GADGET=y || USB_GADGET=USB_DWC3))
        help
          This is the default mode of working of DWC3 controller where
          both host and gadget features are enabled.
index a8afe6e..8ce9d7f 100644 (file)
@@ -95,8 +95,6 @@ static int dwc3_exynos_remove_child(struct device *dev, void *unused)
        return 0;
 }
 
-static u64 dwc3_exynos_dma_mask = DMA_BIT_MASK(32);
-
 static int dwc3_exynos_probe(struct platform_device *pdev)
 {
        struct dwc3_exynos      *exynos;
@@ -118,7 +116,9 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
         * Once we move to full device tree support this will vanish off.
         */
        if (!dev->dma_mask)
-               dev->dma_mask = &dwc3_exynos_dma_mask;
+               dev->dma_mask = &dev->coherent_dma_mask;
+       if (!dev->coherent_dma_mask)
+               dev->coherent_dma_mask = DMA_BIT_MASK(32);
 
        platform_set_drvdata(pdev, exynos);
 
@@ -164,9 +164,9 @@ static int dwc3_exynos_remove(struct platform_device *pdev)
 {
        struct dwc3_exynos      *exynos = platform_get_drvdata(pdev);
 
+       device_for_each_child(&pdev->dev, NULL, dwc3_exynos_remove_child);
        platform_device_unregister(exynos->usb2_phy);
        platform_device_unregister(exynos->usb3_phy);
-       device_for_each_child(&pdev->dev, NULL, dwc3_exynos_remove_child);
 
        clk_disable_unprepare(exynos->clk);
 
index 227d4a7..eba9e2b 100644 (file)
@@ -196,9 +196,9 @@ static void dwc3_pci_remove(struct pci_dev *pci)
 {
        struct dwc3_pci *glue = pci_get_drvdata(pci);
 
+       platform_device_unregister(glue->dwc3);
        platform_device_unregister(glue->usb2_phy);
        platform_device_unregister(glue->usb3_phy);
-       platform_device_unregister(glue->dwc3);
        pci_set_drvdata(pci, NULL);
        pci_disable_device(pci);
 }
index 2b6e7e0..b5e5b35 100644 (file)
@@ -1706,11 +1706,19 @@ static void dwc3_gadget_free_endpoints(struct dwc3 *dwc)
                dep = dwc->eps[epnum];
                if (!dep)
                        continue;
-
-               dwc3_free_trb_pool(dep);
-
-               if (epnum != 0 && epnum != 1)
+               /*
+                * Physical endpoints 0 and 1 are special; they form the
+                * bi-directional USB endpoint 0.
+                *
+                * For those two physical endpoints, we don't allocate a TRB
+                * pool nor do we add them the endpoints list. Due to that, we
+                * shouldn't do these two operations otherwise we would end up
+                * with all sorts of bugs when removing dwc3.ko.
+                */
+               if (epnum != 0 && epnum != 1) {
+                       dwc3_free_trb_pool(dep);
                        list_del(&dep->endpoint.ep_list);
+               }
 
                kfree(dep);
        }
index 83300d9..f41aa0d 100644 (file)
@@ -146,7 +146,6 @@ config USB_LPC32XX
        depends on ARCH_LPC32XX
        depends on USB_PHY
        select USB_ISP1301
-       select USB_OTG_UTILS
        help
           This option selects the USB device controller in the LPC32xx SoC.
 
index f2a970f..5a5128a 100644 (file)
@@ -1992,8 +1992,6 @@ err_map_regs:
 err_get_hclk:
        clk_put(pclk);
 
-       platform_set_drvdata(pdev, NULL);
-
        return ret;
 }
 
index 6e65182..fd24cb4 100644 (file)
@@ -2334,21 +2334,11 @@ static int bcm63xx_udc_probe(struct platform_device *pdev)
        }
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(dev, "error finding USBD resource\n");
-               return -ENXIO;
-       }
-
        udc->usbd_regs = devm_ioremap_resource(dev, res);
        if (IS_ERR(udc->usbd_regs))
                return PTR_ERR(udc->usbd_regs);
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-       if (!res) {
-               dev_err(dev, "error finding IUDMA resource\n");
-               return -ENXIO;
-       }
-
        udc->iudma_regs = devm_ioremap_resource(dev, res);
        if (IS_ERR(udc->iudma_regs))
                return PTR_ERR(udc->iudma_regs);
@@ -2420,7 +2410,6 @@ static int bcm63xx_udc_remove(struct platform_device *pdev)
        usb_del_gadget_udc(&udc->gadget);
        BUG_ON(udc->driver);
 
-       platform_set_drvdata(pdev, NULL);
        bcm63xx_uninit_udc_hw(udc);
 
        return 0;
index 3d5cfc9..80e7f75 100644 (file)
@@ -821,8 +821,10 @@ static int configfs_composite_bind(struct usb_gadget *gadget,
                gi->gstrings[i] = NULL;
                s = usb_gstrings_attach(&gi->cdev, gi->gstrings,
                                USB_GADGET_FIRST_AVAIL_IDX);
-               if (IS_ERR(s))
+               if (IS_ERR(s)) {
+                       ret = PTR_ERR(s);
                        goto err_comp_cleanup;
+               }
 
                gi->cdev.desc.iManufacturer = s[USB_GADGET_MANUFACTURER_IDX].id;
                gi->cdev.desc.iProduct = s[USB_GADGET_PRODUCT_IDX].id;
@@ -847,8 +849,10 @@ static int configfs_composite_bind(struct usb_gadget *gadget,
                        }
                        cfg->gstrings[i] = NULL;
                        s = usb_gstrings_attach(&gi->cdev, cfg->gstrings, 1);
-                       if (IS_ERR(s))
+                       if (IS_ERR(s)) {
+                               ret = PTR_ERR(s);
                                goto err_comp_cleanup;
+                       }
                        c->iConfiguration = s[0].id;
                }
 
index a792e32..c588e8e 100644 (file)
@@ -1001,7 +1001,6 @@ static int dummy_udc_remove(struct platform_device *pdev)
        struct dummy    *dum = platform_get_drvdata(pdev);
 
        usb_del_gadget_udc(&dum->gadget);
-       platform_set_drvdata(pdev, NULL);
        device_remove_file(&dum->gadget.dev, &dev_attr_function);
        return 0;
 }
@@ -2661,8 +2660,10 @@ static int __init init(void)
        }
        for (i = 0; i < mod_data.num; i++) {
                dum[i] = kzalloc(sizeof(struct dummy), GFP_KERNEL);
-               if (!dum[i])
+               if (!dum[i]) {
+                       retval = -ENOMEM;
                        goto err_add_pdata;
+               }
                retval = platform_device_add_data(the_hcd_pdev[i], &dum[i],
                                sizeof(void *));
                if (retval)
index d893d69..abf8a31 100644 (file)
@@ -816,6 +816,7 @@ ecm_unbind(struct usb_configuration *c, struct usb_function *f)
  * @c: the configuration to support the network link
  * @ethaddr: a buffer in which the ethernet address of the host side
  *     side of the link was recorded
+ * @dev: eth_dev structure
  * Context: single threaded during gadget setup
  *
  * Returns zero on success, else negative errno.
index 185d6f5..7be04b3 100644 (file)
@@ -373,6 +373,7 @@ geth_unbind(struct usb_configuration *c, struct usb_function *f)
  * @c: the configuration to support the network link
  * @ethaddr: a buffer in which the ethernet address of the host side
  *     side of the link was recorded
+ * @dev: eth_dev structure
  * Context: single threaded during gadget setup
  *
  * Returns zero on success, else negative errno.
index c7468b6..03c1fb6 100644 (file)
@@ -456,8 +456,6 @@ static int snd_uac2_remove(struct platform_device *pdev)
 {
        struct snd_card *card = platform_get_drvdata(pdev);
 
-       platform_set_drvdata(pdev, NULL);
-
        if (card)
                return snd_card_free(card);
 
index cec8871..b8632d4 100644 (file)
@@ -1461,8 +1461,10 @@ static int __init fusb300_probe(struct platform_device *pdev)
 
        fusb300->ep0_req = fusb300_alloc_request(&fusb300->ep[0]->ep,
                                GFP_KERNEL);
-       if (fusb300->ep0_req == NULL)
+       if (fusb300->ep0_req == NULL) {
+               ret = -ENOMEM;
                goto clean_up3;
+       }
 
        init_controller(fusb300);
        ret = usb_add_gadget_udc(&pdev->dev, &fusb300->gadget);
index b5cebd6..9b2d24e 100644 (file)
@@ -1511,8 +1511,6 @@ static int __exit imx_udc_remove(struct platform_device *pdev)
        if (pdata->exit)
                pdata->exit(&pdev->dev);
 
-       platform_set_drvdata(pdev, NULL);
-
        return 0;
 }
 
index 866ef09..51cfe72 100644 (file)
@@ -1660,8 +1660,10 @@ static int __init m66592_probe(struct platform_device *pdev)
        m66592->epaddr2ep[0] = &m66592->ep[0];
 
        m66592->ep0_req = m66592_alloc_request(&m66592->ep[0].ep, GFP_KERNEL);
-       if (m66592->ep0_req == NULL)
+       if (m66592->ep0_req == NULL) {
+               ret = -ENOMEM;
                goto clean_up3;
+       }
        m66592->ep0_req->complete = nop_completion;
 
        init_controller(m66592);
index ef47495..95c531d 100644 (file)
@@ -2236,7 +2236,6 @@ static int __exit pxa25x_udc_remove(struct platform_device *pdev)
                dev->transceiver = NULL;
        }
 
-       platform_set_drvdata(pdev, NULL);
        the_controller = NULL;
        return 0;
 }
index 0b742d1..7ff7d9c 100644 (file)
@@ -1977,8 +1977,10 @@ static int __init r8a66597_probe(struct platform_device *pdev)
 
        r8a66597->ep0_req = r8a66597_alloc_request(&r8a66597->ep[0].ep,
                                                        GFP_KERNEL);
-       if (r8a66597->ep0_req == NULL)
+       if (r8a66597->ep0_req == NULL) {
+               ret = -ENOMEM;
                goto clean_up3;
+       }
        r8a66597->ep0_req->complete = nop_completion;
 
        ret = usb_add_gadget_udc(&pdev->dev, &r8a66597->gadget);
index a3cdc32..af22f24 100644 (file)
@@ -437,7 +437,7 @@ static void s3c_hsotg_unmap_dma(struct s3c_hsotg *hsotg,
        if (hs_req->req.length == 0)
                return;
 
-       usb_gadget_unmap_request(&hsotg->gadget, hs_req, hs_ep->dir_in);
+       usb_gadget_unmap_request(&hsotg->gadget, req, hs_ep->dir_in);
 }
 
 /**
index d0e75e1..09c4f70 100644 (file)
@@ -1851,6 +1851,7 @@ static int s3c2410_udc_probe(struct platform_device *pdev)
                irq = gpio_to_irq(udc_info->vbus_pin);
                if (irq < 0) {
                        dev_err(dev, "no irq for gpio vbus pin\n");
+                       retval = irq;
                        goto err_gpio_claim;
                }
 
@@ -1948,8 +1949,6 @@ static int s3c2410_udc_remove(struct platform_device *pdev)
        iounmap(base_addr);
        release_mem_region(rsrc_start, rsrc_len);
 
-       platform_set_drvdata(pdev, NULL);
-
        if (!IS_ERR(udc_clock) && udc_clock != NULL) {
                clk_disable(udc_clock);
                clk_put(udc_clock);
index 2cd6262..0deb9d6 100644 (file)
@@ -284,12 +284,16 @@ static int __init zero_bind(struct usb_composite_dev *cdev)
        ss_opts->bulk_buflen = gzero_options.bulk_buflen;
 
        func_ss = usb_get_function(func_inst_ss);
-       if (IS_ERR(func_ss))
+       if (IS_ERR(func_ss)) {
+               status = PTR_ERR(func_ss);
                goto err_put_func_inst_ss;
+       }
 
        func_inst_lb = usb_get_function_instance("Loopback");
-       if (IS_ERR(func_inst_lb))
+       if (IS_ERR(func_inst_lb)) {
+               status = PTR_ERR(func_inst_lb);
                goto err_put_func_ss;
+       }
 
        lb_opts = container_of(func_inst_lb, struct f_lb_opts, func_inst);
        lb_opts->bulk_buflen = gzero_options.bulk_buflen;
index de94f26..344d5e2 100644 (file)
@@ -507,7 +507,7 @@ endif # USB_OHCI_HCD
 
 config USB_UHCI_HCD
        tristate "UHCI HCD (most Intel and VIA) support"
-       depends on PCI || SPARC_LEON || ARCH_VT8500
+       depends on PCI || USB_UHCI_SUPPORT_NON_PCI_HC
        ---help---
          The Universal Host Controller Interface is a standard by Intel for
          accessing the USB hardware in the PC (which is also called the USB
@@ -524,26 +524,19 @@ config USB_UHCI_HCD
 
 config USB_UHCI_SUPPORT_NON_PCI_HC
        bool
-       depends on USB_UHCI_HCD
-       default y if (SPARC_LEON || ARCH_VT8500)
+       default y if (SPARC_LEON || USB_UHCI_PLATFORM)
 
 config USB_UHCI_PLATFORM
-       bool "Generic UHCI Platform Driver support"
-       depends on USB_UHCI_SUPPORT_NON_PCI_HC
+       bool
        default y if ARCH_VT8500
-       ---help---
-         Enable support for generic UHCI platform devices that require no
-         additional configuration.
 
 config USB_UHCI_BIG_ENDIAN_MMIO
        bool
-       depends on USB_UHCI_SUPPORT_NON_PCI_HC && SPARC_LEON
-       default y
+       default y if SPARC_LEON
 
 config USB_UHCI_BIG_ENDIAN_DESC
        bool
-       depends on USB_UHCI_SUPPORT_NON_PCI_HC && SPARC_LEON
-       default y
+       default y if SPARC_LEON
 
 config USB_FHCI_HCD
        tristate "Freescale QE USB Host Controller support"
index 6642009..02f4611 100644 (file)
@@ -63,8 +63,6 @@ static void atmel_stop_ehci(struct platform_device *pdev)
 
 /*-------------------------------------------------------------------------*/
 
-static u64 at91_ehci_dma_mask = DMA_BIT_MASK(32);
-
 static int ehci_atmel_drv_probe(struct platform_device *pdev)
 {
        struct usb_hcd *hcd;
@@ -93,7 +91,9 @@ static int ehci_atmel_drv_probe(struct platform_device *pdev)
         * Once we have dma capability bindings this can go away.
         */
        if (!pdev->dev.dma_mask)
-               pdev->dev.dma_mask = &at91_ehci_dma_mask;
+               pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
+       if (!pdev->dev.coherent_dma_mask)
+               pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
 
        hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
        if (!hcd) {
index 312fc10..246e124 100644 (file)
@@ -1286,23 +1286,6 @@ MODULE_LICENSE ("GPL");
 #define        PLATFORM_DRIVER         ehci_hcd_sead3_driver
 #endif
 
-#if !IS_ENABLED(CONFIG_USB_EHCI_PCI) && \
-       !IS_ENABLED(CONFIG_USB_EHCI_HCD_PLATFORM) && \
-       !IS_ENABLED(CONFIG_USB_CHIPIDEA_HOST) && \
-       !IS_ENABLED(CONFIG_USB_EHCI_MXC) && \
-       !IS_ENABLED(CONFIG_USB_EHCI_HCD_OMAP) && \
-       !IS_ENABLED(CONFIG_USB_EHCI_HCD_ORION) && \
-       !IS_ENABLED(CONFIG_USB_EHCI_HCD_SPEAR) && \
-       !IS_ENABLED(CONFIG_USB_EHCI_S5P) && \
-       !IS_ENABLED(CONFIG_USB_EHCI_HCD_AT91) && \
-       !IS_ENABLED(CONFIG_USB_EHCI_MSM) && \
-       !defined(PLATFORM_DRIVER) && \
-       !defined(PS3_SYSTEM_BUS_DRIVER) && \
-       !defined(OF_PLATFORM_DRIVER) && \
-       !defined(XILINX_OF_PLATFORM_DRIVER)
-#error "missing bus glue for ehci-hcd"
-#endif
-
 static int __init ehci_hcd_init(void)
 {
        int retval = 0;
index 3d1491b..16d7150 100644 (file)
@@ -90,8 +90,6 @@ static const struct ehci_driver_overrides ehci_omap_overrides __initdata = {
        .extra_priv_size = sizeof(struct omap_hcd),
 };
 
-static u64 omap_ehci_dma_mask = DMA_BIT_MASK(32);
-
 /**
  * ehci_hcd_omap_probe - initialize TI-based HCDs
  *
@@ -146,8 +144,10 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
         * Since shared usb code relies on it, set it here for now.
         * Once we have dma capability bindings this can go away.
         */
-       if (!pdev->dev.dma_mask)
-               pdev->dev.dma_mask = &omap_ehci_dma_mask;
+       if (!dev->dma_mask)
+               dev->dma_mask = &dev->coherent_dma_mask;
+       if (!dev->coherent_dma_mask)
+               dev->coherent_dma_mask = DMA_BIT_MASK(32);
 
        hcd = usb_create_hcd(&ehci_omap_hc_driver, dev,
                        dev_name(dev));
index 54c5794..efbc588 100644 (file)
@@ -137,8 +137,6 @@ ehci_orion_conf_mbus_windows(struct usb_hcd *hcd,
        }
 }
 
-static u64 ehci_orion_dma_mask = DMA_BIT_MASK(32);
-
 static int ehci_orion_drv_probe(struct platform_device *pdev)
 {
        struct orion_ehci_data *pd = pdev->dev.platform_data;
@@ -183,7 +181,9 @@ static int ehci_orion_drv_probe(struct platform_device *pdev)
         * now. Once we have dma capability bindings this can go away.
         */
        if (!pdev->dev.dma_mask)
-               pdev->dev.dma_mask = &ehci_orion_dma_mask;
+               pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
+       if (!pdev->dev.coherent_dma_mask)
+               pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
 
        if (!request_mem_region(res->start, resource_size(res),
                                ehci_orion_hc_driver.description)) {
index 6357752..379037f 100644 (file)
@@ -71,8 +71,6 @@ static void s5p_setup_vbus_gpio(struct platform_device *pdev)
                dev_err(dev, "can't request ehci vbus gpio %d", gpio);
 }
 
-static u64 ehci_s5p_dma_mask = DMA_BIT_MASK(32);
-
 static int s5p_ehci_probe(struct platform_device *pdev)
 {
        struct s5p_ehci_platdata *pdata = pdev->dev.platform_data;
@@ -90,7 +88,7 @@ static int s5p_ehci_probe(struct platform_device *pdev)
         * Once we move to full device tree support this will vanish off.
         */
        if (!pdev->dev.dma_mask)
-               pdev->dev.dma_mask = &ehci_s5p_dma_mask;
+               pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
        if (!pdev->dev.coherent_dma_mask)
                pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
 
@@ -107,6 +105,7 @@ static int s5p_ehci_probe(struct platform_device *pdev)
        if (IS_ERR(phy)) {
                /* Fallback to pdata */
                if (!pdata) {
+                       usb_put_hcd(hcd);
                        dev_warn(&pdev->dev, "no platform data or transceiver defined\n");
                        return -EPROBE_DEFER;
                } else {
index acff5b8..f80d033 100644 (file)
@@ -213,7 +213,7 @@ static inline unsigned char tt_start_uframe(struct ehci_hcd *ehci, __hc32 mask)
 }
 
 static const unsigned char
-max_tt_usecs[] = { 125, 125, 125, 125, 125, 125, 125, 25 };
+max_tt_usecs[] = { 125, 125, 125, 125, 125, 125, 30, 0 };
 
 /* carryover low/fullspeed bandwidth that crosses uframe boundries */
 static inline void carryover_tt_bandwidth(unsigned short tt_usecs[8])
@@ -646,6 +646,10 @@ static void end_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh)
        /* reschedule QH iff another request is queued */
        if (!list_empty(&qh->qtd_list) && ehci->rh_state == EHCI_RH_RUNNING) {
                rc = qh_schedule(ehci, qh);
+               if (rc == 0) {
+                       qh_refresh(ehci, qh);
+                       qh_link_periodic(ehci, qh);
+               }
 
                /* An error here likely indicates handshake failure
                 * or no space left in the schedule.  Neither fault
@@ -653,9 +657,10 @@ static void end_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh)
                 *
                 * FIXME kill the now-dysfunctional queued urbs
                 */
-               if (rc != 0)
+               else {
                        ehci_err(ehci, "can't reschedule qh %p, err %d\n",
                                        qh, rc);
+               }
        }
 
        /* maybe turn off periodic schedule */
index 61ecfb3..bd3e5cb 100644 (file)
@@ -58,8 +58,6 @@ static int ehci_spear_drv_resume(struct device *dev)
 static SIMPLE_DEV_PM_OPS(ehci_spear_pm_ops, ehci_spear_drv_suspend,
                ehci_spear_drv_resume);
 
-static u64 spear_ehci_dma_mask = DMA_BIT_MASK(32);
-
 static int spear_ehci_hcd_drv_probe(struct platform_device *pdev)
 {
        struct usb_hcd *hcd ;
@@ -84,7 +82,9 @@ static int spear_ehci_hcd_drv_probe(struct platform_device *pdev)
         * Once we have dma capability bindings this can go away.
         */
        if (!pdev->dev.dma_mask)
-               pdev->dev.dma_mask = &spear_ehci_dma_mask;
+               pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
+       if (!pdev->dev.coherent_dma_mask)
+               pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
 
        usbh_clk = devm_clk_get(&pdev->dev, NULL);
        if (IS_ERR(usbh_clk)) {
index e3eddc3..59d111b 100644 (file)
@@ -637,8 +637,6 @@ static void tegra_ehci_set_phcd(struct usb_phy *x, bool enable)
        writel(val, base + TEGRA_USB_PORTSC1);
 }
 
-static u64 tegra_ehci_dma_mask = DMA_BIT_MASK(32);
-
 static int tegra_ehci_probe(struct platform_device *pdev)
 {
        struct resource *res;
@@ -661,7 +659,9 @@ static int tegra_ehci_probe(struct platform_device *pdev)
         * Once we have dma capability bindings this can go away.
         */
        if (!pdev->dev.dma_mask)
-               pdev->dev.dma_mask = &tegra_ehci_dma_mask;
+               pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
+       if (!pdev->dev.coherent_dma_mask)
+               pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
 
        setup_vbus_gpio(pdev, pdata);
 
index 125e261..2facee5 100644 (file)
@@ -1739,7 +1739,7 @@ static int isp1760_hub_status_data(struct usb_hcd *hcd, char *buf)
        int retval = 1;
        unsigned long flags;
 
-       /* if !USB_SUSPEND, root hub timers won't get shut down ... */
+       /* if !PM_RUNTIME, root hub timers won't get shut down ... */
        if (!HC_IS_RUNNING(hcd->state))
                return 0;
 
index bbb791b..a13709e 100644 (file)
@@ -373,8 +373,10 @@ static int isp1760_plat_probe(struct platform_device *pdev)
        irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
        if (!irq_res) {
                pr_warning("isp1760: IRQ resource not available\n");
-               return -ENODEV;
+               ret = -ENODEV;
+               goto cleanup;
        }
+
        irqflags |= irq_res->flags & IRQF_TRIGGER_MASK;
 
        if (priv) {
index a0cb44f..2ee1496 100644 (file)
@@ -504,8 +504,6 @@ static const struct of_device_id at91_ohci_dt_ids[] = {
 
 MODULE_DEVICE_TABLE(of, at91_ohci_dt_ids);
 
-static u64 at91_ohci_dma_mask = DMA_BIT_MASK(32);
-
 static int ohci_at91_of_init(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
@@ -522,7 +520,9 @@ static int ohci_at91_of_init(struct platform_device *pdev)
         * Once we have dma capability bindings this can go away.
         */
        if (!pdev->dev.dma_mask)
-               pdev->dev.dma_mask = &at91_ohci_dma_mask;
+               pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
+       if (!pdev->dev.coherent_dma_mask)
+               pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
 
        pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
        if (!pdata)
index 07592c0..b0b542c 100644 (file)
@@ -98,8 +98,6 @@ static const struct hc_driver exynos_ohci_hc_driver = {
        .start_port_reset       = ohci_start_port_reset,
 };
 
-static u64 ohci_exynos_dma_mask = DMA_BIT_MASK(32);
-
 static int exynos_ohci_probe(struct platform_device *pdev)
 {
        struct exynos4_ohci_platdata *pdata = pdev->dev.platform_data;
@@ -117,7 +115,7 @@ static int exynos_ohci_probe(struct platform_device *pdev)
         * Once we move to full device tree support this will vanish off.
         */
        if (!pdev->dev.dma_mask)
-               pdev->dev.dma_mask = &ohci_exynos_dma_mask;
+               pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
        if (!pdev->dev.coherent_dma_mask)
                pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
 
index 9e6de95..fc627fd 100644 (file)
@@ -233,14 +233,14 @@ static int ohci_urb_enqueue (
                        urb->start_frame = frame;
                }
        } else if (ed->type == PIPE_ISOCHRONOUS) {
-               u16     next = ohci_frame_no(ohci) + 2;
+               u16     next = ohci_frame_no(ohci) + 1;
                u16     frame = ed->last_iso + ed->interval;
 
                /* Behind the scheduling threshold? */
                if (unlikely(tick_before(frame, next))) {
 
                        /* USB_ISO_ASAP: Round up to the first available slot */
-                       if (urb->transfer_flags & URB_ISO_ASAP)
+                       if (urb->transfer_flags & URB_ISO_ASAP) {
                                frame += (next - frame + ed->interval - 1) &
                                                -ed->interval;
 
@@ -248,21 +248,25 @@ static int ohci_urb_enqueue (
                         * Not ASAP: Use the next slot in the stream.  If
                         * the entire URB falls before the threshold, fail.
                         */
-                       else if (tick_before(frame + ed->interval *
+                       } else {
+                               if (tick_before(frame + ed->interval *
                                        (urb->number_of_packets - 1), next)) {
-                               retval = -EXDEV;
-                               usb_hcd_unlink_urb_from_ep(hcd, urb);
-                               goto fail;
-                       }
+                                       retval = -EXDEV;
+                                       usb_hcd_unlink_urb_from_ep(hcd, urb);
+                                       goto fail;
+                               }
 
-                       /*
-                        * Some OHCI hardware doesn't handle late TDs
-                        * correctly.  After retiring them it proceeds to
-                        * the next ED instead of the next TD.  Therefore
-                        * we have to omit the late TDs entirely.
-                        */
-                       urb_priv->td_cnt = DIV_ROUND_UP(next - frame,
-                                       ed->interval);
+                               /*
+                                * Some OHCI hardware doesn't handle late TDs
+                                * correctly.  After retiring them it proceeds
+                                * to the next ED instead of the next TD.
+                                * Therefore we have to omit the late TDs
+                                * entirely.
+                                */
+                               urb_priv->td_cnt = DIV_ROUND_UP(
+                                               (u16) (next - frame),
+                                               ed->interval);
+                       }
                }
                urb->start_frame = frame;
        }
index f4988fb..5d7eb72 100644 (file)
@@ -223,8 +223,7 @@ static int usb_hcd_nxp_probe(struct platform_device *pdev)
 
        isp1301_i2c_client = isp1301_get_client(isp1301_node);
        if (!isp1301_i2c_client) {
-               ret = -EPROBE_DEFER;
-               goto out;
+               return -EPROBE_DEFER;
        }
 
        pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
@@ -234,7 +233,7 @@ static int usb_hcd_nxp_probe(struct platform_device *pdev)
        if (usb_disabled()) {
                dev_err(&pdev->dev, "USB is disabled\n");
                ret = -ENODEV;
-               goto out;
+               goto fail_disable;
        }
 
        /* Enable AHB slave USB clock, needed for further USB clock control */
@@ -245,19 +244,19 @@ static int usb_hcd_nxp_probe(struct platform_device *pdev)
        if (IS_ERR(usb_pll_clk)) {
                dev_err(&pdev->dev, "failed to acquire USB PLL\n");
                ret = PTR_ERR(usb_pll_clk);
-               goto out1;
+               goto fail_pll;
        }
 
        ret = clk_enable(usb_pll_clk);
        if (ret < 0) {
                dev_err(&pdev->dev, "failed to start USB PLL\n");
-               goto out2;
+               goto fail_pllen;
        }
 
        ret = clk_set_rate(usb_pll_clk, 48000);
        if (ret < 0) {
                dev_err(&pdev->dev, "failed to set USB clock rate\n");
-               goto out3;
+               goto fail_rate;
        }
 
        /* Enable USB device clock */
@@ -265,13 +264,13 @@ static int usb_hcd_nxp_probe(struct platform_device *pdev)
        if (IS_ERR(usb_dev_clk)) {
                dev_err(&pdev->dev, "failed to acquire USB DEV Clock\n");
                ret = PTR_ERR(usb_dev_clk);
-               goto out4;
+               goto fail_dev;
        }
 
        ret = clk_enable(usb_dev_clk);
        if (ret < 0) {
                dev_err(&pdev->dev, "failed to start USB DEV Clock\n");
-               goto out5;
+               goto fail_deven;
        }
 
        /* Enable USB otg clocks */
@@ -279,7 +278,7 @@ static int usb_hcd_nxp_probe(struct platform_device *pdev)
        if (IS_ERR(usb_otg_clk)) {
                dev_err(&pdev->dev, "failed to acquire USB DEV Clock\n");
                ret = PTR_ERR(usb_otg_clk);
-               goto out6;
+               goto fail_otg;
        }
 
        __raw_writel(__raw_readl(USB_CTRL) | USB_HOST_NEED_CLK_EN, USB_CTRL);
@@ -287,7 +286,7 @@ static int usb_hcd_nxp_probe(struct platform_device *pdev)
        ret = clk_enable(usb_otg_clk);
        if (ret < 0) {
                dev_err(&pdev->dev, "failed to start USB DEV Clock\n");
-               goto out7;
+               goto fail_otgen;
        }
 
        isp1301_configure();
@@ -296,20 +295,14 @@ static int usb_hcd_nxp_probe(struct platform_device *pdev)
        if (!hcd) {
                dev_err(&pdev->dev, "Failed to allocate HC buffer\n");
                ret = -ENOMEM;
-               goto out8;
+               goto fail_hcd;
        }
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(&pdev->dev, "Failed to get MEM resource\n");
-               ret =  -ENOMEM;
-               goto out8;
-       }
-
        hcd->regs = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(hcd->regs)) {
                ret = PTR_ERR(hcd->regs);
-               goto out8;
+               goto fail_resource;
        }
        hcd->rsrc_start = res->start;
        hcd->rsrc_len = resource_size(res);
@@ -317,7 +310,7 @@ static int usb_hcd_nxp_probe(struct platform_device *pdev)
        irq = platform_get_irq(pdev, 0);
        if (irq < 0) {
                ret = -ENXIO;
-               goto out8;
+               goto fail_resource;
        }
 
        nxp_start_hc();
@@ -331,23 +324,24 @@ static int usb_hcd_nxp_probe(struct platform_device *pdev)
                return ret;
 
        nxp_stop_hc();
-out8:
+fail_resource:
        usb_put_hcd(hcd);
-out7:
+fail_hcd:
        clk_disable(usb_otg_clk);
-out6:
+fail_otgen:
        clk_put(usb_otg_clk);
-out5:
+fail_otg:
        clk_disable(usb_dev_clk);
-out4:
+fail_deven:
        clk_put(usb_dev_clk);
-out3:
+fail_dev:
+fail_rate:
        clk_disable(usb_pll_clk);
-out2:
+fail_pllen:
        clk_put(usb_pll_clk);
-out1:
+fail_pll:
+fail_disable:
        isp1301_i2c_client = NULL;
-out:
        return ret;
 }
 
index ddfc314..8663851 100644 (file)
@@ -114,8 +114,6 @@ static const struct hc_driver ohci_omap3_hc_driver = {
 
 /*-------------------------------------------------------------------------*/
 
-static u64 omap_ohci_dma_mask = DMA_BIT_MASK(32);
-
 /*
  * configure so an HC device and id are always provided
  * always called with process context; sleeping is OK
@@ -168,8 +166,10 @@ static int ohci_hcd_omap3_probe(struct platform_device *pdev)
         * Since shared usb code relies on it, set it here for now.
         * Once we have dma capability bindings this can go away.
         */
-       if (!pdev->dev.dma_mask)
-               pdev->dev.dma_mask = &omap_ohci_dma_mask;
+       if (!dev->dma_mask)
+               dev->dma_mask = &dev->coherent_dma_mask;
+       if (!dev->coherent_dma_mask)
+               dev->coherent_dma_mask = DMA_BIT_MASK(32);
 
        hcd = usb_create_hcd(&ohci_omap3_hc_driver, dev,
                        dev_name(dev));
index efe71f3..279b2ef 100644 (file)
@@ -282,8 +282,6 @@ static const struct of_device_id pxa_ohci_dt_ids[] = {
 
 MODULE_DEVICE_TABLE(of, pxa_ohci_dt_ids);
 
-static u64 pxa_ohci_dma_mask = DMA_BIT_MASK(32);
-
 static int ohci_pxa_of_init(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
@@ -298,7 +296,9 @@ static int ohci_pxa_of_init(struct platform_device *pdev)
         * Once we have dma capability bindings this can go away.
         */
        if (!pdev->dev.dma_mask)
-               pdev->dev.dma_mask = &pxa_ohci_dma_mask;
+               pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
+       if (!pdev->dev.coherent_dma_mask)
+               pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
 
        pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
        if (!pdata)
index 9020bf0..3e19e01 100644 (file)
@@ -91,8 +91,6 @@ static const struct hc_driver ohci_spear_hc_driver = {
        .start_port_reset       = ohci_start_port_reset,
 };
 
-static u64 spear_ohci_dma_mask = DMA_BIT_MASK(32);
-
 static int spear_ohci_hcd_drv_probe(struct platform_device *pdev)
 {
        const struct hc_driver *driver = &ohci_spear_hc_driver;
@@ -114,7 +112,9 @@ static int spear_ohci_hcd_drv_probe(struct platform_device *pdev)
         * Once we have dma capability bindings this can go away.
         */
        if (!pdev->dev.dma_mask)
-               pdev->dev.dma_mask = &spear_ohci_dma_mask;
+               pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
+       if (!pdev->dev.coherent_dma_mask)
+               pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
 
        usbh_clk = devm_clk_get(&pdev->dev, NULL);
        if (IS_ERR(usbh_clk)) {
index 4f0f033..0f401db 100644 (file)
@@ -3084,7 +3084,7 @@ static int oxu_hub_status_data(struct usb_hcd *hcd, char *buf)
        int ports, i, retval = 1;
        unsigned long flags;
 
-       /* if !USB_SUSPEND, root hub timers won't get shut down ... */
+       /* if !PM_RUNTIME, root hub timers won't get shut down ... */
        if (!HC_IS_RUNNING(hcd->state))
                return 0;
 
index ad4483e..b2ec7fe 100644 (file)
@@ -22,7 +22,7 @@
  * and usb-storage.
  *
  * TODO:
- * - usb suspend/resume triggered by sl811 (with USB_SUSPEND)
+ * - usb suspend/resume triggered by sl811 (with PM_RUNTIME)
  * - various issues noted in the code
  * - performance work; use both register banks; ...
  * - use urb->iso_frame_desc[] with ISO transfers
index f87bee6..9189bc9 100644 (file)
@@ -225,7 +225,8 @@ static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf)
                /* auto-stop if nothing connected for 1 second */
                if (any_ports_active(uhci))
                        uhci->rh_state = UHCI_RH_RUNNING;
-               else if (time_after_eq(jiffies, uhci->auto_stop_time))
+               else if (time_after_eq(jiffies, uhci->auto_stop_time) &&
+                               !uhci->wait_for_hp)
                        suspend_rh(uhci, UHCI_RH_AUTO_STOPPED);
                break;
 
index 8c4dace..f1db61a 100644 (file)
@@ -60,8 +60,6 @@ static const struct hc_driver uhci_platform_hc_driver = {
        .hub_control =          uhci_hub_control,
 };
 
-static u64 platform_uhci_dma_mask = DMA_BIT_MASK(32);
-
 static int uhci_hcd_platform_probe(struct platform_device *pdev)
 {
        struct usb_hcd *hcd;
@@ -78,7 +76,9 @@ static int uhci_hcd_platform_probe(struct platform_device *pdev)
         * Once we have dma capability bindings this can go away.
         */
        if (!pdev->dev.dma_mask)
-               pdev->dev.dma_mask = &platform_uhci_dma_mask;
+               pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
+       if (!pdev->dev.coherent_dma_mask)
+               pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
 
        hcd = usb_create_hcd(&uhci_platform_hc_driver, &pdev->dev,
                        pdev->name);
index f0976d8..041c6dd 100644 (file)
@@ -1287,7 +1287,7 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
                return -EINVAL;         /* Can't change the period */
 
        } else {
-               next = uhci->frame_number + 2;
+               next = uhci->frame_number + 1;
 
                /* Find the next unused frame */
                if (list_empty(&qh->queue)) {
index 965b539..fbf75e5 100644 (file)
@@ -1423,15 +1423,17 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
        ep_ctx->ep_info2 |= cpu_to_le32(xhci_get_endpoint_type(udev, ep));
 
        /* Set the max packet size and max burst */
+       max_packet = GET_MAX_PACKET(usb_endpoint_maxp(&ep->desc));
+       max_burst = 0;
        switch (udev->speed) {
        case USB_SPEED_SUPER:
-               max_packet = usb_endpoint_maxp(&ep->desc);
-               ep_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(max_packet));
                /* dig out max burst from ep companion desc */
-               max_packet = ep->ss_ep_comp.bMaxBurst;
-               ep_ctx->ep_info2 |= cpu_to_le32(MAX_BURST(max_packet));
+               max_burst = ep->ss_ep_comp.bMaxBurst;
                break;
        case USB_SPEED_HIGH:
+               /* Some devices get this wrong */
+               if (usb_endpoint_xfer_bulk(&ep->desc))
+                       max_packet = 512;
                /* bits 11:12 specify the number of additional transaction
                 * opportunities per microframe (USB 2.0, section 9.6.6)
                 */
@@ -1439,17 +1441,16 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
                                usb_endpoint_xfer_int(&ep->desc)) {
                        max_burst = (usb_endpoint_maxp(&ep->desc)
                                     & 0x1800) >> 11;
-                       ep_ctx->ep_info2 |= cpu_to_le32(MAX_BURST(max_burst));
                }
-               /* Fall through */
+               break;
        case USB_SPEED_FULL:
        case USB_SPEED_LOW:
-               max_packet = GET_MAX_PACKET(usb_endpoint_maxp(&ep->desc));
-               ep_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(max_packet));
                break;
        default:
                BUG();
        }
+       ep_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(max_packet) |
+                       MAX_BURST(max_burst));
        max_esit_payload = xhci_get_max_esit_payload(xhci, udev, ep);
        ep_ctx->tx_info = cpu_to_le32(MAX_ESIT_PAYLOAD_FOR_EP(max_esit_payload));
 
@@ -1826,6 +1827,9 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
        }
        spin_unlock_irqrestore(&xhci->lock, flags);
 
+       if (!xhci->rh_bw)
+               goto no_bw;
+
        num_ports = HCS_MAX_PORTS(xhci->hcs_params1);
        for (i = 0; i < num_ports; i++) {
                struct xhci_interval_bw_table *bwt = &xhci->rh_bw[i].bw_table;
@@ -1844,6 +1848,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
                }
        }
 
+no_bw:
        xhci->num_usb2_ports = 0;
        xhci->num_usb3_ports = 0;
        xhci->num_active_eps = 0;
@@ -2255,6 +2260,9 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
        u32 page_size, temp;
        int i;
 
+       INIT_LIST_HEAD(&xhci->lpm_failed_devs);
+       INIT_LIST_HEAD(&xhci->cancel_cmd_list);
+
        page_size = xhci_readl(xhci, &xhci->op_regs->page_size);
        xhci_dbg(xhci, "Supported page size register = 0x%x\n", page_size);
        for (i = 0; i < 16; i++) {
@@ -2333,7 +2341,6 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
        xhci->cmd_ring = xhci_ring_alloc(xhci, 1, 1, TYPE_COMMAND, flags);
        if (!xhci->cmd_ring)
                goto fail;
-       INIT_LIST_HEAD(&xhci->cancel_cmd_list);
        xhci_dbg(xhci, "Allocated command ring at %p\n", xhci->cmd_ring);
        xhci_dbg(xhci, "First segment DMA is 0x%llx\n",
                        (unsigned long long)xhci->cmd_ring->first_seg->dma);
@@ -2444,8 +2451,6 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
        if (xhci_setup_port_arrays(xhci, flags))
                goto fail;
 
-       INIT_LIST_HEAD(&xhci->lpm_failed_devs);
-
        /* Enable USB 3.0 device notifications for function remote wake, which
         * is necessary for allowing USB 3.0 devices to do remote wakeup from
         * U3 (device suspend).
index 1a30c38..cc24e39 100644 (file)
@@ -221,6 +221,14 @@ static void xhci_pci_remove(struct pci_dev *dev)
 static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
 {
        struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+       struct pci_dev          *pdev = to_pci_dev(hcd->self.controller);
+
+       /*
+        * Systems with the TI redriver that loses port status change events
+        * need to have the registers polled during D3, so avoid D3cold.
+        */
+       if (xhci_compliance_mode_recovery_timer_quirk_check())
+               pdev->no_d3cold = true;
 
        return xhci_suspend(xhci);
 }
index b4aa79d..d8f640b 100644 (file)
@@ -466,7 +466,7 @@ static void compliance_mode_recovery_timer_init(struct xhci_hcd *xhci)
  * Systems:
  * Vendor: Hewlett-Packard -> System Models: Z420, Z620 and Z820
  */
-static bool compliance_mode_recovery_timer_quirk_check(void)
+bool xhci_compliance_mode_recovery_timer_quirk_check(void)
 {
        const char *dmi_product_name, *dmi_sys_vendor;
 
@@ -517,7 +517,7 @@ int xhci_init(struct usb_hcd *hcd)
        xhci_dbg(xhci, "Finished xhci_init\n");
 
        /* Initializing Compliance Mode Recovery Data If Needed */
-       if (compliance_mode_recovery_timer_quirk_check()) {
+       if (xhci_compliance_mode_recovery_timer_quirk_check()) {
                xhci->quirks |= XHCI_COMP_MODE_QUIRK;
                compliance_mode_recovery_timer_init(xhci);
        }
@@ -956,6 +956,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
        struct usb_hcd          *hcd = xhci_to_hcd(xhci);
        struct usb_hcd          *secondary_hcd;
        int                     retval = 0;
+       bool                    comp_timer_running = false;
 
        /* Wait a bit if either of the roothubs need to settle from the
         * transition into bus suspend.
@@ -993,6 +994,13 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
 
        /* If restore operation fails, re-initialize the HC during resume */
        if ((temp & STS_SRE) || hibernated) {
+
+               if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) &&
+                               !(xhci_all_ports_seen_u0(xhci))) {
+                       del_timer_sync(&xhci->comp_mode_recovery_timer);
+                       xhci_dbg(xhci, "Compliance Mode Recovery Timer deleted!\n");
+               }
+
                /* Let the USB core know _both_ roothubs lost power. */
                usb_root_hub_lost_power(xhci->main_hcd->self.root_hub);
                usb_root_hub_lost_power(xhci->shared_hcd->self.root_hub);
@@ -1035,6 +1043,8 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
                retval = xhci_init(hcd->primary_hcd);
                if (retval)
                        return retval;
+               comp_timer_running = true;
+
                xhci_dbg(xhci, "Start the primary HCD\n");
                retval = xhci_run(hcd->primary_hcd);
                if (!retval) {
@@ -1076,7 +1086,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
         * to suffer the Compliance Mode issue again. It doesn't matter if
         * ports have entered previously to U0 before system's suspension.
         */
-       if (xhci->quirks & XHCI_COMP_MODE_QUIRK)
+       if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) && !comp_timer_running)
                compliance_mode_recovery_timer_init(xhci);
 
        /* Re-enable port polling. */
index 29c978e..77600ce 100644 (file)
@@ -1853,4 +1853,7 @@ struct xhci_input_control_ctx *xhci_get_input_control_ctx(struct xhci_hcd *xhci,
 struct xhci_slot_ctx *xhci_get_slot_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx);
 struct xhci_ep_ctx *xhci_get_ep_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx, unsigned int ep_index);
 
+/* xHCI quirks */
+bool xhci_compliance_mode_recovery_timer_quirk_check(void);
+
 #endif /* __LINUX_XHCI_HCD_H */
index 3a18e44..e1b661d 100644 (file)
@@ -560,6 +560,7 @@ static int dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)
                if (!config) {
                        dev_err(&pdev->dev,
                                "failed to allocate musb hdrc config\n");
+                       ret = -ENOMEM;
                        goto err2;
                }
 
index 8914dec..9d3044b 100644 (file)
@@ -1232,7 +1232,6 @@ void musb_host_tx(struct musb *musb, u8 epnum)
        void __iomem            *mbase = musb->mregs;
        struct dma_channel      *dma;
        bool                    transfer_pending = false;
-       static bool use_sg;
 
        musb_ep_select(mbase, epnum);
        tx_csr = musb_readw(epio, MUSB_TXCSR);
@@ -1463,9 +1462,9 @@ done:
         * NULL.
         */
        if (!urb->transfer_buffer)
-               use_sg = true;
+               qh->use_sg = true;
 
-       if (use_sg) {
+       if (qh->use_sg) {
                /* sg_miter_start is already done in musb_ep_program */
                if (!sg_miter_next(&qh->sg_miter)) {
                        dev_err(musb->controller, "error: sg list empty\n");
@@ -1484,9 +1483,9 @@ done:
 
        qh->segsize = length;
 
-       if (use_sg) {
+       if (qh->use_sg) {
                if (offset + length >= urb->transfer_buffer_length)
-                       use_sg = false;
+                       qh->use_sg = false;
        }
 
        musb_ep_select(mbase, epnum);
@@ -1552,7 +1551,6 @@ void musb_host_rx(struct musb *musb, u8 epnum)
        bool                    done = false;
        u32                     status;
        struct dma_channel      *dma;
-       static bool use_sg;
        unsigned int sg_flags = SG_MITER_ATOMIC | SG_MITER_TO_SG;
 
        musb_ep_select(mbase, epnum);
@@ -1878,12 +1876,12 @@ void musb_host_rx(struct musb *musb, u8 epnum)
                         * NULL.
                         */
                        if (!urb->transfer_buffer) {
-                               use_sg = true;
+                               qh->use_sg = true;
                                sg_miter_start(&qh->sg_miter, urb->sg, 1,
                                                sg_flags);
                        }
 
-                       if (use_sg) {
+                       if (qh->use_sg) {
                                if (!sg_miter_next(&qh->sg_miter)) {
                                        dev_err(musb->controller, "error: sg list empty\n");
                                        sg_miter_stop(&qh->sg_miter);
@@ -1913,8 +1911,8 @@ finish:
        urb->actual_length += xfer_len;
        qh->offset += xfer_len;
        if (done) {
-               if (use_sg)
-                       use_sg = false;
+               if (qh->use_sg)
+                       qh->use_sg = false;
 
                if (urb->status == -EINPROGRESS)
                        urb->status = status;
index 5a9c8fe..738f7eb 100644 (file)
@@ -74,6 +74,7 @@ struct musb_qh {
        u16                     frame;          /* for periodic schedule */
        unsigned                iso_idx;        /* in urb->iso_frame_desc[] */
        struct sg_mapping_iter sg_miter;        /* for highmem in PIO mode */
+       bool                    use_sg;         /* to track urb using sglist */
 };
 
 /* map from control or bulk queue head to the first qh on that ring */
index 3551f1a..628b93f 100644 (file)
@@ -549,7 +549,8 @@ static int omap2430_probe(struct platform_device *pdev)
                glue->control_otghs = omap_get_control_dev();
                if (IS_ERR(glue->control_otghs)) {
                        dev_vdbg(&pdev->dev, "Failed to get control device\n");
-                       return -ENODEV;
+                       ret = PTR_ERR(glue->control_otghs);
+                       goto err2;
                }
        } else {
                glue->control_otghs = ERR_PTR(-ENODEV);
index 371d0e7..7ef3eb8 100644 (file)
@@ -25,7 +25,7 @@ config AB8500_USB
 
 config FSL_USB2_OTG
        bool "Freescale USB OTG Transceiver Driver"
-       depends on USB_EHCI_FSL && USB_FSL_USB2 && USB_SUSPEND
+       depends on USB_EHCI_FSL && USB_FSL_USB2 && PM_RUNTIME
        select USB_OTG
        help
          Enable this to support Freescale USB OTG transceiver.
@@ -139,7 +139,6 @@ config USB_ISP1301
        tristate "NXP ISP1301 USB transceiver support"
        depends on USB || USB_GADGET
        depends on I2C
-       select USB_OTG_UTILS
        help
          Say Y here to add support for the NXP ISP1301 USB transceiver driver.
          This chip is typically used as USB transceiver for USB host, gadget
@@ -162,7 +161,7 @@ config USB_MSM_OTG
 
 config USB_MV_OTG
        tristate "Marvell USB OTG support"
-       depends on USB_EHCI_MV && USB_MV_UDC && USB_SUSPEND
+       depends on USB_EHCI_MV && USB_MV_UDC && PM_RUNTIME
        select USB_OTG
        help
          Say Y here if you want to build Marvell USB OTG transciever
index 4acef26..e5eb1b5 100644 (file)
@@ -892,8 +892,6 @@ static int ab8500_usb_remove(struct platform_device *pdev)
        else if (ab->mode == USB_PERIPHERAL)
                ab8500_usb_peri_phy_dis(ab);
 
-       platform_set_drvdata(pdev, NULL);
-
        return 0;
 }
 
index 97b9308..e771baf 100644 (file)
@@ -799,6 +799,7 @@ static int fsl_otg_conf(struct platform_device *pdev)
 
        /* initialize the otg structure */
        fsl_otg_tc->phy.label = DRIVER_DESC;
+       fsl_otg_tc->phy.dev = &pdev->dev;
        fsl_otg_tc->phy.set_power = fsl_otg_set_power;
 
        fsl_otg_tc->phy.otg->phy = &fsl_otg_tc->phy;
index 4c76074..8443335 100644 (file)
@@ -266,6 +266,7 @@ static int __init gpio_vbus_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, gpio_vbus);
        gpio_vbus->dev = &pdev->dev;
        gpio_vbus->phy.label = "gpio-vbus";
+       gpio_vbus->phy.dev = gpio_vbus->dev;
        gpio_vbus->phy.set_power = gpio_vbus_set_power;
        gpio_vbus->phy.set_suspend = gpio_vbus_set_suspend;
        gpio_vbus->phy.state = OTG_STATE_UNDEFINED;
@@ -343,7 +344,6 @@ err_irq:
                gpio_free(pdata->gpio_pullup);
        gpio_free(pdata->gpio_vbus);
 err_gpio:
-       platform_set_drvdata(pdev, NULL);
        kfree(gpio_vbus->phy.otg);
        kfree(gpio_vbus);
        return err;
@@ -365,7 +365,6 @@ static int __exit gpio_vbus_remove(struct platform_device *pdev)
        if (gpio_is_valid(pdata->gpio_pullup))
                gpio_free(pdata->gpio_pullup);
        gpio_free(gpio);
-       platform_set_drvdata(pdev, NULL);
        kfree(gpio_vbus->phy.otg);
        kfree(gpio_vbus);
 
index 225ae6c..8a55b37 100644 (file)
@@ -102,6 +102,7 @@ static int isp1301_probe(struct i2c_client *client,
        mutex_init(&isp->mutex);
 
        phy = &isp->phy;
+       phy->dev = &client->dev;
        phy->label = DRV_NAME;
        phy->init = isp1301_phy_init;
        phy->set_vbus = isp1301_phy_set_vbus;
index f7838a4..1568ea6 100644 (file)
@@ -278,11 +278,6 @@ static int mv_u3d_phy_probe(struct platform_device *pdev)
        }
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(dev, "missing mem resource\n");
-               return -ENODEV;
-       }
-
        phy_base = devm_ioremap_resource(dev, res);
        if (IS_ERR(phy_base))
                return PTR_ERR(phy_base);
index c987bbe..4a6b03c 100644 (file)
@@ -667,7 +667,6 @@ int mv_otg_remove(struct platform_device *pdev)
        mv_otg_disable(mvotg);
 
        usb_remove_phy(&mvotg->phy);
-       platform_set_drvdata(pdev, NULL);
 
        return 0;
 }
@@ -850,8 +849,6 @@ err_destroy_workqueue:
        flush_workqueue(mvotg->qwork);
        destroy_workqueue(mvotg->qwork);
 
-       platform_set_drvdata(pdev, NULL);
-
        return retval;
 }
 
index 9d4381e..bd601c5 100644 (file)
@@ -130,11 +130,6 @@ static int mxs_phy_probe(struct platform_device *pdev)
        int ret;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(&pdev->dev, "can't get device resources\n");
-               return -ENOENT;
-       }
-
        base = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(base))
                return PTR_ERR(base);
@@ -160,6 +155,7 @@ static int mxs_phy_probe(struct platform_device *pdev)
        mxs_phy->phy.set_suspend        = mxs_phy_suspend;
        mxs_phy->phy.notify_connect     = mxs_phy_on_connect;
        mxs_phy->phy.notify_disconnect  = mxs_phy_on_disconnect;
+       mxs_phy->phy.type               = USB_PHY_TYPE_USB2;
 
        ATOMIC_INIT_NOTIFIER_HEAD(&mxs_phy->phy.notifier);
 
@@ -180,8 +176,6 @@ static int mxs_phy_remove(struct platform_device *pdev)
 
        usb_remove_phy(&mxs_phy->phy);
 
-       platform_set_drvdata(pdev, NULL);
-
        return 0;
 }
 
index 2b10cc9..638cc5d 100644 (file)
@@ -254,8 +254,6 @@ static int nop_usb_xceiv_remove(struct platform_device *pdev)
 
        usb_remove_phy(&nop->phy);
 
-       platform_set_drvdata(pdev, NULL);
-
        return 0;
 }
 
index 45ffe03..9d5e273 100644 (file)
@@ -363,11 +363,6 @@ static int samsung_usb2phy_probe(struct platform_device *pdev)
        int ret;
 
        phy_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!phy_mem) {
-               dev_err(dev, "%s: missing mem resource\n", __func__);
-               return -ENODEV;
-       }
-
        phy_base = devm_ioremap_resource(dev, phy_mem);
        if (IS_ERR(phy_base))
                return PTR_ERR(phy_base);
index 133f3d0..5a9efcb 100644 (file)
@@ -239,11 +239,6 @@ static int samsung_usb3phy_probe(struct platform_device *pdev)
        int ret;
 
        phy_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!phy_mem) {
-               dev_err(dev, "%s: missing mem resource\n", __func__);
-               return -ENODEV;
-       }
-
        phy_base = devm_ioremap_resource(dev, phy_mem);
        if (IS_ERR(phy_base))
                return PTR_ERR(phy_base);
index 3b16118..40e7fd9 100644 (file)
@@ -43,7 +43,7 @@
 #define DRIVER_NAME "ark3116"
 
 /* usb timeout of 1 second */
-#define ARK_TIMEOUT (1*HZ)
+#define ARK_TIMEOUT 1000
 
 static const struct usb_device_id id_table[] = {
        { USB_DEVICE(0x6547, 0x0232) },
index d341555..0821201 100644 (file)
@@ -65,6 +65,7 @@ static const struct usb_device_id id_table_earthmate[] = {
 static const struct usb_device_id id_table_cyphidcomrs232[] = {
        { USB_DEVICE(VENDOR_ID_CYPRESS, PRODUCT_ID_CYPHIDCOM) },
        { USB_DEVICE(VENDOR_ID_POWERCOM, PRODUCT_ID_UPS) },
+       { USB_DEVICE(VENDOR_ID_FRWD, PRODUCT_ID_CYPHIDCOM_FRWD) },
        { }                                             /* Terminating entry */
 };
 
@@ -78,6 +79,7 @@ static const struct usb_device_id id_table_combined[] = {
        { USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB_LT20) },
        { USB_DEVICE(VENDOR_ID_CYPRESS, PRODUCT_ID_CYPHIDCOM) },
        { USB_DEVICE(VENDOR_ID_POWERCOM, PRODUCT_ID_UPS) },
+       { USB_DEVICE(VENDOR_ID_FRWD, PRODUCT_ID_CYPHIDCOM_FRWD) },
        { USB_DEVICE(VENDOR_ID_DAZZLE, PRODUCT_ID_CA42) },
        { }                                             /* Terminating entry */
 };
@@ -229,6 +231,12 @@ static struct usb_serial_driver * const serial_drivers[] = {
  * Cypress serial helper functions
  *****************************************************************************/
 
+/* FRWD Dongle hidcom needs to skip reset and speed checks */
+static inline bool is_frwd(struct usb_device *dev)
+{
+       return ((le16_to_cpu(dev->descriptor.idVendor) == VENDOR_ID_FRWD) &&
+               (le16_to_cpu(dev->descriptor.idProduct) == PRODUCT_ID_CYPHIDCOM_FRWD));
+}
 
 static int analyze_baud_rate(struct usb_serial_port *port, speed_t new_rate)
 {
@@ -238,6 +246,10 @@ static int analyze_baud_rate(struct usb_serial_port *port, speed_t new_rate)
        if (unstable_bauds)
                return new_rate;
 
+       /* FRWD Dongle uses 115200 bps */
+       if (is_frwd(port->serial->dev))
+               return new_rate;
+
        /*
         * The general purpose firmware for the Cypress M8 allows for
         * a maximum speed of 57600bps (I have no idea whether DeLorme
@@ -448,7 +460,11 @@ static int cypress_generic_port_probe(struct usb_serial_port *port)
                return -ENOMEM;
        }
 
-       usb_reset_configuration(serial->dev);
+       /* Skip reset for FRWD device. It is a workaound:
+          device hangs if it receives SET_CONFIGURE in Configured
+          state. */
+       if (!is_frwd(serial->dev))
+               usb_reset_configuration(serial->dev);
 
        priv->cmd_ctrl = 0;
        priv->line_control = 0;
index 67cf608..b461311 100644 (file)
 #define VENDOR_ID_CYPRESS              0x04b4
 #define PRODUCT_ID_CYPHIDCOM           0x5500
 
+/* FRWD Dongle - a GPS sports watch */
+#define VENDOR_ID_FRWD                 0x6737
+#define PRODUCT_ID_CYPHIDCOM_FRWD      0x0001
+
 /* Powercom UPS, chip CY7C63723 */
 #define VENDOR_ID_POWERCOM             0x0d9f
 #define PRODUCT_ID_UPS                 0x0002
index 242b577..7260ec6 100644 (file)
@@ -189,6 +189,8 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_GBM_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_GBM_BOOST_PID) },
        { USB_DEVICE(NEWPORT_VID, NEWPORT_AGILIS_PID) },
+       { USB_DEVICE(NEWPORT_VID, NEWPORT_CONEX_CC_PID) },
+       { USB_DEVICE(NEWPORT_VID, NEWPORT_CONEX_AGP_PID) },
        { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) },
        { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_SPROG_II) },
@@ -924,8 +926,8 @@ static int  ftdi_tiocmset(struct tty_struct *tty,
 static int  ftdi_ioctl(struct tty_struct *tty,
                        unsigned int cmd, unsigned long arg);
 static void ftdi_break_ctl(struct tty_struct *tty, int break_state);
-static int ftdi_chars_in_buffer(struct tty_struct *tty);
-static int ftdi_get_modem_status(struct tty_struct *tty,
+static bool ftdi_tx_empty(struct usb_serial_port *port);
+static int ftdi_get_modem_status(struct usb_serial_port *port,
                                                unsigned char status[2]);
 
 static unsigned short int ftdi_232am_baud_base_to_divisor(int baud, int base);
@@ -961,7 +963,7 @@ static struct usb_serial_driver ftdi_sio_device = {
        .ioctl =                ftdi_ioctl,
        .set_termios =          ftdi_set_termios,
        .break_ctl =            ftdi_break_ctl,
-       .chars_in_buffer =      ftdi_chars_in_buffer,
+       .tx_empty =             ftdi_tx_empty,
 };
 
 static struct usb_serial_driver * const serial_drivers[] = {
@@ -2056,27 +2058,18 @@ static void ftdi_break_ctl(struct tty_struct *tty, int break_state)
 
 }
 
-static int ftdi_chars_in_buffer(struct tty_struct *tty)
+static bool ftdi_tx_empty(struct usb_serial_port *port)
 {
-       struct usb_serial_port *port = tty->driver_data;
-       int chars;
        unsigned char buf[2];
        int ret;
 
-       chars = usb_serial_generic_chars_in_buffer(tty);
-       if (chars)
-               goto out;
-
-       /* Check if hardware buffer is empty. */
-       ret = ftdi_get_modem_status(tty, buf);
+       ret = ftdi_get_modem_status(port, buf);
        if (ret == 2) {
                if (!(buf[1] & FTDI_RS_TEMT))
-                       chars = 1;
+                       return false;
        }
-out:
-       dev_dbg(&port->dev, "%s - %d\n", __func__, chars);
 
-       return chars;
+       return true;
 }
 
 /* old_termios contains the original termios settings and tty->termios contains
@@ -2268,10 +2261,9 @@ no_c_cflag_changes:
  * Returns the number of status bytes retrieved (device dependant), or
  * negative error code.
  */
-static int ftdi_get_modem_status(struct tty_struct *tty,
+static int ftdi_get_modem_status(struct usb_serial_port *port,
                                                unsigned char status[2])
 {
-       struct usb_serial_port *port = tty->driver_data;
        struct ftdi_private *priv = usb_get_serial_port_data(port);
        unsigned char *buf;
        int len;
@@ -2336,7 +2328,7 @@ static int ftdi_tiocmget(struct tty_struct *tty)
        unsigned char buf[2];
        int ret;
 
-       ret = ftdi_get_modem_status(tty, buf);
+       ret = ftdi_get_modem_status(port, buf);
        if (ret < 0)
                return ret;
 
index 9852827..6dd7925 100644 (file)
  */
 #define NEWPORT_VID                    0x104D
 #define NEWPORT_AGILIS_PID             0x3000
+#define NEWPORT_CONEX_CC_PID           0x3002
+#define NEWPORT_CONEX_AGP_PID          0x3006
 
 /* Interbiometrics USB I/O Board */
 /* Developed for Interbiometrics by Rudolf Gugler */
index 297665f..ba45170 100644 (file)
@@ -253,6 +253,37 @@ int usb_serial_generic_chars_in_buffer(struct tty_struct *tty)
 }
 EXPORT_SYMBOL_GPL(usb_serial_generic_chars_in_buffer);
 
+void usb_serial_generic_wait_until_sent(struct tty_struct *tty, long timeout)
+{
+       struct usb_serial_port *port = tty->driver_data;
+       unsigned int bps;
+       unsigned long period;
+       unsigned long expire;
+
+       bps = tty_get_baud_rate(tty);
+       if (!bps)
+               bps = 9600;     /* B0 */
+       /*
+        * Use a poll-period of roughly the time it takes to send one
+        * character or at least one jiffy.
+        */
+       period = max_t(unsigned long, (10 * HZ / bps), 1);
+       period = min_t(unsigned long, period, timeout);
+
+       dev_dbg(&port->dev, "%s - timeout = %u ms, period = %u ms\n",
+                                       __func__, jiffies_to_msecs(timeout),
+                                       jiffies_to_msecs(period));
+       expire = jiffies + timeout;
+       while (!port->serial->type->tx_empty(port)) {
+               schedule_timeout_interruptible(period);
+               if (signal_pending(current))
+                       break;
+               if (time_after(jiffies, expire))
+                       break;
+       }
+}
+EXPORT_SYMBOL_GPL(usb_serial_generic_wait_until_sent);
+
 static int usb_serial_generic_submit_read_urb(struct usb_serial_port *port,
                                                int index, gfp_t mem_flags)
 {
index 158bf4b..1be6ba7 100644 (file)
@@ -2019,8 +2019,6 @@ static int edge_chars_in_buffer(struct tty_struct *tty)
        struct edgeport_port *edge_port = usb_get_serial_port_data(port);
        int chars = 0;
        unsigned long flags;
-       int ret;
-
        if (edge_port == NULL)
                return 0;
 
@@ -2028,16 +2026,22 @@ static int edge_chars_in_buffer(struct tty_struct *tty)
        chars = kfifo_len(&edge_port->write_fifo);
        spin_unlock_irqrestore(&edge_port->ep_lock, flags);
 
-       if (!chars) {
-               ret = tx_active(edge_port);
-               if (ret > 0)
-                       chars = ret;
-       }
-
        dev_dbg(&port->dev, "%s - returns %d\n", __func__, chars);
        return chars;
 }
 
+static bool edge_tx_empty(struct usb_serial_port *port)
+{
+       struct edgeport_port *edge_port = usb_get_serial_port_data(port);
+       int ret;
+
+       ret = tx_active(edge_port);
+       if (ret > 0)
+               return false;
+
+       return true;
+}
+
 static void edge_throttle(struct tty_struct *tty)
 {
        struct usb_serial_port *port = tty->driver_data;
@@ -2557,6 +2561,7 @@ static struct usb_serial_driver edgeport_1port_device = {
        .write                  = edge_write,
        .write_room             = edge_write_room,
        .chars_in_buffer        = edge_chars_in_buffer,
+       .tx_empty               = edge_tx_empty,
        .break_ctl              = edge_break,
        .read_int_callback      = edge_interrupt_callback,
        .read_bulk_callback     = edge_bulk_in_callback,
@@ -2589,6 +2594,7 @@ static struct usb_serial_driver edgeport_2port_device = {
        .write                  = edge_write,
        .write_room             = edge_write_room,
        .chars_in_buffer        = edge_chars_in_buffer,
+       .tx_empty               = edge_tx_empty,
        .break_ctl              = edge_break,
        .read_int_callback      = edge_interrupt_callback,
        .read_bulk_callback     = edge_bulk_in_callback,
index 9d74c27..790673e 100644 (file)
@@ -287,7 +287,7 @@ static int bulk_immediate(struct usb_serial_port *port, u8 *buf, u8 count)
            usb_bulk_msg(serial->dev,
                         usb_sndbulkpipe(serial->dev,
                                         port->bulk_out_endpointAddress), buf,
-                        count, &actual, HZ * 1);
+                        count, &actual, 1000);
 
        if (status != IUU_OPERATION_OK)
                dev_dbg(&port->dev, "%s - error = %2x\n", __func__, status);
@@ -307,7 +307,7 @@ static int read_immediate(struct usb_serial_port *port, u8 *buf, u8 count)
            usb_bulk_msg(serial->dev,
                         usb_rcvbulkpipe(serial->dev,
                                         port->bulk_in_endpointAddress), buf,
-                        count, &actual, HZ * 1);
+                        count, &actual, 1000);
 
        if (status != IUU_OPERATION_OK)
                dev_dbg(&port->dev, "%s - error = %2x\n", __func__, status);
index eb30d7b..3549d07 100644 (file)
@@ -1548,7 +1548,6 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial,
        struct keyspan_serial_private           *s_priv;
        struct keyspan_port_private             *p_priv;
        const struct keyspan_device_details     *d_details;
-       int                                     outcont_urb;
        struct urb                              *this_urb;
        int                                     device_port, err;
 
@@ -1559,7 +1558,6 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial,
        d_details = s_priv->device_details;
        device_port = port->number - port->serial->minor;
 
-       outcont_urb = d_details->outcont_endpoints[port->number];
        this_urb = p_priv->outcont_urb;
 
        dev_dbg(&port->dev, "%s - endpoint %d\n", __func__, usb_pipeendpoint(this_urb->pipe));
@@ -1685,14 +1683,6 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial,
        err = usb_submit_urb(this_urb, GFP_ATOMIC);
        if (err != 0)
                dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
-#if 0
-       else {
-               dev_dbg(&port->dev, "%s - usb_submit_urb(%d) OK %d bytes (end %d)\n", __func__
-                       outcont_urb, this_urb->transfer_buffer_length,
-                       usb_pipeendpoint(this_urb->pipe));
-       }
-#endif
-
        return 0;
 }
 
index cc0e543..f27c621 100644 (file)
@@ -40,7 +40,7 @@
 #define DRIVER_DESC "Moschip USB Serial Driver"
 
 /* default urb timeout */
-#define MOS_WDR_TIMEOUT        (HZ * 5)
+#define MOS_WDR_TIMEOUT        5000
 
 #define MOS_MAX_PORT   0x02
 #define MOS_WRITE      0x0E
@@ -227,11 +227,22 @@ static int read_mos_reg(struct usb_serial *serial, unsigned int serial_portnum,
        __u8 requesttype = (__u8)0xc0;
        __u16 index = get_reg_index(reg);
        __u16 value = get_reg_value(reg, serial_portnum);
-       int status = usb_control_msg(usbdev, pipe, request, requesttype, value,
-                                    index, data, 1, MOS_WDR_TIMEOUT);
-       if (status < 0)
+       u8 *buf;
+       int status;
+
+       buf = kmalloc(1, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       status = usb_control_msg(usbdev, pipe, request, requesttype, value,
+                                    index, buf, 1, MOS_WDR_TIMEOUT);
+       if (status == 1)
+               *data = *buf;
+       else if (status < 0)
                dev_err(&usbdev->dev,
                        "mos7720: usb_control_msg() failed: %d", status);
+       kfree(buf);
+
        return status;
 }
 
@@ -1618,7 +1629,7 @@ static void change_port_settings(struct tty_struct *tty,
                mos7720_port->shadowMCR |= (UART_MCR_XONANY);
                /* To set hardware flow control to the specified *
                 * serial port, in SP1/2_CONTROL_REG             */
-               if (port->number)
+               if (port_number)
                        write_mos_reg(serial, dummy, SP_CONTROL_REG, 0x01);
                else
                        write_mos_reg(serial, dummy, SP_CONTROL_REG, 0x02);
@@ -1927,7 +1938,7 @@ static int mos7720_startup(struct usb_serial *serial)
 
        /* setting configuration feature to one */
        usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
-                       (__u8)0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5*HZ);
+                       (__u8)0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5000);
 
        /* start the interrupt urb */
        ret_val = usb_submit_urb(serial->port[0]->interrupt_in_urb, GFP_KERNEL);
@@ -1970,7 +1981,7 @@ static void mos7720_release(struct usb_serial *serial)
                /* wait for synchronous usb calls to return */
                if (mos_parport->msg_pending)
                        wait_for_completion_timeout(&mos_parport->syncmsg_compl,
-                                                   MOS_WDR_TIMEOUT);
+                                           msecs_to_jiffies(MOS_WDR_TIMEOUT));
 
                parport_remove_port(mos_parport->pp);
                usb_set_serial_data(serial, NULL);
index a0d5ea5..7e99808 100644 (file)
@@ -2142,13 +2142,21 @@ static int mos7840_ioctl(struct tty_struct *tty,
 static int mos7810_check(struct usb_serial *serial)
 {
        int i, pass_count = 0;
+       u8 *buf;
        __u16 data = 0, mcr_data = 0;
        __u16 test_pattern = 0x55AA;
+       int res;
+
+       buf = kmalloc(VENDOR_READ_LENGTH, GFP_KERNEL);
+       if (!buf)
+               return 0;       /* failed to identify 7810 */
 
        /* Store MCR setting */
-       usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+       res = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
                MCS_RDREQ, MCS_RD_RTYPE, 0x0300, MODEM_CONTROL_REGISTER,
-               &mcr_data, VENDOR_READ_LENGTH, MOS_WDR_TIMEOUT);
+               buf, VENDOR_READ_LENGTH, MOS_WDR_TIMEOUT);
+       if (res == VENDOR_READ_LENGTH)
+               mcr_data = *buf;
 
        for (i = 0; i < 16; i++) {
                /* Send the 1-bit test pattern out to MCS7810 test pin */
@@ -2158,9 +2166,12 @@ static int mos7810_check(struct usb_serial *serial)
                        MODEM_CONTROL_REGISTER, NULL, 0, MOS_WDR_TIMEOUT);
 
                /* Read the test pattern back */
-               usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
-                       MCS_RDREQ, MCS_RD_RTYPE, 0, GPIO_REGISTER, &data,
-                       VENDOR_READ_LENGTH, MOS_WDR_TIMEOUT);
+               res = usb_control_msg(serial->dev,
+                               usb_rcvctrlpipe(serial->dev, 0), MCS_RDREQ,
+                               MCS_RD_RTYPE, 0, GPIO_REGISTER, buf,
+                               VENDOR_READ_LENGTH, MOS_WDR_TIMEOUT);
+               if (res == VENDOR_READ_LENGTH)
+                       data = *buf;
 
                /* If this is a MCS7810 device, both test patterns must match */
                if (((test_pattern >> i) ^ (~data >> 1)) & 0x0001)
@@ -2174,6 +2185,8 @@ static int mos7810_check(struct usb_serial *serial)
                MCS_WR_RTYPE, 0x0300 | mcr_data, MODEM_CONTROL_REGISTER, NULL,
                0, MOS_WDR_TIMEOUT);
 
+       kfree(buf);
+
        if (pass_count == 16)
                return 1;
 
@@ -2183,11 +2196,17 @@ static int mos7810_check(struct usb_serial *serial)
 static int mos7840_calc_num_ports(struct usb_serial *serial)
 {
        __u16 data = 0x00;
+       u8 *buf;
        int mos7840_num_ports;
 
-       usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
-               MCS_RDREQ, MCS_RD_RTYPE, 0, GPIO_REGISTER, &data,
-               VENDOR_READ_LENGTH, MOS_WDR_TIMEOUT);
+       buf = kzalloc(VENDOR_READ_LENGTH, GFP_KERNEL);
+       if (buf) {
+               usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+                       MCS_RDREQ, MCS_RD_RTYPE, 0, GPIO_REGISTER, buf,
+                       VENDOR_READ_LENGTH, MOS_WDR_TIMEOUT);
+               data = *buf;
+               kfree(buf);
+       }
 
        if (serial->dev->descriptor.idProduct == MOSCHIP_DEVICE_ID_7810 ||
                serial->dev->descriptor.idProduct == MOSCHIP_DEVICE_ID_7820) {
index 7343728..bd4323d 100644 (file)
@@ -196,6 +196,7 @@ static void option_instat_callback(struct urb *urb);
 
 #define DELL_PRODUCT_5800_MINICARD_VZW         0x8195  /* Novatel E362 */
 #define DELL_PRODUCT_5800_V2_MINICARD_VZW      0x8196  /* Novatel E362 */
+#define DELL_PRODUCT_5804_MINICARD_ATT         0x819b  /* Novatel E371 */
 
 #define KYOCERA_VENDOR_ID                      0x0c88
 #define KYOCERA_PRODUCT_KPC650                 0x17da
@@ -249,13 +250,7 @@ static void option_instat_callback(struct urb *urb);
 #define ZTE_PRODUCT_MF622                      0x0001
 #define ZTE_PRODUCT_MF628                      0x0015
 #define ZTE_PRODUCT_MF626                      0x0031
-#define ZTE_PRODUCT_CDMA_TECH                  0xfffe
-#define ZTE_PRODUCT_AC8710                     0xfff1
-#define ZTE_PRODUCT_AC2726                     0xfff5
-#define ZTE_PRODUCT_AC8710T                    0xffff
 #define ZTE_PRODUCT_MC2718                     0xffe8
-#define ZTE_PRODUCT_AD3812                     0xffeb
-#define ZTE_PRODUCT_MC2716                     0xffed
 
 #define BENQ_VENDOR_ID                         0x04a5
 #define BENQ_PRODUCT_H10                       0x4068
@@ -341,8 +336,8 @@ static void option_instat_callback(struct urb *urb);
 #define CINTERION_PRODUCT_EU3_E                        0x0051
 #define CINTERION_PRODUCT_EU3_P                        0x0052
 #define CINTERION_PRODUCT_PH8                  0x0053
-#define CINTERION_PRODUCT_AH                 0x0055
-#define CINTERION_PRODUCT_PLS8                 0x0060
+#define CINTERION_PRODUCT_AHXX                 0x0055
+#define CINTERION_PRODUCT_PLXX                 0x0060
 
 /* Olivetti products */
 #define OLIVETTI_VENDOR_ID                     0x0b3c
@@ -494,18 +489,10 @@ static const struct option_blacklist_info zte_k3765_z_blacklist = {
        .reserved = BIT(4),
 };
 
-static const struct option_blacklist_info zte_ad3812_z_blacklist = {
-       .sendsetup = BIT(0) | BIT(1) | BIT(2),
-};
-
 static const struct option_blacklist_info zte_mc2718_z_blacklist = {
        .sendsetup = BIT(1) | BIT(2) | BIT(3) | BIT(4),
 };
 
-static const struct option_blacklist_info zte_mc2716_z_blacklist = {
-       .sendsetup = BIT(1) | BIT(2) | BIT(3),
-};
-
 static const struct option_blacklist_info huawei_cdc12_blacklist = {
        .reserved = BIT(1) | BIT(2),
 };
@@ -592,6 +579,8 @@ static const struct usb_device_id option_ids[] = {
                .driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3765, 0xff, 0xff, 0xff),
                .driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist },
+       { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x14ac, 0xff, 0xff, 0xff),    /* Huawei E1820 */
+               .driver_info = (kernel_ulong_t) &net_intf1_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4605, 0xff, 0xff, 0xff),
                .driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0xff, 0xff) },
@@ -771,6 +760,7 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_VZW) },         /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */
        { USB_DEVICE_AND_INTERFACE_INFO(DELL_VENDOR_ID, DELL_PRODUCT_5800_MINICARD_VZW, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(DELL_VENDOR_ID, DELL_PRODUCT_5800_V2_MINICARD_VZW, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(DELL_VENDOR_ID, DELL_PRODUCT_5804_MINICARD_ATT, 0xff, 0xff, 0xff) },
        { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_E100A) },   /* ADU-E100, ADU-310 */
        { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_500A) },
        { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_620UW) },
@@ -795,7 +785,6 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1012, 0xff) },
        { USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC650) },
        { USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC680) },
-       { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6000)}, /* ZTE AC8700 */
        { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */
        { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9000)}, /* SIMCom SIM5218 */
        { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6280) }, /* BP3-USB & BP3-EXT HSDPA */
@@ -966,6 +955,8 @@ static const struct usb_device_id option_ids[] = {
          .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0330, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0395, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0412, 0xff, 0xff, 0xff), /* Telewell TW-LTE 4G */
+         .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0414, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0417, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1008, 0xff, 0xff, 0xff),
@@ -1195,16 +1186,9 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0178, 0xff, 0xff, 0xff),
                .driver_info = (kernel_ulong_t)&net_intf3_blacklist },
 
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC2726, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710T, 0xff, 0xff, 0xff) },
+       /* NOTE: most ZTE CDMA devices should be driven by zte_ev, not option */
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MC2718, 0xff, 0xff, 0xff),
         .driver_info = (kernel_ulong_t)&zte_mc2718_z_blacklist },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AD3812, 0xff, 0xff, 0xff),
-        .driver_info = (kernel_ulong_t)&zte_ad3812_z_blacklist },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MC2716, 0xff, 0xff, 0xff),
-        .driver_info = (kernel_ulong_t)&zte_mc2716_z_blacklist },
        { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x01) },
        { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x05) },
        { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x86, 0x10) },
@@ -1264,8 +1248,9 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_E) },
        { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_P) },
        { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PH8) },
-       { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_AH6) },
-       { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PLS8) },
+       { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_AHXX) },
+       { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PLXX),
+               .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
        { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_HC28_MDM) }, 
        { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_HC28_MDMNET) },
        { USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC25_MDM) },
index 59b32b7..bd794b4 100644 (file)
@@ -118,6 +118,7 @@ static const struct usb_device_id id_table[] = {
        {USB_DEVICE(0x1199, 0x901b)},   /* Sierra Wireless MC7770 */
        {USB_DEVICE(0x12D1, 0x14F0)},   /* Sony Gobi 3000 QDL */
        {USB_DEVICE(0x12D1, 0x14F1)},   /* Sony Gobi 3000 Composite */
+       {USB_DEVICE(0x0AF0, 0x8120)},   /* Option GTM681W */
 
        /* non Gobi Qualcomm serial devices */
        {USB_DEVICE_INTERFACE_NUMBER(0x0f3d, 0x68a2, 0)},       /* Sierra Wireless MC7700 Device Management */
index cac47ae..c92c5ed 100644 (file)
@@ -101,6 +101,7 @@ static int ti_write(struct tty_struct *tty, struct usb_serial_port *port,
                const unsigned char *data, int count);
 static int ti_write_room(struct tty_struct *tty);
 static int ti_chars_in_buffer(struct tty_struct *tty);
+static bool ti_tx_empty(struct usb_serial_port *port);
 static void ti_throttle(struct tty_struct *tty);
 static void ti_unthrottle(struct tty_struct *tty);
 static int ti_ioctl(struct tty_struct *tty,
@@ -222,6 +223,7 @@ static struct usb_serial_driver ti_1port_device = {
        .write                  = ti_write,
        .write_room             = ti_write_room,
        .chars_in_buffer        = ti_chars_in_buffer,
+       .tx_empty               = ti_tx_empty,
        .throttle               = ti_throttle,
        .unthrottle             = ti_unthrottle,
        .ioctl                  = ti_ioctl,
@@ -253,6 +255,7 @@ static struct usb_serial_driver ti_2port_device = {
        .write                  = ti_write,
        .write_room             = ti_write_room,
        .chars_in_buffer        = ti_chars_in_buffer,
+       .tx_empty               = ti_tx_empty,
        .throttle               = ti_throttle,
        .unthrottle             = ti_unthrottle,
        .ioctl                  = ti_ioctl,
@@ -684,8 +687,6 @@ static int ti_chars_in_buffer(struct tty_struct *tty)
        struct ti_port *tport = usb_get_serial_port_data(port);
        int chars = 0;
        unsigned long flags;
-       int ret;
-       u8 lsr;
 
        if (tport == NULL)
                return 0;
@@ -694,16 +695,22 @@ static int ti_chars_in_buffer(struct tty_struct *tty)
        chars = kfifo_len(&tport->write_fifo);
        spin_unlock_irqrestore(&tport->tp_lock, flags);
 
-       if (!chars) {
-               ret = ti_get_lsr(tport, &lsr);
-               if (!ret && !(lsr & TI_LSR_TX_EMPTY))
-                       chars = 1;
-       }
-
        dev_dbg(&port->dev, "%s - returns %d\n", __func__, chars);
        return chars;
 }
 
+static bool ti_tx_empty(struct usb_serial_port *port)
+{
+       struct ti_port *tport = usb_get_serial_port_data(port);
+       int ret;
+       u8 lsr;
+
+       ret = ti_get_lsr(tport, &lsr);
+       if (!ret && !(lsr & TI_LSR_TX_EMPTY))
+               return false;
+
+       return true;
+}
 
 static void ti_throttle(struct tty_struct *tty)
 {
index cf75beb..5f6b1ff 100644 (file)
@@ -359,20 +359,29 @@ static int serial_chars_in_buffer(struct tty_struct *tty)
 {
        struct usb_serial_port *port = tty->driver_data;
        struct usb_serial *serial = port->serial;
-       int count = 0;
 
        dev_dbg(tty->dev, "%s\n", __func__);
 
-       mutex_lock(&serial->disc_mutex);
-       /* if the device was unplugged then any remaining characters
-          fell out of the connector ;) */
        if (serial->disconnected)
-               count = 0;
-       else
-               count = serial->type->chars_in_buffer(tty);
-       mutex_unlock(&serial->disc_mutex);
+               return 0;
 
-       return count;
+       return serial->type->chars_in_buffer(tty);
+}
+
+static void serial_wait_until_sent(struct tty_struct *tty, int timeout)
+{
+       struct usb_serial_port *port = tty->driver_data;
+       struct usb_serial *serial = port->serial;
+
+       dev_dbg(tty->dev, "%s\n", __func__);
+
+       if (!port->serial->type->wait_until_sent)
+               return;
+
+       mutex_lock(&serial->disc_mutex);
+       if (!serial->disconnected)
+               port->serial->type->wait_until_sent(tty, timeout);
+       mutex_unlock(&serial->disc_mutex);
 }
 
 static void serial_throttle(struct tty_struct *tty)
@@ -399,7 +408,7 @@ static int serial_ioctl(struct tty_struct *tty,
                                        unsigned int cmd, unsigned long arg)
 {
        struct usb_serial_port *port = tty->driver_data;
-       int retval = -ENODEV;
+       int retval = -ENOIOCTLCMD;
 
        dev_dbg(tty->dev, "%s - cmd 0x%.4x\n", __func__, cmd);
 
@@ -411,8 +420,6 @@ static int serial_ioctl(struct tty_struct *tty,
        default:
                if (port->serial->type->ioctl)
                        retval = port->serial->type->ioctl(tty, cmd, arg);
-               else
-                       retval = -ENOIOCTLCMD;
        }
 
        return retval;
@@ -1191,6 +1198,7 @@ static const struct tty_operations serial_ops = {
        .unthrottle =           serial_unthrottle,
        .break_ctl =            serial_break,
        .chars_in_buffer =      serial_chars_in_buffer,
+       .wait_until_sent =      serial_wait_until_sent,
        .tiocmget =             serial_tiocmget,
        .tiocmset =             serial_tiocmset,
        .get_icount =           serial_get_icount,
@@ -1316,6 +1324,8 @@ static void usb_serial_operations_init(struct usb_serial_driver *device)
        set_to_generic_if_null(device, close);
        set_to_generic_if_null(device, write_room);
        set_to_generic_if_null(device, chars_in_buffer);
+       if (device->tx_empty)
+               set_to_generic_if_null(device, wait_until_sent);
        set_to_generic_if_null(device, read_bulk_callback);
        set_to_generic_if_null(device, write_bulk_callback);
        set_to_generic_if_null(device, process_read_urb);
index 7573ec8..9910aa2 100644 (file)
@@ -560,10 +560,19 @@ static int treo_attach(struct usb_serial *serial)
        */
 #define COPY_PORT(dest, src)                                           \
        do { \
+               int i;                                                  \
+                                                                       \
+               for (i = 0; i < ARRAY_SIZE(src->read_urbs); ++i) {      \
+                       dest->read_urbs[i] = src->read_urbs[i];         \
+                       dest->read_urbs[i]->context = dest;             \
+                       dest->bulk_in_buffers[i] = src->bulk_in_buffers[i]; \
+               }                                                       \
                dest->read_urb = src->read_urb;                         \
                dest->bulk_in_endpointAddress = src->bulk_in_endpointAddress;\
                dest->bulk_in_buffer = src->bulk_in_buffer;             \
+               dest->bulk_in_size = src->bulk_in_size;                 \
                dest->interrupt_in_urb = src->interrupt_in_urb;         \
+               dest->interrupt_in_urb->context = dest;                 \
                dest->interrupt_in_endpointAddress = \
                                        src->interrupt_in_endpointAddress;\
                dest->interrupt_in_buffer = src->interrupt_in_buffer;   \
index b9fca35..347caad 100644 (file)
@@ -649,7 +649,7 @@ static void firm_setup_port(struct tty_struct *tty)
        struct whiteheat_port_settings port_settings;
        unsigned int cflag = tty->termios.c_cflag;
 
-       port_settings.port = port->number + 1;
+       port_settings.port = port->number - port->serial->minor + 1;
 
        /* get the byte size */
        switch (cflag & CSIZE) {
index 39ee737..fca4c75 100644 (file)
@@ -41,9 +41,6 @@ static int zte_ev_usb_serial_open(struct tty_struct *tty,
        int len;
        unsigned char *buf;
 
-       if (port->number != 0)
-               return -ENODEV;
-
        buf = kmalloc(MAX_SETUP_DATA_SIZE, GFP_KERNEL);
        if (!buf)
                return -ENOMEM;
@@ -53,7 +50,7 @@ static int zte_ev_usb_serial_open(struct tty_struct *tty,
        result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
                                 0x22, 0x21,
                                 0x0001, 0x0000, NULL, len,
-                                HZ * USB_CTRL_GET_TIMEOUT);
+                                USB_CTRL_GET_TIMEOUT);
        dev_dbg(dev, "result = %d\n", result);
 
        /* send  2st cmd and recieve data */
@@ -65,7 +62,7 @@ static int zte_ev_usb_serial_open(struct tty_struct *tty,
        result = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
                                 0x21, 0xa1,
                                 0x0000, 0x0000, buf, len,
-                                HZ * USB_CTRL_GET_TIMEOUT);
+                                USB_CTRL_GET_TIMEOUT);
        debug_data(dev, __func__, len, buf, result);
 
        /* send 3 cmd */
@@ -84,7 +81,7 @@ static int zte_ev_usb_serial_open(struct tty_struct *tty,
        result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
                                 0x20, 0x21,
                                 0x0000, 0x0000, buf, len,
-                                HZ * USB_CTRL_GET_TIMEOUT);
+                                USB_CTRL_GET_TIMEOUT);
        debug_data(dev, __func__, len, buf, result);
 
        /* send 4 cmd */
@@ -95,7 +92,7 @@ static int zte_ev_usb_serial_open(struct tty_struct *tty,
        result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
                                 0x22, 0x21,
                                 0x0003, 0x0000, NULL, len,
-                                HZ * USB_CTRL_GET_TIMEOUT);
+                                USB_CTRL_GET_TIMEOUT);
        dev_dbg(dev, "result = %d\n", result);
 
        /* send 5 cmd */
@@ -107,7 +104,7 @@ static int zte_ev_usb_serial_open(struct tty_struct *tty,
        result = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
                                 0x21, 0xa1,
                                 0x0000, 0x0000, buf, len,
-                                HZ * USB_CTRL_GET_TIMEOUT);
+                                USB_CTRL_GET_TIMEOUT);
        debug_data(dev, __func__, len, buf, result);
 
        /* send 6 cmd */
@@ -126,7 +123,7 @@ static int zte_ev_usb_serial_open(struct tty_struct *tty,
        result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
                                 0x20, 0x21,
                                 0x0000, 0x0000, buf, len,
-                                HZ * USB_CTRL_GET_TIMEOUT);
+                                USB_CTRL_GET_TIMEOUT);
        debug_data(dev, __func__, len, buf, result);
        kfree(buf);
 
@@ -166,9 +163,6 @@ static void zte_ev_usb_serial_close(struct usb_serial_port *port)
        int len;
        unsigned char *buf;
 
-       if (port->number != 0)
-               return;
-
        buf = kmalloc(MAX_SETUP_DATA_SIZE, GFP_KERNEL);
        if (!buf)
                return;
@@ -178,7 +172,7 @@ static void zte_ev_usb_serial_close(struct usb_serial_port *port)
        result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
                                 0x22, 0x21,
                                 0x0002, 0x0000, NULL, len,
-                                HZ * USB_CTRL_GET_TIMEOUT);
+                                USB_CTRL_GET_TIMEOUT);
        dev_dbg(dev, "result = %d\n", result);
 
        /* send 2st ctl cmd(CTL    21 22 03 00  00 00 00 00 ) */
@@ -186,7 +180,7 @@ static void zte_ev_usb_serial_close(struct usb_serial_port *port)
        result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
                                 0x22, 0x21,
                                 0x0003, 0x0000, NULL, len,
-                                HZ * USB_CTRL_GET_TIMEOUT);
+                                USB_CTRL_GET_TIMEOUT);
        dev_dbg(dev, "result = %d\n", result);
 
        /* send  3st cmd and recieve data */
@@ -198,7 +192,7 @@ static void zte_ev_usb_serial_close(struct usb_serial_port *port)
        result = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
                                 0x21, 0xa1,
                                 0x0000, 0x0000, buf, len,
-                                HZ * USB_CTRL_GET_TIMEOUT);
+                                USB_CTRL_GET_TIMEOUT);
        debug_data(dev, __func__, len, buf, result);
 
        /* send 4 cmd */
@@ -217,7 +211,7 @@ static void zte_ev_usb_serial_close(struct usb_serial_port *port)
        result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
                                 0x20, 0x21,
                                 0x0000, 0x0000, buf, len,
-                                HZ * USB_CTRL_GET_TIMEOUT);
+                                USB_CTRL_GET_TIMEOUT);
        debug_data(dev, __func__, len, buf, result);
 
        /* send 5 cmd */
@@ -228,7 +222,7 @@ static void zte_ev_usb_serial_close(struct usb_serial_port *port)
        result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
                                 0x22, 0x21,
                                 0x0003, 0x0000, NULL, len,
-                                HZ * USB_CTRL_GET_TIMEOUT);
+                                USB_CTRL_GET_TIMEOUT);
        dev_dbg(dev, "result = %d\n", result);
 
        /* send 6 cmd */
@@ -240,7 +234,7 @@ static void zte_ev_usb_serial_close(struct usb_serial_port *port)
        result = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
                                 0x21, 0xa1,
                                 0x0000, 0x0000, buf, len,
-                                HZ * USB_CTRL_GET_TIMEOUT);
+                                USB_CTRL_GET_TIMEOUT);
        debug_data(dev, __func__, len, buf, result);
 
        /* send 7 cmd */
@@ -259,7 +253,7 @@ static void zte_ev_usb_serial_close(struct usb_serial_port *port)
        result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
                                 0x20, 0x21,
                                 0x0000, 0x0000, buf, len,
-                                HZ * USB_CTRL_GET_TIMEOUT);
+                                USB_CTRL_GET_TIMEOUT);
        debug_data(dev, __func__, len, buf, result);
 
        /* send 8 cmd */
@@ -270,7 +264,7 @@ static void zte_ev_usb_serial_close(struct usb_serial_port *port)
        result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
                                 0x22, 0x21,
                                 0x0003, 0x0000, NULL, len,
-                                HZ * USB_CTRL_GET_TIMEOUT);
+                                USB_CTRL_GET_TIMEOUT);
        dev_dbg(dev, "result = %d\n", result);
 
        kfree(buf);
@@ -279,11 +273,29 @@ static void zte_ev_usb_serial_close(struct usb_serial_port *port)
 }
 
 static const struct usb_device_id id_table[] = {
-       { USB_DEVICE(0x19d2, 0xffff) }, /* AC8700 */
-       { USB_DEVICE(0x19d2, 0xfffe) },
-       { USB_DEVICE(0x19d2, 0xfffd) }, /* MG880 */
+       /* AC8710, AC8710T */
+       { USB_DEVICE_AND_INTERFACE_INFO(0x19d2, 0xffff, 0xff, 0xff, 0xff) },
+        /* AC8700 */
+       { USB_DEVICE_AND_INTERFACE_INFO(0x19d2, 0xfffe, 0xff, 0xff, 0xff) },
+       /* MG880 */
+       { USB_DEVICE(0x19d2, 0xfffd) },
+       { USB_DEVICE(0x19d2, 0xfffc) },
+       { USB_DEVICE(0x19d2, 0xfffb) },
+       /* AC2726, AC8710_V3 */
+       { USB_DEVICE_AND_INTERFACE_INFO(0x19d2, 0xfff1, 0xff, 0xff, 0xff) },
+       { USB_DEVICE(0x19d2, 0xfff6) },
+       { USB_DEVICE(0x19d2, 0xfff7) },
+       { USB_DEVICE(0x19d2, 0xfff8) },
+       { USB_DEVICE(0x19d2, 0xfff9) },
+       { USB_DEVICE(0x19d2, 0xffee) },
+       /* AC2716, MC2716 */
+       { USB_DEVICE_AND_INTERFACE_INFO(0x19d2, 0xffed, 0xff, 0xff, 0xff) },
+       /* AD3812 */
+       { USB_DEVICE_AND_INTERFACE_INFO(0x19d2, 0xffeb, 0xff, 0xff, 0xff) },
+       { USB_DEVICE(0x19d2, 0xffec) },
        { USB_DEVICE(0x05C6, 0x3197) },
        { USB_DEVICE(0x05C6, 0x6000) },
+       { USB_DEVICE(0x05C6, 0x9008) },
        { },
 };
 MODULE_DEVICE_TABLE(usb, id_table);
index 8623577..281be56 100644 (file)
@@ -105,8 +105,9 @@ struct rts51x_chip {
        int status_len;
 
        u32 flag;
-#ifdef CONFIG_REALTEK_AUTOPM
        struct us_data *us;
+
+#ifdef CONFIG_REALTEK_AUTOPM
        struct timer_list rts51x_suspend_timer;
        unsigned long timer_expires;
        int pwr_state;
@@ -988,6 +989,7 @@ static int init_realtek_cr(struct us_data *us)
        us->extra = chip;
        us->extra_destructor = realtek_cr_destructor;
        us->max_lun = chip->max_lun = rts51x_get_max_lun(us);
+       chip->us = us;
 
        usb_stor_dbg(us, "chip->max_lun = %d\n", chip->max_lun);
 
@@ -1010,10 +1012,8 @@ static int init_realtek_cr(struct us_data *us)
                        SET_AUTO_DELINK(chip);
        }
 #ifdef CONFIG_REALTEK_AUTOPM
-       if (ss_en) {
-               chip->us = us;
+       if (ss_en)
                realtek_cr_autosuspend_setup(us);
-       }
 #endif
 
        usb_stor_dbg(us, "chip->flag = 0x%x\n", chip->flag);
index acb7121..6d78736 100644 (file)
@@ -1360,7 +1360,7 @@ static const struct file_operations vfio_device_fops = {
  */
 static char *vfio_devnode(struct device *dev, umode_t *mode)
 {
-       if (MINOR(dev->devt) == 0)
+       if (mode && (MINOR(dev->devt) == 0))
                *mode = S_IRUGO | S_IWUGO;
 
        return kasprintf(GFP_KERNEL, "vfio/%s", dev_name(dev));
index 2b51e23..f80d3dd 100644 (file)
@@ -155,14 +155,11 @@ static void vhost_net_ubuf_put_and_wait(struct vhost_net_ubuf_ref *ubufs)
 
 static void vhost_net_clear_ubuf_info(struct vhost_net *n)
 {
-
-       bool zcopy;
        int i;
 
-       for (i = 0; i < n->dev.nvqs; ++i) {
-               zcopy = vhost_net_zcopy_mask & (0x1 << i);
-               if (zcopy)
-                       kfree(n->vqs[i].ubuf_info);
+       for (i = 0; i < VHOST_NET_VQ_MAX; ++i) {
+               kfree(n->vqs[i].ubuf_info);
+               n->vqs[i].ubuf_info = NULL;
        }
 }
 
@@ -171,7 +168,7 @@ int vhost_net_set_ubuf_info(struct vhost_net *n)
        bool zcopy;
        int i;
 
-       for (i = 0; i < n->dev.nvqs; ++i) {
+       for (i = 0; i < VHOST_NET_VQ_MAX; ++i) {
                zcopy = vhost_net_zcopy_mask & (0x1 << i);
                if (!zcopy)
                        continue;
@@ -183,12 +180,7 @@ int vhost_net_set_ubuf_info(struct vhost_net *n)
        return 0;
 
 err:
-       while (i--) {
-               zcopy = vhost_net_zcopy_mask & (0x1 << i);
-               if (!zcopy)
-                       continue;
-               kfree(n->vqs[i].ubuf_info);
-       }
+       vhost_net_clear_ubuf_info(n);
        return -ENOMEM;
 }
 
@@ -196,12 +188,12 @@ void vhost_net_vq_reset(struct vhost_net *n)
 {
        int i;
 
+       vhost_net_clear_ubuf_info(n);
+
        for (i = 0; i < VHOST_NET_VQ_MAX; i++) {
                n->vqs[i].done_idx = 0;
                n->vqs[i].upend_idx = 0;
                n->vqs[i].ubufs = NULL;
-               kfree(n->vqs[i].ubuf_info);
-               n->vqs[i].ubuf_info = NULL;
                n->vqs[i].vhost_hlen = 0;
                n->vqs[i].sock_hlen = 0;
        }
@@ -436,7 +428,8 @@ static void handle_tx(struct vhost_net *net)
                                kref_get(&ubufs->kref);
                        }
                        nvq->upend_idx = (nvq->upend_idx + 1) % UIO_MAXIOV;
-               }
+               } else
+                       msg.msg_control = NULL;
                /* TODO: Check specific error and bomb out unless ENOBUFS? */
                err = sock->ops->sendmsg(NULL, sock, &msg, len);
                if (unlikely(err < 0)) {
@@ -1053,6 +1046,10 @@ static long vhost_net_set_owner(struct vhost_net *n)
        int r;
 
        mutex_lock(&n->dev.mutex);
+       if (vhost_dev_has_owner(&n->dev)) {
+               r = -EBUSY;
+               goto out;
+       }
        r = vhost_net_set_ubuf_info(n);
        if (r)
                goto out;
index beee7f5..60aa5ad 100644 (file)
@@ -343,6 +343,12 @@ static int vhost_attach_cgroups(struct vhost_dev *dev)
        return attach.ret;
 }
 
+/* Caller should have device mutex */
+bool vhost_dev_has_owner(struct vhost_dev *dev)
+{
+       return dev->mm;
+}
+
 /* Caller should have device mutex */
 long vhost_dev_set_owner(struct vhost_dev *dev)
 {
@@ -350,7 +356,7 @@ long vhost_dev_set_owner(struct vhost_dev *dev)
        int err;
 
        /* Is there an owner already? */
-       if (dev->mm) {
+       if (vhost_dev_has_owner(dev)) {
                err = -EBUSY;
                goto err_mm;
        }
index a7ad635..64adcf9 100644 (file)
@@ -133,6 +133,7 @@ struct vhost_dev {
 
 long vhost_dev_init(struct vhost_dev *, struct vhost_virtqueue **vqs, int nvqs);
 long vhost_dev_set_owner(struct vhost_dev *dev);
+bool vhost_dev_has_owner(struct vhost_dev *dev);
 long vhost_dev_check_owner(struct vhost_dev *);
 struct vhost_memory *vhost_dev_reset_owner_prepare(void);
 void vhost_dev_reset_owner(struct vhost_dev *, struct vhost_memory *);
index bff0775..5174eba 100644 (file)
@@ -3,6 +3,7 @@
  *
  * Since these may be in userspace, we use (inline) accessors.
  */
+#include <linux/module.h>
 #include <linux/vringh.h>
 #include <linux/virtio_ring.h>
 #include <linux/kernel.h>
@@ -1005,3 +1006,5 @@ int vringh_need_notify_kern(struct vringh *vrh)
        return __vringh_need_notify(vrh, getu16_kern);
 }
 EXPORT_SYMBOL(vringh_need_notify_kern);
+
+MODULE_LICENSE("GPL");
index d71d60f..2e937bd 100644 (file)
@@ -2199,7 +2199,7 @@ config FB_XILINX
 
 config FB_GOLDFISH
        tristate "Goldfish Framebuffer"
-       depends on FB
+       depends on FB && HAS_DMA
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
@@ -2453,6 +2453,23 @@ config FB_HYPERV
        help
          This framebuffer driver supports Microsoft Hyper-V Synthetic Video.
 
+config FB_SIMPLE
+       bool "Simple framebuffer support"
+       depends on (FB = y) && OF
+       select FB_CFB_FILLRECT
+       select FB_CFB_COPYAREA
+       select FB_CFB_IMAGEBLIT
+       help
+         Say Y if you want support for a simple frame-buffer.
+
+         This driver assumes that the display hardware has been initialized
+         before the kernel boots, and the kernel will simply render to the
+         pre-allocated frame buffer surface.
+
+         Configuration re: surface address, size, and format must be provided
+         through device tree, or potentially plain old platform data in the
+         future.
+
 source "drivers/video/omap/Kconfig"
 source "drivers/video/omap2/Kconfig"
 source "drivers/video/exynos/Kconfig"
index 7234e4a..e8bae8d 100644 (file)
@@ -166,6 +166,7 @@ obj-$(CONFIG_FB_MX3)                  += mx3fb.o
 obj-$(CONFIG_FB_DA8XX)           += da8xx-fb.o
 obj-$(CONFIG_FB_MXS)             += mxsfb.o
 obj-$(CONFIG_FB_SSD1307)         += ssd1307fb.o
+obj-$(CONFIG_FB_SIMPLE)           += simplefb.o
 
 # the test framebuffer is last
 obj-$(CONFIG_FB_VIRTUAL)          += vfb.o
index 540909d..effdb37 100644 (file)
@@ -223,8 +223,14 @@ static void init_backlight(struct atmel_lcdfb_info *sinfo)
 
 static void exit_backlight(struct atmel_lcdfb_info *sinfo)
 {
-       if (sinfo->backlight)
-               backlight_device_unregister(sinfo->backlight);
+       if (!sinfo->backlight)
+               return;
+
+       if (sinfo->backlight->ops) {
+               sinfo->backlight->props.power = FB_BLANK_POWERDOWN;
+               sinfo->backlight->ops->update_status(sinfo->backlight);
+       }
+       backlight_device_unregister(sinfo->backlight);
 }
 
 #else
@@ -461,8 +467,11 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var,
        if (info->fix.smem_len) {
                unsigned int smem_len = (var->xres_virtual * var->yres_virtual
                                         * ((var->bits_per_pixel + 7) / 8));
-               if (smem_len > info->fix.smem_len)
+               if (smem_len > info->fix.smem_len) {
+                       dev_err(dev, "Frame buffer is too small (%u) for screen size (need at least %u)\n",
+                               info->fix.smem_len, smem_len);
                        return -EINVAL;
+               }
        }
 
        /* Saturate vertical and horizontal timings at maximum values */
index a862e91..48da25c 100644 (file)
@@ -18,6 +18,8 @@ font-objs-$(CONFIG_FONT_MINI_4x6)  += font_mini_4x6.o
 
 font-objs += $(font-objs-y)
 
+obj-$(CONFIG_FONTS) += font.o
+
 # Each configuration option enables a list of files.
 
 obj-$(CONFIG_DUMMY_CONSOLE)       += dummycon.o
index 60cc6fe..c9c2252 100644 (file)
@@ -53,6 +53,8 @@ static char *def_disp_name;
 module_param_named(def_disp, def_disp_name, charp, 0);
 MODULE_PARM_DESC(def_disp, "default display name");
 
+static bool dss_initialized;
+
 const char *omapdss_get_default_display_name(void)
 {
        return core.default_display_name;
@@ -66,6 +68,12 @@ enum omapdss_version omapdss_get_version(void)
 }
 EXPORT_SYMBOL(omapdss_get_version);
 
+bool omapdss_is_initialized(void)
+{
+       return dss_initialized;
+}
+EXPORT_SYMBOL(omapdss_is_initialized);
+
 struct platform_device *dss_get_core_pdev(void)
 {
        return core.pdev;
@@ -603,6 +611,8 @@ static int __init omap_dss_init(void)
                return r;
        }
 
+       dss_initialized = true;
+
        return 0;
 }
 
@@ -633,7 +643,15 @@ static int __init omap_dss_init(void)
 
 static int __init omap_dss_init2(void)
 {
-       return omap_dss_register_drivers();
+       int r;
+
+       r = omap_dss_register_drivers();
+       if (r)
+               return r;
+
+       dss_initialized = true;
+
+       return 0;
 }
 
 core_initcall(omap_dss_init);
index 17f4d55..a109934 100644 (file)
@@ -1065,10 +1065,6 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev)
        mutex_init(&hdmi.ip_data.lock);
 
        res = platform_get_resource(hdmi.pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               DSSERR("can't get IORESOURCE_MEM HDMI\n");
-               return -EINVAL;
-       }
 
        /* Base address taken from platform */
        hdmi.ip_data.base_wp = devm_ioremap_resource(&pdev->dev, res);
index c84bb8a..856917b 100644 (file)
@@ -2416,6 +2416,9 @@ static int omapfb_probe(struct platform_device *pdev)
 
        DBG("omapfb_probe\n");
 
+       if (omapdss_is_initialized() == false)
+               return -EPROBE_DEFER;
+
        if (pdev->num_resources != 0) {
                dev_err(&pdev->dev, "probed for an unknown device\n");
                r = -ENODEV;
index 5261229..f346b02 100644 (file)
@@ -353,11 +353,6 @@ static int __init vrfb_probe(struct platform_device *pdev)
        /* first resource is the register res, the rest are vrfb contexts */
 
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!mem) {
-               dev_err(&pdev->dev, "can't get vrfb base address\n");
-               return -EINVAL;
-       }
-
        vrfb_base = devm_ioremap_resource(&pdev->dev, mem);
        if (IS_ERR(vrfb_base))
                return PTR_ERR(vrfb_base);
index d9f08c6..dbfe2c1 100644 (file)
@@ -710,7 +710,7 @@ static int ps3fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
        r = vm_iomap_memory(vma, info->fix.smem_start, info->fix.smem_len);
 
        dev_dbg(info->device, "ps3fb: mmap framebuffer P(%lx)->V(%lx)\n",
-               info->fix.smem_start + vma->vm_pgoff << PAGE_SHIFT,
+               info->fix.smem_start + (vma->vm_pgoff << PAGE_SHIFT),
                vma->vm_start);
 
        return r;
diff --git a/drivers/video/simplefb.c b/drivers/video/simplefb.c
new file mode 100644 (file)
index 0000000..e2e9e3e
--- /dev/null
@@ -0,0 +1,234 @@
+/*
+ * Simplest possible simple frame-buffer driver, as a platform device
+ *
+ * Copyright (c) 2013, Stephen Warren
+ *
+ * Based on q40fb.c, which was:
+ * Copyright (C) 2001 Richard Zidlicky <rz@linux-m68k.org>
+ *
+ * Also based on offb.c, which was:
+ * Copyright (C) 1997 Geert Uytterhoeven
+ * Copyright (C) 1996 Paul Mackerras
+ *
+ * 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.
+ */
+
+#include <linux/errno.h>
+#include <linux/fb.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+static struct fb_fix_screeninfo simplefb_fix = {
+       .id             = "simple",
+       .type           = FB_TYPE_PACKED_PIXELS,
+       .visual         = FB_VISUAL_TRUECOLOR,
+       .accel          = FB_ACCEL_NONE,
+};
+
+static struct fb_var_screeninfo simplefb_var = {
+       .height         = -1,
+       .width          = -1,
+       .activate       = FB_ACTIVATE_NOW,
+       .vmode          = FB_VMODE_NONINTERLACED,
+};
+
+static int simplefb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+                             u_int transp, struct fb_info *info)
+{
+       u32 *pal = info->pseudo_palette;
+       u32 cr = red >> (16 - info->var.red.length);
+       u32 cg = green >> (16 - info->var.green.length);
+       u32 cb = blue >> (16 - info->var.blue.length);
+       u32 value;
+
+       if (regno >= 16)
+               return -EINVAL;
+
+       value = (cr << info->var.red.offset) |
+               (cg << info->var.green.offset) |
+               (cb << info->var.blue.offset);
+       if (info->var.transp.length > 0) {
+               u32 mask = (1 << info->var.transp.length) - 1;
+               mask <<= info->var.transp.offset;
+               value |= mask;
+       }
+       pal[regno] = value;
+
+       return 0;
+}
+
+static struct fb_ops simplefb_ops = {
+       .owner          = THIS_MODULE,
+       .fb_setcolreg   = simplefb_setcolreg,
+       .fb_fillrect    = cfb_fillrect,
+       .fb_copyarea    = cfb_copyarea,
+       .fb_imageblit   = cfb_imageblit,
+};
+
+struct simplefb_format {
+       const char *name;
+       u32 bits_per_pixel;
+       struct fb_bitfield red;
+       struct fb_bitfield green;
+       struct fb_bitfield blue;
+       struct fb_bitfield transp;
+};
+
+static struct simplefb_format simplefb_formats[] = {
+       { "r5g6b5", 16, {11, 5}, {5, 6}, {0, 5}, {0, 0} },
+};
+
+struct simplefb_params {
+       u32 width;
+       u32 height;
+       u32 stride;
+       struct simplefb_format *format;
+};
+
+static int simplefb_parse_dt(struct platform_device *pdev,
+                          struct simplefb_params *params)
+{
+       struct device_node *np = pdev->dev.of_node;
+       int ret;
+       const char *format;
+       int i;
+
+       ret = of_property_read_u32(np, "width", &params->width);
+       if (ret) {
+               dev_err(&pdev->dev, "Can't parse width property\n");
+               return ret;
+       }
+
+       ret = of_property_read_u32(np, "height", &params->height);
+       if (ret) {
+               dev_err(&pdev->dev, "Can't parse height property\n");
+               return ret;
+       }
+
+       ret = of_property_read_u32(np, "stride", &params->stride);
+       if (ret) {
+               dev_err(&pdev->dev, "Can't parse stride property\n");
+               return ret;
+       }
+
+       ret = of_property_read_string(np, "format", &format);
+       if (ret) {
+               dev_err(&pdev->dev, "Can't parse format property\n");
+               return ret;
+       }
+       params->format = NULL;
+       for (i = 0; i < ARRAY_SIZE(simplefb_formats); i++) {
+               if (strcmp(format, simplefb_formats[i].name))
+                       continue;
+               params->format = &simplefb_formats[i];
+               break;
+       }
+       if (!params->format) {
+               dev_err(&pdev->dev, "Invalid format value\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int simplefb_probe(struct platform_device *pdev)
+{
+       int ret;
+       struct simplefb_params params;
+       struct fb_info *info;
+       struct resource *mem;
+
+       if (fb_get_options("simplefb", NULL))
+               return -ENODEV;
+
+       ret = simplefb_parse_dt(pdev, &params);
+       if (ret)
+               return ret;
+
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!mem) {
+               dev_err(&pdev->dev, "No memory resource\n");
+               return -EINVAL;
+       }
+
+       info = framebuffer_alloc(sizeof(u32) * 16, &pdev->dev);
+       if (!info)
+               return -ENOMEM;
+       platform_set_drvdata(pdev, info);
+
+       info->fix = simplefb_fix;
+       info->fix.smem_start = mem->start;
+       info->fix.smem_len = resource_size(mem);
+       info->fix.line_length = params.stride;
+
+       info->var = simplefb_var;
+       info->var.xres = params.width;
+       info->var.yres = params.height;
+       info->var.xres_virtual = params.width;
+       info->var.yres_virtual = params.height;
+       info->var.bits_per_pixel = params.format->bits_per_pixel;
+       info->var.red = params.format->red;
+       info->var.green = params.format->green;
+       info->var.blue = params.format->blue;
+       info->var.transp = params.format->transp;
+
+       info->fbops = &simplefb_ops;
+       info->flags = FBINFO_DEFAULT;
+       info->screen_base = devm_ioremap(&pdev->dev, info->fix.smem_start,
+                                        info->fix.smem_len);
+       if (!info->screen_base) {
+               framebuffer_release(info);
+               return -ENODEV;
+       }
+       info->pseudo_palette = (void *)(info + 1);
+
+       ret = register_framebuffer(info);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Unable to register simplefb: %d\n", ret);
+               framebuffer_release(info);
+               return ret;
+       }
+
+       dev_info(&pdev->dev, "fb%d: simplefb registered!\n", info->node);
+
+       return 0;
+}
+
+static int simplefb_remove(struct platform_device *pdev)
+{
+       struct fb_info *info = platform_get_drvdata(pdev);
+
+       unregister_framebuffer(info);
+       framebuffer_release(info);
+
+       return 0;
+}
+
+static const struct of_device_id simplefb_of_match[] = {
+       { .compatible = "simple-framebuffer", },
+       { },
+};
+MODULE_DEVICE_TABLE(of, simplefb_of_match);
+
+static struct platform_driver simplefb_driver = {
+       .driver = {
+               .name = "simple-framebuffer",
+               .owner = THIS_MODULE,
+               .of_match_table = simplefb_of_match,
+       },
+       .probe = simplefb_probe,
+       .remove = simplefb_remove,
+};
+module_platform_driver(simplefb_driver);
+
+MODULE_AUTHOR("Stephen Warren <swarren@wwwdotorg.org>");
+MODULE_DESCRIPTION("Simple framebuffer driver");
+MODULE_LICENSE("GPL v2");
index db2390a..6e94d8d 100644 (file)
@@ -555,11 +555,6 @@ static int omap_hdq_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, hdq_data);
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_dbg(&pdev->dev, "unable to get resource\n");
-               return -ENXIO;
-       }
-
        hdq_data->hdq_base = devm_ioremap_resource(dev, res);
        if (IS_ERR(hdq_data->hdq_base))
                return PTR_ERR(hdq_data->hdq_base);
index d184c48..37cb09b 100644 (file)
@@ -248,11 +248,6 @@ static int ath79_wdt_probe(struct platform_device *pdev)
                return -EBUSY;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(&pdev->dev, "no memory resource found\n");
-               return -EINVAL;
-       }
-
        wdt_base = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(wdt_base))
                return PTR_ERR(wdt_base);
index 100d4fb..bead774 100644 (file)
@@ -217,11 +217,6 @@ static int davinci_wdt_probe(struct platform_device *pdev)
        dev_info(dev, "heartbeat %d sec\n", heartbeat);
 
        wdt_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (wdt_mem == NULL) {
-               dev_err(dev, "failed to get memory region resource\n");
-               return -ENOENT;
-       }
-
        wdt_base = devm_ioremap_resource(dev, wdt_mem);
        if (IS_ERR(wdt_base))
                return PTR_ERR(wdt_base);
index ff90882..62946c2 100644 (file)
@@ -257,11 +257,6 @@ static int __init imx2_wdt_probe(struct platform_device *pdev)
        struct resource *res;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(&pdev->dev, "can't get device resources\n");
-               return -ENODEV;
-       }
-
        imx2_wdt.base = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(imx2_wdt.base))
                return PTR_ERR(imx2_wdt.base);
index dd4d9cb..9e02d60 100644 (file)
@@ -19,11 +19,10 @@ config XEN_SELFBALLOONING
          by the current usage of anonymous memory ("committed AS") and
          controlled by various sysfs-settable parameters.  Configuring
          FRONTSWAP is highly recommended; if it is not configured, self-
-         ballooning is disabled by default but can be enabled with the
-         'selfballooning' kernel boot parameter.  If FRONTSWAP is configured,
+         ballooning is disabled by default. If FRONTSWAP is configured,
          frontswap-selfshrinking is enabled by default but can be disabled
-         with the 'noselfshrink' kernel boot parameter; and self-ballooning
-         is enabled by default but can be disabled with the 'noselfballooning'
+         with the 'tmem.selfshrink=0' kernel boot parameter; and self-ballooning
+         is enabled by default but can be disabled with the 'tmem.selfballooning=0'
          kernel boot parameter.  Note that systems without a sufficiently
          large swap device should not enable self-ballooning.
 
@@ -141,7 +140,7 @@ config XEN_GRANT_DEV_ALLOC
 
 config SWIOTLB_XEN
        def_bool y
-       depends on PCI
+       depends on PCI && X86
        select SWIOTLB
 
 config XEN_TMEM
index a56776d..930fb68 100644 (file)
@@ -407,7 +407,8 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp)
                nr_pages = ARRAY_SIZE(frame_list);
 
        for (i = 0; i < nr_pages; i++) {
-               if ((page = alloc_page(gfp)) == NULL) {
+               page = alloc_page(gfp);
+               if (page == NULL) {
                        nr_pages = i;
                        state = BP_EAGAIN;
                        break;
index d8cc812..6a6bbe4 100644 (file)
@@ -167,6 +167,8 @@ static void xen_irq_info_common_init(struct irq_info *info,
        info->cpu = cpu;
 
        evtchn_to_irq[evtchn] = irq;
+
+       irq_clear_status_flags(irq, IRQ_NOREQUEST|IRQ_NOAUTOEN);
 }
 
 static void xen_irq_info_evtchn_init(unsigned irq,
@@ -874,7 +876,6 @@ int bind_evtchn_to_irq(unsigned int evtchn)
                struct irq_info *info = info_for_irq(irq);
                WARN_ON(info == NULL || info->type != IRQT_EVTCHN);
        }
-       irq_clear_status_flags(irq, IRQ_NOREQUEST|IRQ_NOAUTOEN);
 
 out:
        mutex_unlock(&irq_mapping_update_lock);
index ca2b00e..2cfc24d 100644 (file)
@@ -504,7 +504,7 @@ static void privcmd_close(struct vm_area_struct *vma)
        struct page **pages = vma->vm_private_data;
        int numpgs = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
 
-       if (!xen_feature(XENFEAT_auto_translated_physmap || !numpgs || !pages))
+       if (!xen_feature(XENFEAT_auto_translated_physmap) || !numpgs || !pages)
                return;
 
        xen_unmap_domain_mfn_range(vma, numpgs, pages);
index e3600be..0f0493c 100644 (file)
 #include <linux/init.h>
 #include <linux/pagemap.h>
 #include <linux/cleancache.h>
-
-/* temporary ifdef until include/linux/frontswap.h is upstream */
-#ifdef CONFIG_FRONTSWAP
 #include <linux/frontswap.h>
-#endif
 
 #include <xen/xen.h>
 #include <xen/interface/xen.h>
 #include <asm/xen/hypervisor.h>
 #include <xen/tmem.h>
 
+#ifndef CONFIG_XEN_TMEM_MODULE
+bool __read_mostly tmem_enabled = false;
+
+static int __init enable_tmem(char *s)
+{
+       tmem_enabled = true;
+       return 1;
+}
+__setup("tmem", enable_tmem);
+#endif
+
+#ifdef CONFIG_CLEANCACHE
+static bool cleancache __read_mostly = true;
+module_param(cleancache, bool, S_IRUGO);
+static bool selfballooning __read_mostly = true;
+module_param(selfballooning, bool, S_IRUGO);
+#endif /* CONFIG_CLEANCACHE */
+
+#ifdef CONFIG_FRONTSWAP
+static bool frontswap __read_mostly = true;
+module_param(frontswap, bool, S_IRUGO);
+#else /* CONFIG_FRONTSWAP */
+#define frontswap (0)
+#endif /* CONFIG_FRONTSWAP */
+
+#ifdef CONFIG_XEN_SELFBALLOONING
+static bool selfshrinking __read_mostly = true;
+module_param(selfshrinking, bool, S_IRUGO);
+#endif /* CONFIG_XEN_SELFBALLOONING */
+
 #define TMEM_CONTROL               0
 #define TMEM_NEW_POOL              1
 #define TMEM_DESTROY_POOL          2
@@ -129,16 +155,6 @@ static int xen_tmem_flush_object(u32 pool_id, struct tmem_oid oid)
        return xen_tmem_op(TMEM_FLUSH_OBJECT, pool_id, oid, 0, 0, 0, 0, 0);
 }
 
-#ifndef CONFIG_XEN_TMEM_MODULE
-bool __read_mostly tmem_enabled = false;
-
-static int __init enable_tmem(char *s)
-{
-       tmem_enabled = true;
-       return 1;
-}
-__setup("tmem", enable_tmem);
-#endif
 
 #ifdef CONFIG_CLEANCACHE
 static int xen_tmem_destroy_pool(u32 pool_id)
@@ -230,20 +246,6 @@ static int tmem_cleancache_init_shared_fs(char *uuid, size_t pagesize)
        return xen_tmem_new_pool(shared_uuid, TMEM_POOL_SHARED, pagesize);
 }
 
-static bool disable_cleancache __read_mostly;
-static bool disable_selfballooning __read_mostly;
-#ifdef CONFIG_XEN_TMEM_MODULE
-module_param(disable_cleancache, bool, S_IRUGO);
-module_param(disable_selfballooning, bool, S_IRUGO);
-#else
-static int __init no_cleancache(char *s)
-{
-       disable_cleancache = true;
-       return 1;
-}
-__setup("nocleancache", no_cleancache);
-#endif
-
 static struct cleancache_ops tmem_cleancache_ops = {
        .put_page = tmem_cleancache_put_page,
        .get_page = tmem_cleancache_get_page,
@@ -361,20 +363,6 @@ static void tmem_frontswap_init(unsigned ignored)
                    xen_tmem_new_pool(private, TMEM_POOL_PERSIST, PAGE_SIZE);
 }
 
-static bool disable_frontswap __read_mostly;
-static bool disable_frontswap_selfshrinking __read_mostly;
-#ifdef CONFIG_XEN_TMEM_MODULE
-module_param(disable_frontswap, bool, S_IRUGO);
-module_param(disable_frontswap_selfshrinking, bool, S_IRUGO);
-#else
-static int __init no_frontswap(char *s)
-{
-       disable_frontswap = true;
-       return 1;
-}
-__setup("nofrontswap", no_frontswap);
-#endif
-
 static struct frontswap_ops tmem_frontswap_ops = {
        .store = tmem_frontswap_store,
        .load = tmem_frontswap_load,
@@ -382,8 +370,6 @@ static struct frontswap_ops tmem_frontswap_ops = {
        .invalidate_area = tmem_frontswap_flush_area,
        .init = tmem_frontswap_init
 };
-#else  /* CONFIG_FRONTSWAP */
-#define disable_frontswap_selfshrinking 1
 #endif
 
 static int xen_tmem_init(void)
@@ -391,12 +377,12 @@ static int xen_tmem_init(void)
        if (!xen_domain())
                return 0;
 #ifdef CONFIG_FRONTSWAP
-       if (tmem_enabled && !disable_frontswap) {
+       if (tmem_enabled && frontswap) {
                char *s = "";
-               struct frontswap_ops *old_ops =
-                       frontswap_register_ops(&tmem_frontswap_ops);
+               struct frontswap_ops *old_ops;
 
                tmem_frontswap_poolid = -1;
+               old_ops = frontswap_register_ops(&tmem_frontswap_ops);
                if (IS_ERR(old_ops) || old_ops) {
                        if (IS_ERR(old_ops))
                                return PTR_ERR(old_ops);
@@ -408,7 +394,7 @@ static int xen_tmem_init(void)
 #endif
 #ifdef CONFIG_CLEANCACHE
        BUG_ON(sizeof(struct cleancache_filekey) != sizeof(struct tmem_oid));
-       if (tmem_enabled && !disable_cleancache) {
+       if (tmem_enabled && cleancache) {
                char *s = "";
                struct cleancache_ops *old_ops =
                        cleancache_register_ops(&tmem_cleancache_ops);
@@ -419,8 +405,15 @@ static int xen_tmem_init(void)
        }
 #endif
 #ifdef CONFIG_XEN_SELFBALLOONING
-       xen_selfballoon_init(!disable_selfballooning,
-                               !disable_frontswap_selfshrinking);
+       /*
+        * There is no point of driving pages to the swap system if they
+        * aren't going anywhere in tmem universe.
+        */
+       if (!frontswap) {
+               selfshrinking = false;
+               selfballooning = false;
+       }
+       xen_selfballoon_init(selfballooning, selfshrinking);
 #endif
        return 0;
 }
index a2278ba..4e8ba38 100644 (file)
@@ -106,7 +106,7 @@ static void pcistub_device_release(struct kref *kref)
        else
                pci_restore_state(dev);
 
-       if (pci_find_capability(dev, PCI_CAP_ID_MSIX)) {
+       if (dev->msix_cap) {
                struct physdev_pci_device ppdev = {
                        .seg = pci_domain_nr(dev->bus),
                        .bus = dev->bus->number,
@@ -371,7 +371,7 @@ static int pcistub_init_device(struct pci_dev *dev)
        if (err)
                goto config_release;
 
-       if (pci_find_capability(dev, PCI_CAP_ID_MSIX)) {
+       if (dev->msix_cap) {
                struct physdev_pci_device ppdev = {
                        .seg = pci_domain_nr(dev->bus),
                        .bus = dev->bus->number,
index f2ef569..f70984a 100644 (file)
  * System configuration note: Selfballooning should not be enabled on
  * systems without a sufficiently large swap device configured; for best
  * results, it is recommended that total swap be increased by the size
- * of the guest memory.  Also, while technically not required to be
- * configured, it is highly recommended that frontswap also be configured
- * and enabled when selfballooning is running.  So, selfballooning
- * is disabled by default if frontswap is not configured and can only
- * be enabled with the "selfballooning" kernel boot option; similarly
- * selfballooning is enabled by default if frontswap is configured and
- * can be disabled with the "noselfballooning" kernel boot option.  Finally,
- * when frontswap is configured, frontswap-selfshrinking can be disabled
- * with the "noselfshrink" kernel boot option.
+ * of the guest memory. Note, that selfballooning should be disabled by default
+ * if frontswap is not configured.  Similarly selfballooning should be enabled
+ * by default if frontswap is configured and can be disabled with the
+ * "tmem.selfballooning=0" kernel boot option.  Finally, when frontswap is
+ * configured, frontswap-selfshrinking can be disabled  with the
+ * "tmem.selfshrink=0" kernel boot option.
  *
  * Selfballooning is disallowed in domain0 and force-disabled.
  *
@@ -120,9 +117,6 @@ static DECLARE_DELAYED_WORK(selfballoon_worker, selfballoon_process);
 /* Enable/disable with sysfs. */
 static bool frontswap_selfshrinking __read_mostly;
 
-/* Enable/disable with kernel boot option. */
-static bool use_frontswap_selfshrink = true;
-
 /*
  * The default values for the following parameters were deemed reasonable
  * by experimentation, may be workload-dependent, and can all be
@@ -176,35 +170,6 @@ static void frontswap_selfshrink(void)
        frontswap_shrink(tgt_frontswap_pages);
 }
 
-static int __init xen_nofrontswap_selfshrink_setup(char *s)
-{
-       use_frontswap_selfshrink = false;
-       return 1;
-}
-
-__setup("noselfshrink", xen_nofrontswap_selfshrink_setup);
-
-/* Disable with kernel boot option. */
-static bool use_selfballooning = true;
-
-static int __init xen_noselfballooning_setup(char *s)
-{
-       use_selfballooning = false;
-       return 1;
-}
-
-__setup("noselfballooning", xen_noselfballooning_setup);
-#else /* !CONFIG_FRONTSWAP */
-/* Enable with kernel boot option. */
-static bool use_selfballooning;
-
-static int __init xen_selfballooning_setup(char *s)
-{
-       use_selfballooning = true;
-       return 1;
-}
-
-__setup("selfballooning", xen_selfballooning_setup);
 #endif /* CONFIG_FRONTSWAP */
 
 #define MB2PAGES(mb)   ((mb) << (20 - PAGE_SHIFT))
index 61786be..ec097d6 100644 (file)
@@ -534,7 +534,7 @@ static int xenbus_map_ring_valloc_hvm(struct xenbus_device *dev,
 
        err = xenbus_map_ring(dev, gnt_ref, &node->handle, addr);
        if (err)
-               goto out_err;
+               goto out_err_free_ballooned_pages;
 
        spin_lock(&xenbus_valloc_lock);
        list_add(&node->next, &xenbus_valloc_pages);
@@ -543,8 +543,9 @@ static int xenbus_map_ring_valloc_hvm(struct xenbus_device *dev,
        *vaddr = addr;
        return 0;
 
- out_err:
+ out_err_free_ballooned_pages:
        free_xenballooned_pages(1, &node->page);
+ out_err:
        kfree(node);
        return err;
 }
index c8abd3b..e74f9c1 100644 (file)
@@ -45,6 +45,7 @@ int xb_wait_for_data_to_read(void);
 int xs_input_avail(void);
 extern struct xenstore_domain_interface *xen_store_interface;
 extern int xen_store_evtchn;
+extern enum xenstore_init xen_store_domain_type;
 
 extern const struct file_operations xen_xenbus_fops;
 
index d730008..a6f42fc 100644 (file)
@@ -70,22 +70,21 @@ static long xenbus_alloc(domid_t domid)
        return err;
 }
 
-static long xenbus_backend_ioctl(struct file *file, unsigned int cmd, unsigned long data)
+static long xenbus_backend_ioctl(struct file *file, unsigned int cmd,
+                                unsigned long data)
 {
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
        switch (cmd) {
-               case IOCTL_XENBUS_BACKEND_EVTCHN:
-                       if (xen_store_evtchn > 0)
-                               return xen_store_evtchn;
-                       return -ENODEV;
-
-               case IOCTL_XENBUS_BACKEND_SETUP:
-                       return xenbus_alloc(data);
-
-               default:
-                       return -ENOTTY;
+       case IOCTL_XENBUS_BACKEND_EVTCHN:
+               if (xen_store_evtchn > 0)
+                       return xen_store_evtchn;
+               return -ENODEV;
+       case IOCTL_XENBUS_BACKEND_SETUP:
+               return xenbus_alloc(data);
+       default:
+               return -ENOTTY;
        }
 }
 
index 3325884..56cfaaa 100644 (file)
@@ -69,6 +69,9 @@ EXPORT_SYMBOL_GPL(xen_store_evtchn);
 struct xenstore_domain_interface *xen_store_interface;
 EXPORT_SYMBOL_GPL(xen_store_interface);
 
+enum xenstore_init xen_store_domain_type;
+EXPORT_SYMBOL_GPL(xen_store_domain_type);
+
 static unsigned long xen_store_mfn;
 
 static BLOCKING_NOTIFIER_HEAD(xenstore_chain);
@@ -719,17 +722,11 @@ static int __init xenstored_local_init(void)
        return err;
 }
 
-enum xenstore_init {
-       UNKNOWN,
-       PV,
-       HVM,
-       LOCAL,
-};
 static int __init xenbus_init(void)
 {
        int err = 0;
-       enum xenstore_init usage = UNKNOWN;
        uint64_t v = 0;
+       xen_store_domain_type = XS_UNKNOWN;
 
        if (!xen_domain())
                return -ENODEV;
@@ -737,29 +734,29 @@ static int __init xenbus_init(void)
        xenbus_ring_ops_init();
 
        if (xen_pv_domain())
-               usage = PV;
+               xen_store_domain_type = XS_PV;
        if (xen_hvm_domain())
-               usage = HVM;
+               xen_store_domain_type = XS_HVM;
        if (xen_hvm_domain() && xen_initial_domain())
-               usage = LOCAL;
+               xen_store_domain_type = XS_LOCAL;
        if (xen_pv_domain() && !xen_start_info->store_evtchn)
-               usage = LOCAL;
+               xen_store_domain_type = XS_LOCAL;
        if (xen_pv_domain() && xen_start_info->store_evtchn)
                xenstored_ready = 1;
 
-       switch (usage) {
-       case LOCAL:
+       switch (xen_store_domain_type) {
+       case XS_LOCAL:
                err = xenstored_local_init();
                if (err)
                        goto out_error;
                xen_store_interface = mfn_to_virt(xen_store_mfn);
                break;
-       case PV:
+       case XS_PV:
                xen_store_evtchn = xen_start_info->store_evtchn;
                xen_store_mfn = xen_start_info->store_mfn;
                xen_store_interface = mfn_to_virt(xen_store_mfn);
                break;
-       case HVM:
+       case XS_HVM:
                err = hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &v);
                if (err)
                        goto out_error;
index bb4f92e..146f857 100644 (file)
@@ -47,6 +47,13 @@ struct xen_bus_type {
        struct bus_type bus;
 };
 
+enum xenstore_init {
+       XS_UNKNOWN,
+       XS_PV,
+       XS_HVM,
+       XS_LOCAL,
+};
+
 extern struct device_attribute xenbus_dev_attrs[];
 
 extern int xenbus_match(struct device *_dev, struct device_driver *_drv);
index 3159a37..a7e2507 100644 (file)
@@ -29,6 +29,8 @@
 #include "xenbus_probe.h"
 
 
+static struct workqueue_struct *xenbus_frontend_wq;
+
 /* device/<type>/<id> => <type>-<id> */
 static int frontend_bus_id(char bus_id[XEN_BUS_ID_SIZE], const char *nodename)
 {
@@ -89,9 +91,40 @@ static void backend_changed(struct xenbus_watch *watch,
        xenbus_otherend_changed(watch, vec, len, 1);
 }
 
+static void xenbus_frontend_delayed_resume(struct work_struct *w)
+{
+       struct xenbus_device *xdev = container_of(w, struct xenbus_device, work);
+
+       xenbus_dev_resume(&xdev->dev);
+}
+
+static int xenbus_frontend_dev_resume(struct device *dev)
+{
+       /*
+        * If xenstored is running in this domain, we cannot access the backend
+        * state at the moment, so we need to defer xenbus_dev_resume
+        */
+       if (xen_store_domain_type == XS_LOCAL) {
+               struct xenbus_device *xdev = to_xenbus_device(dev);
+
+               if (!xenbus_frontend_wq) {
+                       pr_err("%s: no workqueue to process delayed resume\n",
+                              xdev->nodename);
+                       return -EFAULT;
+               }
+
+               INIT_WORK(&xdev->work, xenbus_frontend_delayed_resume);
+               queue_work(xenbus_frontend_wq, &xdev->work);
+
+               return 0;
+       }
+
+       return xenbus_dev_resume(dev);
+}
+
 static const struct dev_pm_ops xenbus_pm_ops = {
        .suspend        = xenbus_dev_suspend,
-       .resume         = xenbus_dev_resume,
+       .resume         = xenbus_frontend_dev_resume,
        .freeze         = xenbus_dev_suspend,
        .thaw           = xenbus_dev_cancel,
        .restore        = xenbus_dev_resume,
@@ -440,6 +473,8 @@ static int __init xenbus_probe_frontend_init(void)
 
        register_xenstore_notifier(&xenstore_notifier);
 
+       xenbus_frontend_wq = create_workqueue("xenbus_frontend");
+
        return 0;
 }
 subsys_initcall(xenbus_probe_frontend_init);
index c5b1a8c..2bbcacf 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -141,9 +141,6 @@ static void aio_free_ring(struct kioctx *ctx)
        for (i = 0; i < ctx->nr_pages; i++)
                put_page(ctx->ring_pages[i]);
 
-       if (ctx->mmap_size)
-               vm_munmap(ctx->mmap_base, ctx->mmap_size);
-
        if (ctx->ring_pages && ctx->ring_pages != ctx->internal_pages)
                kfree(ctx->ring_pages);
 }
@@ -307,7 +304,9 @@ static void free_ioctx(struct kioctx *ctx)
        kunmap_atomic(ring);
 
        while (atomic_read(&ctx->reqs_active) > 0) {
-               wait_event(ctx->wait, head != ctx->tail);
+               wait_event(ctx->wait,
+                               head != ctx->tail ||
+                               atomic_read(&ctx->reqs_active) <= 0);
 
                avail = (head <= ctx->tail ? ctx->tail : ctx->nr_events) - head;
 
@@ -320,11 +319,6 @@ static void free_ioctx(struct kioctx *ctx)
 
        aio_free_ring(ctx);
 
-       spin_lock(&aio_nr_lock);
-       BUG_ON(aio_nr - ctx->max_reqs > aio_nr);
-       aio_nr -= ctx->max_reqs;
-       spin_unlock(&aio_nr_lock);
-
        pr_debug("freeing %p\n", ctx);
 
        /*
@@ -433,17 +427,24 @@ static void kill_ioctx(struct kioctx *ctx)
 {
        if (!atomic_xchg(&ctx->dead, 1)) {
                hlist_del_rcu(&ctx->list);
-               /* Between hlist_del_rcu() and dropping the initial ref */
-               synchronize_rcu();
 
                /*
-                * We can't punt to workqueue here because put_ioctx() ->
-                * free_ioctx() will unmap the ringbuffer, and that has to be
-                * done in the original process's context. kill_ioctx_rcu/work()
-                * exist for exit_aio(), as in that path free_ioctx() won't do
-                * the unmap.
+                * It'd be more correct to do this in free_ioctx(), after all
+                * the outstanding kiocbs have finished - but by then io_destroy
+                * has already returned, so io_setup() could potentially return
+                * -EAGAIN with no ioctxs actually in use (as far as userspace
+                *  could tell).
                 */
-               kill_ioctx_work(&ctx->rcu_work);
+               spin_lock(&aio_nr_lock);
+               BUG_ON(aio_nr - ctx->max_reqs > aio_nr);
+               aio_nr -= ctx->max_reqs;
+               spin_unlock(&aio_nr_lock);
+
+               if (ctx->mmap_size)
+                       vm_munmap(ctx->mmap_base, ctx->mmap_size);
+
+               /* Between hlist_del_rcu() and dropping the initial ref */
+               call_rcu(&ctx->rcu_head, kill_ioctx_rcu);
        }
 }
 
@@ -493,10 +494,7 @@ void exit_aio(struct mm_struct *mm)
                 */
                ctx->mmap_size = 0;
 
-               if (!atomic_xchg(&ctx->dead, 1)) {
-                       hlist_del_rcu(&ctx->list);
-                       call_rcu(&ctx->rcu_head, kill_ioctx_rcu);
-               }
+               kill_ioctx(ctx);
        }
 }
 
@@ -1299,8 +1297,7 @@ SYSCALL_DEFINE3(io_cancel, aio_context_t, ctx_id, struct iocb __user *, iocb,
  *     < min_nr if the timeout specified by timeout has elapsed
  *     before sufficient events are available, where timeout == NULL
  *     specifies an infinite timeout. Note that the timeout pointed to by
- *     timeout is relative and will be updated if not NULL and the
- *     operation blocks. Will fail with -ENOSYS if not implemented.
+ *     timeout is relative.  Will fail with -ENOSYS if not implemented.
  */
 SYSCALL_DEFINE5(io_getevents, aio_context_t, ctx_id,
                long, min_nr,
index 8615ee8..f95dddc 100644 (file)
@@ -265,8 +265,8 @@ befs_readdir(struct file *filp, void *dirent, filldir_t filldir)
                result = filldir(dirent, keybuf, keysize, filp->f_pos,
                                 (ino_t) value, d_type);
        }
-
-       filp->f_pos++;
+       if (!result)
+               filp->f_pos++;
 
        befs_debug(sb, "<--- befs_readdir() filp->f_pos %Ld", filp->f_pos);
 
index b4fb415..290e347 100644 (file)
@@ -918,7 +918,8 @@ again:
                                                           ref->parent, bsz, 0);
                                if (!eb || !extent_buffer_uptodate(eb)) {
                                        free_extent_buffer(eb);
-                                       return -EIO;
+                                       ret = -EIO;
+                                       goto out;
                                }
                                ret = find_extent_in_eb(eb, bytenr,
                                                        *extent_item_pos, &eie);
index 18af6f4..1431a69 100644 (file)
@@ -1700,7 +1700,7 @@ static int btrfsic_read_block(struct btrfsic_state *state,
                unsigned int j;
                DECLARE_COMPLETION_ONSTACK(complete);
 
-               bio = bio_alloc(GFP_NOFS, num_pages - i);
+               bio = btrfs_io_bio_alloc(GFP_NOFS, num_pages - i);
                if (!bio) {
                        printk(KERN_INFO
                               "btrfsic: bio_alloc() for %u pages failed!\n",
index de6de8e..02fae7f 100644 (file)
@@ -951,10 +951,12 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans,
                        BUG_ON(ret); /* -ENOMEM */
                }
                if (new_flags != 0) {
+                       int level = btrfs_header_level(buf);
+
                        ret = btrfs_set_disk_extent_flags(trans, root,
                                                          buf->start,
                                                          buf->len,
-                                                         new_flags, 0);
+                                                         new_flags, level, 0);
                        if (ret)
                                return ret;
                }
index 63c328a..d6dd49b 100644 (file)
@@ -88,12 +88,12 @@ struct btrfs_ordered_sum;
 /* holds checksums of all the data extents */
 #define BTRFS_CSUM_TREE_OBJECTID 7ULL
 
-/* for storing balance parameters in the root tree */
-#define BTRFS_BALANCE_OBJECTID -4ULL
-
 /* holds quota configuration and tracking */
 #define BTRFS_QUOTA_TREE_OBJECTID 8ULL
 
+/* for storing balance parameters in the root tree */
+#define BTRFS_BALANCE_OBJECTID -4ULL
+
 /* orhpan objectid for tracking unlinked/truncated files */
 #define BTRFS_ORPHAN_OBJECTID -5ULL
 
@@ -3075,7 +3075,7 @@ int btrfs_dec_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
 int btrfs_set_disk_extent_flags(struct btrfs_trans_handle *trans,
                                struct btrfs_root *root,
                                u64 bytenr, u64 num_bytes, u64 flags,
-                               int is_data);
+                               int level, int is_data);
 int btrfs_free_extent(struct btrfs_trans_handle *trans,
                      struct btrfs_root *root,
                      u64 bytenr, u64 num_bytes, u64 parent, u64 root_objectid,
index f75fcaf..70b962c 100644 (file)
@@ -60,6 +60,7 @@ struct btrfs_delayed_ref_node {
 struct btrfs_delayed_extent_op {
        struct btrfs_disk_key key;
        u64 flags_to_set;
+       int level;
        unsigned int update_key:1;
        unsigned int update_flags:1;
        unsigned int is_data:1;
index 7ba7b39..65241f3 100644 (file)
@@ -313,6 +313,11 @@ int btrfs_dev_replace_start(struct btrfs_root *root,
        struct btrfs_device *tgt_device = NULL;
        struct btrfs_device *src_device = NULL;
 
+       if (btrfs_fs_incompat(fs_info, RAID56)) {
+               pr_warn("btrfs: dev_replace cannot yet handle RAID5/RAID6\n");
+               return -EINVAL;
+       }
+
        switch (args->start.cont_reading_from_srcdev_mode) {
        case BTRFS_IOCTL_DEV_REPLACE_CONT_READING_FROM_SRCDEV_MODE_ALWAYS:
        case BTRFS_IOCTL_DEV_REPLACE_CONT_READING_FROM_SRCDEV_MODE_AVOID:
index 4e9ebe1..e7b3cb5 100644 (file)
@@ -152,7 +152,7 @@ static struct btrfs_lockdep_keyset {
        { .id = BTRFS_DEV_TREE_OBJECTID,        .name_stem = "dev"      },
        { .id = BTRFS_FS_TREE_OBJECTID,         .name_stem = "fs"       },
        { .id = BTRFS_CSUM_TREE_OBJECTID,       .name_stem = "csum"     },
-       { .id = BTRFS_ORPHAN_OBJECTID,          .name_stem = "orphan"   },
+       { .id = BTRFS_QUOTA_TREE_OBJECTID,      .name_stem = "quota"    },
        { .id = BTRFS_TREE_LOG_OBJECTID,        .name_stem = "log"      },
        { .id = BTRFS_TREE_RELOC_OBJECTID,      .name_stem = "treloc"   },
        { .id = BTRFS_DATA_RELOC_TREE_OBJECTID, .name_stem = "dreloc"   },
@@ -1513,7 +1513,6 @@ struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_root *tree_root,
        }
 
        root->commit_root = btrfs_root_node(root);
-       BUG_ON(!root->node); /* -ENOMEM */
 out:
        if (location->objectid != BTRFS_TREE_LOG_OBJECTID) {
                root->ref_cows = 1;
@@ -1988,30 +1987,33 @@ static void free_root_pointers(struct btrfs_fs_info *info, int chunk_root)
 {
        free_extent_buffer(info->tree_root->node);
        free_extent_buffer(info->tree_root->commit_root);
-       free_extent_buffer(info->dev_root->node);
-       free_extent_buffer(info->dev_root->commit_root);
-       free_extent_buffer(info->extent_root->node);
-       free_extent_buffer(info->extent_root->commit_root);
-       free_extent_buffer(info->csum_root->node);
-       free_extent_buffer(info->csum_root->commit_root);
-       if (info->quota_root) {
-               free_extent_buffer(info->quota_root->node);
-               free_extent_buffer(info->quota_root->commit_root);
-       }
-
        info->tree_root->node = NULL;
        info->tree_root->commit_root = NULL;
-       info->dev_root->node = NULL;
-       info->dev_root->commit_root = NULL;
-       info->extent_root->node = NULL;
-       info->extent_root->commit_root = NULL;
-       info->csum_root->node = NULL;
-       info->csum_root->commit_root = NULL;
+
+       if (info->dev_root) {
+               free_extent_buffer(info->dev_root->node);
+               free_extent_buffer(info->dev_root->commit_root);
+               info->dev_root->node = NULL;
+               info->dev_root->commit_root = NULL;
+       }
+       if (info->extent_root) {
+               free_extent_buffer(info->extent_root->node);
+               free_extent_buffer(info->extent_root->commit_root);
+               info->extent_root->node = NULL;
+               info->extent_root->commit_root = NULL;
+       }
+       if (info->csum_root) {
+               free_extent_buffer(info->csum_root->node);
+               free_extent_buffer(info->csum_root->commit_root);
+               info->csum_root->node = NULL;
+               info->csum_root->commit_root = NULL;
+       }
        if (info->quota_root) {
+               free_extent_buffer(info->quota_root->node);
+               free_extent_buffer(info->quota_root->commit_root);
                info->quota_root->node = NULL;
                info->quota_root->commit_root = NULL;
        }
-
        if (chunk_root) {
                free_extent_buffer(info->chunk_root->node);
                free_extent_buffer(info->chunk_root->commit_root);
@@ -3128,7 +3130,7 @@ static int write_dev_flush(struct btrfs_device *device, int wait)
         * caller
         */
        device->flush_bio = NULL;
-       bio = bio_alloc(GFP_NOFS, 0);
+       bio = btrfs_io_bio_alloc(GFP_NOFS, 0);
        if (!bio)
                return -ENOMEM;
 
@@ -3659,8 +3661,11 @@ static void btrfs_destroy_ordered_operations(struct btrfs_transaction *t,
                                         ordered_operations);
 
                list_del_init(&btrfs_inode->ordered_operations);
+               spin_unlock(&root->fs_info->ordered_extent_lock);
 
                btrfs_invalidate_inodes(btrfs_inode->root);
+
+               spin_lock(&root->fs_info->ordered_extent_lock);
        }
 
        spin_unlock(&root->fs_info->ordered_extent_lock);
@@ -3782,8 +3787,11 @@ static void btrfs_destroy_delalloc_inodes(struct btrfs_root *root)
                list_del_init(&btrfs_inode->delalloc_inodes);
                clear_bit(BTRFS_INODE_IN_DELALLOC_LIST,
                          &btrfs_inode->runtime_flags);
+               spin_unlock(&root->fs_info->delalloc_lock);
 
                btrfs_invalidate_inodes(btrfs_inode->root);
+
+               spin_lock(&root->fs_info->delalloc_lock);
        }
 
        spin_unlock(&root->fs_info->delalloc_lock);
@@ -3808,7 +3816,7 @@ static int btrfs_destroy_marked_extents(struct btrfs_root *root,
                while (start <= end) {
                        eb = btrfs_find_tree_block(root, start,
                                                   root->leafsize);
-                       start += eb->len;
+                       start += root->leafsize;
                        if (!eb)
                                continue;
                        wait_on_extent_buffer_writeback(eb);
index 2305b5c..df472ab 100644 (file)
@@ -2070,8 +2070,7 @@ static int run_delayed_extent_op(struct btrfs_trans_handle *trans,
        u32 item_size;
        int ret;
        int err = 0;
-       int metadata = (node->type == BTRFS_TREE_BLOCK_REF_KEY ||
-                       node->type == BTRFS_SHARED_BLOCK_REF_KEY);
+       int metadata = !extent_op->is_data;
 
        if (trans->aborted)
                return 0;
@@ -2086,11 +2085,8 @@ static int run_delayed_extent_op(struct btrfs_trans_handle *trans,
        key.objectid = node->bytenr;
 
        if (metadata) {
-               struct btrfs_delayed_tree_ref *tree_ref;
-
-               tree_ref = btrfs_delayed_node_to_tree_ref(node);
                key.type = BTRFS_METADATA_ITEM_KEY;
-               key.offset = tree_ref->level;
+               key.offset = extent_op->level;
        } else {
                key.type = BTRFS_EXTENT_ITEM_KEY;
                key.offset = node->num_bytes;
@@ -2719,7 +2715,7 @@ out:
 int btrfs_set_disk_extent_flags(struct btrfs_trans_handle *trans,
                                struct btrfs_root *root,
                                u64 bytenr, u64 num_bytes, u64 flags,
-                               int is_data)
+                               int level, int is_data)
 {
        struct btrfs_delayed_extent_op *extent_op;
        int ret;
@@ -2732,6 +2728,7 @@ int btrfs_set_disk_extent_flags(struct btrfs_trans_handle *trans,
        extent_op->update_flags = 1;
        extent_op->update_key = 0;
        extent_op->is_data = is_data ? 1 : 0;
+       extent_op->level = level;
 
        ret = btrfs_add_delayed_extent_op(root->fs_info, trans, bytenr,
                                          num_bytes, extent_op);
@@ -3109,6 +3106,11 @@ again:
        WARN_ON(ret);
 
        if (i_size_read(inode) > 0) {
+               ret = btrfs_check_trunc_cache_free_space(root,
+                                       &root->fs_info->global_block_rsv);
+               if (ret)
+                       goto out_put;
+
                ret = btrfs_truncate_free_space_cache(root, trans, path,
                                                      inode);
                if (ret)
@@ -4562,6 +4564,8 @@ static void init_global_block_rsv(struct btrfs_fs_info *fs_info)
        fs_info->csum_root->block_rsv = &fs_info->global_block_rsv;
        fs_info->dev_root->block_rsv = &fs_info->global_block_rsv;
        fs_info->tree_root->block_rsv = &fs_info->global_block_rsv;
+       if (fs_info->quota_root)
+               fs_info->quota_root->block_rsv = &fs_info->global_block_rsv;
        fs_info->chunk_root->block_rsv = &fs_info->chunk_block_rsv;
 
        update_global_block_rsv(fs_info);
@@ -6651,51 +6655,51 @@ use_block_rsv(struct btrfs_trans_handle *trans,
        struct btrfs_block_rsv *block_rsv;
        struct btrfs_block_rsv *global_rsv = &root->fs_info->global_block_rsv;
        int ret;
+       bool global_updated = false;
 
        block_rsv = get_block_rsv(trans, root);
 
-       if (block_rsv->size == 0) {
-               ret = reserve_metadata_bytes(root, block_rsv, blocksize,
-                                            BTRFS_RESERVE_NO_FLUSH);
-               /*
-                * If we couldn't reserve metadata bytes try and use some from
-                * the global reserve.
-                */
-               if (ret && block_rsv != global_rsv) {
-                       ret = block_rsv_use_bytes(global_rsv, blocksize);
-                       if (!ret)
-                               return global_rsv;
-                       return ERR_PTR(ret);
-               } else if (ret) {
-                       return ERR_PTR(ret);
-               }
+       if (unlikely(block_rsv->size == 0))
+               goto try_reserve;
+again:
+       ret = block_rsv_use_bytes(block_rsv, blocksize);
+       if (!ret)
                return block_rsv;
+
+       if (block_rsv->failfast)
+               return ERR_PTR(ret);
+
+       if (block_rsv->type == BTRFS_BLOCK_RSV_GLOBAL && !global_updated) {
+               global_updated = true;
+               update_global_block_rsv(root->fs_info);
+               goto again;
        }
 
-       ret = block_rsv_use_bytes(block_rsv, blocksize);
+       if (btrfs_test_opt(root, ENOSPC_DEBUG)) {
+               static DEFINE_RATELIMIT_STATE(_rs,
+                               DEFAULT_RATELIMIT_INTERVAL * 10,
+                               /*DEFAULT_RATELIMIT_BURST*/ 1);
+               if (__ratelimit(&_rs))
+                       WARN(1, KERN_DEBUG
+                               "btrfs: block rsv returned %d\n", ret);
+       }
+try_reserve:
+       ret = reserve_metadata_bytes(root, block_rsv, blocksize,
+                                    BTRFS_RESERVE_NO_FLUSH);
        if (!ret)
                return block_rsv;
-       if (ret && !block_rsv->failfast) {
-               if (btrfs_test_opt(root, ENOSPC_DEBUG)) {
-                       static DEFINE_RATELIMIT_STATE(_rs,
-                                       DEFAULT_RATELIMIT_INTERVAL * 10,
-                                       /*DEFAULT_RATELIMIT_BURST*/ 1);
-                       if (__ratelimit(&_rs))
-                               WARN(1, KERN_DEBUG
-                                       "btrfs: block rsv returned %d\n", ret);
-               }
-               ret = reserve_metadata_bytes(root, block_rsv, blocksize,
-                                            BTRFS_RESERVE_NO_FLUSH);
-               if (!ret) {
-                       return block_rsv;
-               } else if (ret && block_rsv != global_rsv) {
-                       ret = block_rsv_use_bytes(global_rsv, blocksize);
-                       if (!ret)
-                               return global_rsv;
-               }
+       /*
+        * If we couldn't reserve metadata bytes try and use some from
+        * the global reserve if its space type is the same as the global
+        * reservation.
+        */
+       if (block_rsv->type != BTRFS_BLOCK_RSV_GLOBAL &&
+           block_rsv->space_info == global_rsv->space_info) {
+               ret = block_rsv_use_bytes(global_rsv, blocksize);
+               if (!ret)
+                       return global_rsv;
        }
-
-       return ERR_PTR(-ENOSPC);
+       return ERR_PTR(ret);
 }
 
 static void unuse_block_rsv(struct btrfs_fs_info *fs_info,
@@ -6763,6 +6767,7 @@ struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
                        extent_op->update_key = 1;
                extent_op->update_flags = 1;
                extent_op->is_data = 0;
+               extent_op->level = level;
 
                ret = btrfs_add_delayed_tree_ref(root->fs_info, trans,
                                        ins.objectid,
@@ -6934,7 +6939,8 @@ static noinline int walk_down_proc(struct btrfs_trans_handle *trans,
                ret = btrfs_dec_ref(trans, root, eb, 0, wc->for_reloc);
                BUG_ON(ret); /* -ENOMEM */
                ret = btrfs_set_disk_extent_flags(trans, root, eb->start,
-                                                 eb->len, flag, 0);
+                                                 eb->len, flag,
+                                                 btrfs_header_level(eb), 0);
                BUG_ON(ret); /* -ENOMEM */
                wc->flags[level] |= flag;
        }
index 32d67a8..e7e7afb 100644 (file)
@@ -23,6 +23,7 @@
 
 static struct kmem_cache *extent_state_cache;
 static struct kmem_cache *extent_buffer_cache;
+static struct bio_set *btrfs_bioset;
 
 #ifdef CONFIG_BTRFS_DEBUG
 static LIST_HEAD(buffers);
@@ -125,10 +126,20 @@ int __init extent_io_init(void)
                        SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, NULL);
        if (!extent_buffer_cache)
                goto free_state_cache;
+
+       btrfs_bioset = bioset_create(BIO_POOL_SIZE,
+                                    offsetof(struct btrfs_io_bio, bio));
+       if (!btrfs_bioset)
+               goto free_buffer_cache;
        return 0;
 
+free_buffer_cache:
+       kmem_cache_destroy(extent_buffer_cache);
+       extent_buffer_cache = NULL;
+
 free_state_cache:
        kmem_cache_destroy(extent_state_cache);
+       extent_state_cache = NULL;
        return -ENOMEM;
 }
 
@@ -145,6 +156,8 @@ void extent_io_exit(void)
                kmem_cache_destroy(extent_state_cache);
        if (extent_buffer_cache)
                kmem_cache_destroy(extent_buffer_cache);
+       if (btrfs_bioset)
+               bioset_free(btrfs_bioset);
 }
 
 void extent_io_tree_init(struct extent_io_tree *tree,
@@ -1947,28 +1960,6 @@ static void check_page_uptodate(struct extent_io_tree *tree, struct page *page)
                SetPageUptodate(page);
 }
 
-/*
- * helper function to unlock a page if all the extents in the tree
- * for that page are unlocked
- */
-static void check_page_locked(struct extent_io_tree *tree, struct page *page)
-{
-       u64 start = page_offset(page);
-       u64 end = start + PAGE_CACHE_SIZE - 1;
-       if (!test_range_bit(tree, start, end, EXTENT_LOCKED, 0, NULL))
-               unlock_page(page);
-}
-
-/*
- * helper function to end page writeback if all the extents
- * in the tree for that page are done with writeback
- */
-static void check_page_writeback(struct extent_io_tree *tree,
-                                struct page *page)
-{
-       end_page_writeback(page);
-}
-
 /*
  * When IO fails, either with EIO or csum verification fails, we
  * try other mirrors that might have a good copy of the data.  This
@@ -2046,7 +2037,7 @@ int repair_io_failure(struct btrfs_fs_info *fs_info, u64 start,
        if (btrfs_is_parity_mirror(map_tree, logical, length, mirror_num))
                return 0;
 
-       bio = bio_alloc(GFP_NOFS, 1);
+       bio = btrfs_io_bio_alloc(GFP_NOFS, 1);
        if (!bio)
                return -EIO;
        bio->bi_private = &compl;
@@ -2336,7 +2327,7 @@ static int bio_readpage_error(struct bio *failed_bio, struct page *page,
                return -EIO;
        }
 
-       bio = bio_alloc(GFP_NOFS, 1);
+       bio = btrfs_io_bio_alloc(GFP_NOFS, 1);
        if (!bio) {
                free_io_failure(inode, failrec, 0);
                return -EIO;
@@ -2398,19 +2389,24 @@ static void end_bio_extent_writepage(struct bio *bio, int err)
        struct extent_io_tree *tree;
        u64 start;
        u64 end;
-       int whole_page;
 
        do {
                struct page *page = bvec->bv_page;
                tree = &BTRFS_I(page->mapping->host)->io_tree;
 
-               start = page_offset(page) + bvec->bv_offset;
-               end = start + bvec->bv_len - 1;
+               /* We always issue full-page reads, but if some block
+                * in a page fails to read, blk_update_request() will
+                * advance bv_offset and adjust bv_len to compensate.
+                * Print a warning for nonzero offsets, and an error
+                * if they don't add up to a full page.  */
+               if (bvec->bv_offset || bvec->bv_len != PAGE_CACHE_SIZE)
+                       printk("%s page write in btrfs with offset %u and length %u\n",
+                              bvec->bv_offset + bvec->bv_len != PAGE_CACHE_SIZE
+                              ? KERN_ERR "partial" : KERN_INFO "incomplete",
+                              bvec->bv_offset, bvec->bv_len);
 
-               if (bvec->bv_offset == 0 && bvec->bv_len == PAGE_CACHE_SIZE)
-                       whole_page = 1;
-               else
-                       whole_page = 0;
+               start = page_offset(page);
+               end = start + bvec->bv_offset + bvec->bv_len - 1;
 
                if (--bvec >= bio->bi_io_vec)
                        prefetchw(&bvec->bv_page->flags);
@@ -2418,10 +2414,7 @@ static void end_bio_extent_writepage(struct bio *bio, int err)
                if (end_extent_writepage(page, err, start, end))
                        continue;
 
-               if (whole_page)
-                       end_page_writeback(page);
-               else
-                       check_page_writeback(tree, page);
+               end_page_writeback(page);
        } while (bvec >= bio->bi_io_vec);
 
        bio_put(bio);
@@ -2446,7 +2439,6 @@ static void end_bio_extent_readpage(struct bio *bio, int err)
        struct extent_io_tree *tree;
        u64 start;
        u64 end;
-       int whole_page;
        int mirror;
        int ret;
 
@@ -2457,19 +2449,26 @@ static void end_bio_extent_readpage(struct bio *bio, int err)
                struct page *page = bvec->bv_page;
                struct extent_state *cached = NULL;
                struct extent_state *state;
+               struct btrfs_io_bio *io_bio = btrfs_io_bio(bio);
 
                pr_debug("end_bio_extent_readpage: bi_sector=%llu, err=%d, "
-                        "mirror=%ld\n", (u64)bio->bi_sector, err,
-                        (long int)bio->bi_bdev);
+                        "mirror=%lu\n", (u64)bio->bi_sector, err,
+                        io_bio->mirror_num);
                tree = &BTRFS_I(page->mapping->host)->io_tree;
 
-               start = page_offset(page) + bvec->bv_offset;
-               end = start + bvec->bv_len - 1;
+               /* We always issue full-page reads, but if some block
+                * in a page fails to read, blk_update_request() will
+                * advance bv_offset and adjust bv_len to compensate.
+                * Print a warning for nonzero offsets, and an error
+                * if they don't add up to a full page.  */
+               if (bvec->bv_offset || bvec->bv_len != PAGE_CACHE_SIZE)
+                       printk("%s page read in btrfs with offset %u and length %u\n",
+                              bvec->bv_offset + bvec->bv_len != PAGE_CACHE_SIZE
+                              ? KERN_ERR "partial" : KERN_INFO "incomplete",
+                              bvec->bv_offset, bvec->bv_len);
 
-               if (bvec->bv_offset == 0 && bvec->bv_len == PAGE_CACHE_SIZE)
-                       whole_page = 1;
-               else
-                       whole_page = 0;
+               start = page_offset(page);
+               end = start + bvec->bv_offset + bvec->bv_len - 1;
 
                if (++bvec <= bvec_end)
                        prefetchw(&bvec->bv_page->flags);
@@ -2485,7 +2484,7 @@ static void end_bio_extent_readpage(struct bio *bio, int err)
                }
                spin_unlock(&tree->lock);
 
-               mirror = (int)(unsigned long)bio->bi_bdev;
+               mirror = io_bio->mirror_num;
                if (uptodate && tree->ops && tree->ops->readpage_end_io_hook) {
                        ret = tree->ops->readpage_end_io_hook(page, start, end,
                                                              state, mirror);
@@ -2528,39 +2527,35 @@ static void end_bio_extent_readpage(struct bio *bio, int err)
                }
                unlock_extent_cached(tree, start, end, &cached, GFP_ATOMIC);
 
-               if (whole_page) {
-                       if (uptodate) {
-                               SetPageUptodate(page);
-                       } else {
-                               ClearPageUptodate(page);
-                               SetPageError(page);
-                       }
-                       unlock_page(page);
+               if (uptodate) {
+                       SetPageUptodate(page);
                } else {
-                       if (uptodate) {
-                               check_page_uptodate(tree, page);
-                       } else {
-                               ClearPageUptodate(page);
-                               SetPageError(page);
-                       }
-                       check_page_locked(tree, page);
+                       ClearPageUptodate(page);
+                       SetPageError(page);
                }
+               unlock_page(page);
        } while (bvec <= bvec_end);
 
        bio_put(bio);
 }
 
+/*
+ * this allocates from the btrfs_bioset.  We're returning a bio right now
+ * but you can call btrfs_io_bio for the appropriate container_of magic
+ */
 struct bio *
 btrfs_bio_alloc(struct block_device *bdev, u64 first_sector, int nr_vecs,
                gfp_t gfp_flags)
 {
        struct bio *bio;
 
-       bio = bio_alloc(gfp_flags, nr_vecs);
+       bio = bio_alloc_bioset(gfp_flags, nr_vecs, btrfs_bioset);
 
        if (bio == NULL && (current->flags & PF_MEMALLOC)) {
-               while (!bio && (nr_vecs /= 2))
-                       bio = bio_alloc(gfp_flags, nr_vecs);
+               while (!bio && (nr_vecs /= 2)) {
+                       bio = bio_alloc_bioset(gfp_flags,
+                                              nr_vecs, btrfs_bioset);
+               }
        }
 
        if (bio) {
@@ -2571,6 +2566,19 @@ btrfs_bio_alloc(struct block_device *bdev, u64 first_sector, int nr_vecs,
        return bio;
 }
 
+struct bio *btrfs_bio_clone(struct bio *bio, gfp_t gfp_mask)
+{
+       return bio_clone_bioset(bio, gfp_mask, btrfs_bioset);
+}
+
+
+/* this also allocates from the btrfs_bioset */
+struct bio *btrfs_io_bio_alloc(gfp_t gfp_mask, unsigned int nr_iovecs)
+{
+       return bio_alloc_bioset(gfp_mask, nr_iovecs, btrfs_bioset);
+}
+
+
 static int __must_check submit_one_bio(int rw, struct bio *bio,
                                       int mirror_num, unsigned long bio_flags)
 {
@@ -3988,7 +3996,7 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
                last_for_get_extent = isize;
        }
 
-       lock_extent_bits(&BTRFS_I(inode)->io_tree, start, start + len, 0,
+       lock_extent_bits(&BTRFS_I(inode)->io_tree, start, start + len - 1, 0,
                         &cached_state);
 
        em = get_extent_skip_holes(inode, start, last_for_get_extent,
@@ -4075,7 +4083,7 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
 out_free:
        free_extent_map(em);
 out:
-       unlock_extent_cached(&BTRFS_I(inode)->io_tree, start, start + len,
+       unlock_extent_cached(&BTRFS_I(inode)->io_tree, start, start + len - 1,
                             &cached_state, GFP_NOFS);
        return ret;
 }
index a2c03a1..41fb81e 100644 (file)
@@ -336,6 +336,8 @@ int extent_clear_unlock_delalloc(struct inode *inode,
 struct bio *
 btrfs_bio_alloc(struct block_device *bdev, u64 first_sector, int nr_vecs,
                gfp_t gfp_flags);
+struct bio *btrfs_io_bio_alloc(gfp_t gfp_mask, unsigned int nr_iovecs);
+struct bio *btrfs_bio_clone(struct bio *bio, gfp_t gfp_mask);
 
 struct btrfs_fs_info;
 
index ecca6c7..e530096 100644 (file)
@@ -197,30 +197,32 @@ int create_free_space_inode(struct btrfs_root *root,
                                         block_group->key.objectid);
 }
 
-int btrfs_truncate_free_space_cache(struct btrfs_root *root,
-                                   struct btrfs_trans_handle *trans,
-                                   struct btrfs_path *path,
-                                   struct inode *inode)
+int btrfs_check_trunc_cache_free_space(struct btrfs_root *root,
+                                      struct btrfs_block_rsv *rsv)
 {
-       struct btrfs_block_rsv *rsv;
        u64 needed_bytes;
-       loff_t oldsize;
-       int ret = 0;
-
-       rsv = trans->block_rsv;
-       trans->block_rsv = &root->fs_info->global_block_rsv;
+       int ret;
 
        /* 1 for slack space, 1 for updating the inode */
        needed_bytes = btrfs_calc_trunc_metadata_size(root, 1) +
                btrfs_calc_trans_metadata_size(root, 1);
 
-       spin_lock(&trans->block_rsv->lock);
-       if (trans->block_rsv->reserved < needed_bytes) {
-               spin_unlock(&trans->block_rsv->lock);
-               trans->block_rsv = rsv;
-               return -ENOSPC;
-       }
-       spin_unlock(&trans->block_rsv->lock);
+       spin_lock(&rsv->lock);
+       if (rsv->reserved < needed_bytes)
+               ret = -ENOSPC;
+       else
+               ret = 0;
+       spin_unlock(&rsv->lock);
+       return 0;
+}
+
+int btrfs_truncate_free_space_cache(struct btrfs_root *root,
+                                   struct btrfs_trans_handle *trans,
+                                   struct btrfs_path *path,
+                                   struct inode *inode)
+{
+       loff_t oldsize;
+       int ret = 0;
 
        oldsize = i_size_read(inode);
        btrfs_i_size_write(inode, 0);
@@ -232,9 +234,7 @@ int btrfs_truncate_free_space_cache(struct btrfs_root *root,
         */
        ret = btrfs_truncate_inode_items(trans, root, inode,
                                         0, BTRFS_EXTENT_DATA_KEY);
-
        if (ret) {
-               trans->block_rsv = rsv;
                btrfs_abort_transaction(trans, root, ret);
                return ret;
        }
@@ -242,7 +242,6 @@ int btrfs_truncate_free_space_cache(struct btrfs_root *root,
        ret = btrfs_update_inode(trans, root, inode);
        if (ret)
                btrfs_abort_transaction(trans, root, ret);
-       trans->block_rsv = rsv;
 
        return ret;
 }
@@ -920,10 +919,8 @@ static int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode,
 
        /* Make sure we can fit our crcs into the first page */
        if (io_ctl.check_crcs &&
-           (io_ctl.num_pages * sizeof(u32)) >= PAGE_CACHE_SIZE) {
-               WARN_ON(1);
+           (io_ctl.num_pages * sizeof(u32)) >= PAGE_CACHE_SIZE)
                goto out_nospc;
-       }
 
        io_ctl_set_generation(&io_ctl, trans->transid);
 
index 4dc17d8..8b7f19f 100644 (file)
@@ -54,6 +54,8 @@ int create_free_space_inode(struct btrfs_root *root,
                            struct btrfs_block_group_cache *block_group,
                            struct btrfs_path *path);
 
+int btrfs_check_trunc_cache_free_space(struct btrfs_root *root,
+                                      struct btrfs_block_rsv *rsv);
 int btrfs_truncate_free_space_cache(struct btrfs_root *root,
                                    struct btrfs_trans_handle *trans,
                                    struct btrfs_path *path,
index d26f67a..2c66ddb 100644 (file)
@@ -429,11 +429,12 @@ int btrfs_save_ino_cache(struct btrfs_root *root,
        num_bytes = trans->bytes_reserved;
        /*
         * 1 item for inode item insertion if need
-        * 3 items for inode item update (in the worst case)
+        * 4 items for inode item update (in the worst case)
+        * 1 items for slack space if we need do truncation
         * 1 item for free space object
         * 3 items for pre-allocation
         */
-       trans->bytes_reserved = btrfs_calc_trans_metadata_size(root, 8);
+       trans->bytes_reserved = btrfs_calc_trans_metadata_size(root, 10);
        ret = btrfs_block_rsv_add(root, trans->block_rsv,
                                  trans->bytes_reserved,
                                  BTRFS_RESERVE_NO_FLUSH);
@@ -468,7 +469,8 @@ again:
        if (i_size_read(inode) > 0) {
                ret = btrfs_truncate_free_space_cache(root, trans, path, inode);
                if (ret) {
-                       btrfs_abort_transaction(trans, root, ret);
+                       if (ret != -ENOSPC)
+                               btrfs_abort_transaction(trans, root, ret);
                        goto out_put;
                }
        }
index 9b31b3b..af978f7 100644 (file)
@@ -715,8 +715,10 @@ retry:
                                        async_extent->ram_size - 1, 0);
 
                em = alloc_extent_map();
-               if (!em)
+               if (!em) {
+                       ret = -ENOMEM;
                        goto out_free_reserve;
+               }
                em->start = async_extent->start;
                em->len = async_extent->ram_size;
                em->orig_start = em->start;
@@ -923,8 +925,10 @@ static noinline int __cow_file_range(struct btrfs_trans_handle *trans,
                }
 
                em = alloc_extent_map();
-               if (!em)
+               if (!em) {
+                       ret = -ENOMEM;
                        goto out_reserve;
+               }
                em->start = start;
                em->orig_start = em->start;
                ram_size = ins.offset;
@@ -4724,6 +4728,7 @@ void btrfs_evict_inode(struct inode *inode)
        btrfs_end_transaction(trans, root);
        btrfs_btree_balance_dirty(root);
 no_delete:
+       btrfs_remove_delayed_node(inode);
        clear_inode(inode);
        return;
 }
@@ -4839,14 +4844,13 @@ static void inode_tree_add(struct inode *inode)
        struct rb_node **p;
        struct rb_node *parent;
        u64 ino = btrfs_ino(inode);
-again:
-       p = &root->inode_tree.rb_node;
-       parent = NULL;
 
        if (inode_unhashed(inode))
                return;
-
+again:
+       parent = NULL;
        spin_lock(&root->inode_lock);
+       p = &root->inode_tree.rb_node;
        while (*p) {
                parent = *p;
                entry = rb_entry(parent, struct btrfs_inode, rb_node);
@@ -6928,7 +6932,11 @@ struct btrfs_dio_private {
        /* IO errors */
        int errors;
 
+       /* orig_bio is our btrfs_io_bio */
        struct bio *orig_bio;
+
+       /* dio_bio came from fs/direct-io.c */
+       struct bio *dio_bio;
 };
 
 static void btrfs_endio_direct_read(struct bio *bio, int err)
@@ -6938,6 +6946,7 @@ static void btrfs_endio_direct_read(struct bio *bio, int err)
        struct bio_vec *bvec = bio->bi_io_vec;
        struct inode *inode = dip->inode;
        struct btrfs_root *root = BTRFS_I(inode)->root;
+       struct bio *dio_bio;
        u64 start;
 
        start = dip->logical_offset;
@@ -6977,14 +6986,15 @@ failed:
 
        unlock_extent(&BTRFS_I(inode)->io_tree, dip->logical_offset,
                      dip->logical_offset + dip->bytes - 1);
-       bio->bi_private = dip->private;
+       dio_bio = dip->dio_bio;
 
        kfree(dip);
 
        /* If we had a csum failure make sure to clear the uptodate flag */
        if (err)
-               clear_bit(BIO_UPTODATE, &bio->bi_flags);
-       dio_end_io(bio, err);
+               clear_bit(BIO_UPTODATE, &dio_bio->bi_flags);
+       dio_end_io(dio_bio, err);
+       bio_put(bio);
 }
 
 static void btrfs_endio_direct_write(struct bio *bio, int err)
@@ -6995,6 +7005,7 @@ static void btrfs_endio_direct_write(struct bio *bio, int err)
        struct btrfs_ordered_extent *ordered = NULL;
        u64 ordered_offset = dip->logical_offset;
        u64 ordered_bytes = dip->bytes;
+       struct bio *dio_bio;
        int ret;
 
        if (err)
@@ -7022,14 +7033,15 @@ out_test:
                goto again;
        }
 out_done:
-       bio->bi_private = dip->private;
+       dio_bio = dip->dio_bio;
 
        kfree(dip);
 
        /* If we had an error make sure to clear the uptodate flag */
        if (err)
-               clear_bit(BIO_UPTODATE, &bio->bi_flags);
-       dio_end_io(bio, err);
+               clear_bit(BIO_UPTODATE, &dio_bio->bi_flags);
+       dio_end_io(dio_bio, err);
+       bio_put(bio);
 }
 
 static int __btrfs_submit_bio_start_direct_io(struct inode *inode, int rw,
@@ -7065,10 +7077,10 @@ static void btrfs_end_dio_bio(struct bio *bio, int err)
        if (!atomic_dec_and_test(&dip->pending_bios))
                goto out;
 
-       if (dip->errors)
+       if (dip->errors) {
                bio_io_error(dip->orig_bio);
-       else {
-               set_bit(BIO_UPTODATE, &dip->orig_bio->bi_flags);
+       else {
+               set_bit(BIO_UPTODATE, &dip->dio_bio->bi_flags);
                bio_endio(dip->orig_bio, 0);
        }
 out:
@@ -7243,25 +7255,34 @@ out_err:
        return 0;
 }
 
-static void btrfs_submit_direct(int rw, struct bio *bio, struct inode *inode,
-                               loff_t file_offset)
+static void btrfs_submit_direct(int rw, struct bio *dio_bio,
+                               struct inode *inode, loff_t file_offset)
 {
        struct btrfs_root *root = BTRFS_I(inode)->root;
        struct btrfs_dio_private *dip;
-       struct bio_vec *bvec = bio->bi_io_vec;
+       struct bio_vec *bvec = dio_bio->bi_io_vec;
+       struct bio *io_bio;
        int skip_sum;
        int write = rw & REQ_WRITE;
        int ret = 0;
 
        skip_sum = BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM;
 
+       io_bio = btrfs_bio_clone(dio_bio, GFP_NOFS);
+
+       if (!io_bio) {
+               ret = -ENOMEM;
+               goto free_ordered;
+       }
+
        dip = kmalloc(sizeof(*dip), GFP_NOFS);
        if (!dip) {
                ret = -ENOMEM;
-               goto free_ordered;
+               goto free_io_bio;
        }
 
-       dip->private = bio->bi_private;
+       dip->private = dio_bio->bi_private;
+       io_bio->bi_private = dio_bio->bi_private;
        dip->inode = inode;
        dip->logical_offset = file_offset;
 
@@ -7269,22 +7290,27 @@ static void btrfs_submit_direct(int rw, struct bio *bio, struct inode *inode,
        do {
                dip->bytes += bvec->bv_len;
                bvec++;
-       } while (bvec <= (bio->bi_io_vec + bio->bi_vcnt - 1));
+       } while (bvec <= (dio_bio->bi_io_vec + dio_bio->bi_vcnt - 1));
 
-       dip->disk_bytenr = (u64)bio->bi_sector << 9;
-       bio->bi_private = dip;
+       dip->disk_bytenr = (u64)dio_bio->bi_sector << 9;
+       io_bio->bi_private = dip;
        dip->errors = 0;
-       dip->orig_bio = bio;
+       dip->orig_bio = io_bio;
+       dip->dio_bio = dio_bio;
        atomic_set(&dip->pending_bios, 0);
 
        if (write)
-               bio->bi_end_io = btrfs_endio_direct_write;
+               io_bio->bi_end_io = btrfs_endio_direct_write;
        else
-               bio->bi_end_io = btrfs_endio_direct_read;
+               io_bio->bi_end_io = btrfs_endio_direct_read;
 
        ret = btrfs_submit_direct_hook(rw, dip, skip_sum);
        if (!ret)
                return;
+
+free_io_bio:
+       bio_put(io_bio);
+
 free_ordered:
        /*
         * If this is a write, we need to clean up the reserved space and kill
@@ -7300,7 +7326,7 @@ free_ordered:
                btrfs_put_ordered_extent(ordered);
                btrfs_put_ordered_extent(ordered);
        }
-       bio_endio(bio, ret);
+       bio_endio(dio_bio, ret);
 }
 
 static ssize_t check_direct_IO(struct btrfs_root *root, int rw, struct kiocb *iocb,
@@ -7979,7 +8005,6 @@ void btrfs_destroy_inode(struct inode *inode)
        inode_tree_del(inode);
        btrfs_drop_extent_cache(inode, 0, (u64)-1, 0);
 free:
-       btrfs_remove_delayed_node(inode);
        call_rcu(&inode->i_rcu, btrfs_i_callback);
 }
 
index 0de4a2f..0f81d67 100644 (file)
@@ -1801,7 +1801,11 @@ static noinline int copy_to_sk(struct btrfs_root *root,
                item_off = btrfs_item_ptr_offset(leaf, i);
                item_len = btrfs_item_size_nr(leaf, i);
 
-               if (item_len > BTRFS_SEARCH_ARGS_BUFSIZE)
+               btrfs_item_key_to_cpu(leaf, key, i);
+               if (!key_in_sk(key, sk))
+                       continue;
+
+               if (sizeof(sh) + item_len > BTRFS_SEARCH_ARGS_BUFSIZE)
                        item_len = 0;
 
                if (sizeof(sh) + item_len + *sk_offset >
@@ -1810,10 +1814,6 @@ static noinline int copy_to_sk(struct btrfs_root *root,
                        goto overflow;
                }
 
-               btrfs_item_key_to_cpu(leaf, key, i);
-               if (!key_in_sk(key, sk))
-                       continue;
-
                sh.objectid = key->objectid;
                sh.offset = key->offset;
                sh.type = key->type;
index 0740621..0525e13 100644 (file)
@@ -1050,7 +1050,7 @@ static int rbio_add_io_page(struct btrfs_raid_bio *rbio,
        }
 
        /* put a new bio on the list */
-       bio = bio_alloc(GFP_NOFS, bio_max_len >> PAGE_SHIFT?:1);
+       bio = btrfs_io_bio_alloc(GFP_NOFS, bio_max_len >> PAGE_SHIFT?:1);
        if (!bio)
                return -ENOMEM;
 
index 704a1b8..395b820 100644 (file)
@@ -1773,7 +1773,7 @@ again:
                        if (!eb || !extent_buffer_uptodate(eb)) {
                                ret = (!eb) ? -ENOMEM : -EIO;
                                free_extent_buffer(eb);
-                               return ret;
+                               break;
                        }
                        btrfs_tree_lock(eb);
                        if (cow) {
@@ -3350,6 +3350,11 @@ static int delete_block_group_cache(struct btrfs_fs_info *fs_info,
        }
 
 truncate:
+       ret = btrfs_check_trunc_cache_free_space(root,
+                                                &fs_info->global_block_rsv);
+       if (ret)
+               goto out;
+
        path = btrfs_alloc_path();
        if (!path) {
                ret = -ENOMEM;
index f489e24..79bd479 100644 (file)
@@ -1296,7 +1296,7 @@ static void scrub_recheck_block(struct btrfs_fs_info *fs_info,
                }
 
                WARN_ON(!page->page);
-               bio = bio_alloc(GFP_NOFS, 1);
+               bio = btrfs_io_bio_alloc(GFP_NOFS, 1);
                if (!bio) {
                        page->io_error = 1;
                        sblock->no_io_error_seen = 0;
@@ -1431,7 +1431,7 @@ static int scrub_repair_page_from_good_copy(struct scrub_block *sblock_bad,
                        return -EIO;
                }
 
-               bio = bio_alloc(GFP_NOFS, 1);
+               bio = btrfs_io_bio_alloc(GFP_NOFS, 1);
                if (!bio)
                        return -EIO;
                bio->bi_bdev = page_bad->dev->bdev;
@@ -1522,7 +1522,7 @@ again:
                sbio->dev = wr_ctx->tgtdev;
                bio = sbio->bio;
                if (!bio) {
-                       bio = bio_alloc(GFP_NOFS, wr_ctx->pages_per_wr_bio);
+                       bio = btrfs_io_bio_alloc(GFP_NOFS, wr_ctx->pages_per_wr_bio);
                        if (!bio) {
                                mutex_unlock(&wr_ctx->wr_lock);
                                return -ENOMEM;
@@ -1930,7 +1930,7 @@ again:
                sbio->dev = spage->dev;
                bio = sbio->bio;
                if (!bio) {
-                       bio = bio_alloc(GFP_NOFS, sctx->pages_per_rd_bio);
+                       bio = btrfs_io_bio_alloc(GFP_NOFS, sctx->pages_per_rd_bio);
                        if (!bio)
                                return -ENOMEM;
                        sbio->bio = bio;
@@ -3307,7 +3307,7 @@ static int write_page_nocow(struct scrub_ctx *sctx,
                        "btrfs: scrub write_page_nocow(bdev == NULL) is unexpected!\n");
                return -EIO;
        }
-       bio = bio_alloc(GFP_NOFS, 1);
+       bio = btrfs_io_bio_alloc(GFP_NOFS, 1);
        if (!bio) {
                spin_lock(&sctx->stat_lock);
                sctx->stat.malloc_errors++;
index a4807ce..f0857e0 100644 (file)
@@ -1263,6 +1263,7 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
 
                btrfs_dev_replace_suspend_for_unmount(fs_info);
                btrfs_scrub_cancel(fs_info);
+               btrfs_pause_balance(fs_info);
 
                ret = btrfs_commit_super(root);
                if (ret)
index 0e925ce..8bffb91 100644 (file)
@@ -3120,14 +3120,13 @@ int btrfs_balance(struct btrfs_balance_control *bctl,
        allowed = BTRFS_AVAIL_ALLOC_BIT_SINGLE;
        if (num_devices == 1)
                allowed |= BTRFS_BLOCK_GROUP_DUP;
-       else if (num_devices < 4)
+       else if (num_devices > 1)
                allowed |= (BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID1);
-       else
-               allowed |= (BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID1 |
-                               BTRFS_BLOCK_GROUP_RAID10 |
-                               BTRFS_BLOCK_GROUP_RAID5 |
-                               BTRFS_BLOCK_GROUP_RAID6);
-
+       if (num_devices > 2)
+               allowed |= BTRFS_BLOCK_GROUP_RAID5;
+       if (num_devices > 3)
+               allowed |= (BTRFS_BLOCK_GROUP_RAID10 |
+                           BTRFS_BLOCK_GROUP_RAID6);
        if ((bctl->data.flags & BTRFS_BALANCE_ARGS_CONVERT) &&
            (!alloc_profile_is_valid(bctl->data.target, 1) ||
             (bctl->data.target & ~allowed))) {
@@ -5019,42 +5018,16 @@ int btrfs_rmap_block(struct btrfs_mapping_tree *map_tree,
        return 0;
 }
 
-static void *merge_stripe_index_into_bio_private(void *bi_private,
-                                                unsigned int stripe_index)
-{
-       /*
-        * with single, dup, RAID0, RAID1 and RAID10, stripe_index is
-        * at most 1.
-        * The alternative solution (instead of stealing bits from the
-        * pointer) would be to allocate an intermediate structure
-        * that contains the old private pointer plus the stripe_index.
-        */
-       BUG_ON((((uintptr_t)bi_private) & 3) != 0);
-       BUG_ON(stripe_index > 3);
-       return (void *)(((uintptr_t)bi_private) | stripe_index);
-}
-
-static struct btrfs_bio *extract_bbio_from_bio_private(void *bi_private)
-{
-       return (struct btrfs_bio *)(((uintptr_t)bi_private) & ~((uintptr_t)3));
-}
-
-static unsigned int extract_stripe_index_from_bio_private(void *bi_private)
-{
-       return (unsigned int)((uintptr_t)bi_private) & 3;
-}
-
 static void btrfs_end_bio(struct bio *bio, int err)
 {
-       struct btrfs_bio *bbio = extract_bbio_from_bio_private(bio->bi_private);
+       struct btrfs_bio *bbio = bio->bi_private;
        int is_orig_bio = 0;
 
        if (err) {
                atomic_inc(&bbio->error);
                if (err == -EIO || err == -EREMOTEIO) {
                        unsigned int stripe_index =
-                               extract_stripe_index_from_bio_private(
-                                       bio->bi_private);
+                               btrfs_io_bio(bio)->stripe_index;
                        struct btrfs_device *dev;
 
                        BUG_ON(stripe_index >= bbio->num_stripes);
@@ -5084,8 +5057,7 @@ static void btrfs_end_bio(struct bio *bio, int err)
                }
                bio->bi_private = bbio->private;
                bio->bi_end_io = bbio->end_io;
-               bio->bi_bdev = (struct block_device *)
-                                       (unsigned long)bbio->mirror_num;
+               btrfs_io_bio(bio)->mirror_num = bbio->mirror_num;
                /* only send an error to the higher layers if it is
                 * beyond the tolerance of the btrfs bio
                 */
@@ -5211,8 +5183,7 @@ static void submit_stripe_bio(struct btrfs_root *root, struct btrfs_bio *bbio,
        struct btrfs_device *dev = bbio->stripes[dev_nr].dev;
 
        bio->bi_private = bbio;
-       bio->bi_private = merge_stripe_index_into_bio_private(
-                       bio->bi_private, (unsigned int)dev_nr);
+       btrfs_io_bio(bio)->stripe_index = dev_nr;
        bio->bi_end_io = btrfs_end_bio;
        bio->bi_sector = physical >> 9;
 #ifdef DEBUG
@@ -5273,8 +5244,7 @@ static void bbio_error(struct btrfs_bio *bbio, struct bio *bio, u64 logical)
        if (atomic_dec_and_test(&bbio->stripes_pending)) {
                bio->bi_private = bbio->private;
                bio->bi_end_io = bbio->end_io;
-               bio->bi_bdev = (struct block_device *)
-                       (unsigned long)bbio->mirror_num;
+               btrfs_io_bio(bio)->mirror_num = bbio->mirror_num;
                bio->bi_sector = logical >> 9;
                kfree(bbio);
                bio_endio(bio, -EIO);
@@ -5352,7 +5322,7 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio,
                }
 
                if (dev_nr < total_devs - 1) {
-                       bio = bio_clone(first_bio, GFP_NOFS);
+                       bio = btrfs_bio_clone(first_bio, GFP_NOFS);
                        BUG_ON(!bio); /* -ENOMEM */
                } else {
                        bio = first_bio;
index 845ccbb..f6247e2 100644 (file)
@@ -152,6 +152,26 @@ struct btrfs_fs_devices {
        int rotating;
 };
 
+/*
+ * we need the mirror number and stripe index to be passed around
+ * the call chain while we are processing end_io (especially errors).
+ * Really, what we need is a btrfs_bio structure that has this info
+ * and is properly sized with its stripe array, but we're not there
+ * quite yet.  We have our own btrfs bioset, and all of the bios
+ * we allocate are actually btrfs_io_bios.  We'll cram as much of
+ * struct btrfs_bio as we can into this over time.
+ */
+struct btrfs_io_bio {
+       unsigned long mirror_num;
+       unsigned long stripe_index;
+       struct bio bio;
+};
+
+static inline struct btrfs_io_bio *btrfs_io_bio(struct bio *bio)
+{
+       return container_of(bio, struct btrfs_io_bio, bio);
+}
+
 struct btrfs_bio_stripe {
        struct btrfs_device *dev;
        u64 physical;
index 202dd3d..ebbf680 100644 (file)
@@ -191,27 +191,23 @@ void ceph_count_locks(struct inode *inode, int *fcntl_count, int *flock_count)
 }
 
 /**
- * Encode the flock and fcntl locks for the given inode into the pagelist.
- * Format is: #fcntl locks, sequential fcntl locks, #flock locks,
- * sequential flock locks.
- * Must be called with lock_flocks() already held.
- * If we encounter more of a specific lock type than expected,
- * we return the value 1.
+ * Encode the flock and fcntl locks for the given inode into the ceph_filelock
+ * array. Must be called with lock_flocks() already held.
+ * If we encounter more of a specific lock type than expected, return -ENOSPC.
  */
-int ceph_encode_locks(struct inode *inode, struct ceph_pagelist *pagelist,
-                     int num_fcntl_locks, int num_flock_locks)
+int ceph_encode_locks_to_buffer(struct inode *inode,
+                               struct ceph_filelock *flocks,
+                               int num_fcntl_locks, int num_flock_locks)
 {
        struct file_lock *lock;
-       struct ceph_filelock cephlock;
        int err = 0;
        int seen_fcntl = 0;
        int seen_flock = 0;
+       int l = 0;
 
        dout("encoding %d flock and %d fcntl locks", num_flock_locks,
             num_fcntl_locks);
-       err = ceph_pagelist_append(pagelist, &num_fcntl_locks, sizeof(u32));
-       if (err)
-               goto fail;
+
        for (lock = inode->i_flock; lock != NULL; lock = lock->fl_next) {
                if (lock->fl_flags & FL_POSIX) {
                        ++seen_fcntl;
@@ -219,19 +215,12 @@ int ceph_encode_locks(struct inode *inode, struct ceph_pagelist *pagelist,
                                err = -ENOSPC;
                                goto fail;
                        }
-                       err = lock_to_ceph_filelock(lock, &cephlock);
+                       err = lock_to_ceph_filelock(lock, &flocks[l]);
                        if (err)
                                goto fail;
-                       err = ceph_pagelist_append(pagelist, &cephlock,
-                                          sizeof(struct ceph_filelock));
+                       ++l;
                }
-               if (err)
-                       goto fail;
        }
-
-       err = ceph_pagelist_append(pagelist, &num_flock_locks, sizeof(u32));
-       if (err)
-               goto fail;
        for (lock = inode->i_flock; lock != NULL; lock = lock->fl_next) {
                if (lock->fl_flags & FL_FLOCK) {
                        ++seen_flock;
@@ -239,19 +228,51 @@ int ceph_encode_locks(struct inode *inode, struct ceph_pagelist *pagelist,
                                err = -ENOSPC;
                                goto fail;
                        }
-                       err = lock_to_ceph_filelock(lock, &cephlock);
+                       err = lock_to_ceph_filelock(lock, &flocks[l]);
                        if (err)
                                goto fail;
-                       err = ceph_pagelist_append(pagelist, &cephlock,
-                                          sizeof(struct ceph_filelock));
+                       ++l;
                }
-               if (err)
-                       goto fail;
        }
 fail:
        return err;
 }
 
+/**
+ * Copy the encoded flock and fcntl locks into the pagelist.
+ * Format is: #fcntl locks, sequential fcntl locks, #flock locks,
+ * sequential flock locks.
+ * Returns zero on success.
+ */
+int ceph_locks_to_pagelist(struct ceph_filelock *flocks,
+                          struct ceph_pagelist *pagelist,
+                          int num_fcntl_locks, int num_flock_locks)
+{
+       int err = 0;
+       __le32 nlocks;
+
+       nlocks = cpu_to_le32(num_fcntl_locks);
+       err = ceph_pagelist_append(pagelist, &nlocks, sizeof(nlocks));
+       if (err)
+               goto out_fail;
+
+       err = ceph_pagelist_append(pagelist, flocks,
+                                  num_fcntl_locks * sizeof(*flocks));
+       if (err)
+               goto out_fail;
+
+       nlocks = cpu_to_le32(num_flock_locks);
+       err = ceph_pagelist_append(pagelist, &nlocks, sizeof(nlocks));
+       if (err)
+               goto out_fail;
+
+       err = ceph_pagelist_append(pagelist,
+                                  &flocks[num_fcntl_locks],
+                                  num_flock_locks * sizeof(*flocks));
+out_fail:
+       return err;
+}
+
 /*
  * Given a pointer to a lock, convert it to a ceph filelock
  */
index 4f22671..4d29203 100644 (file)
@@ -2478,39 +2478,44 @@ static int encode_caps_cb(struct inode *inode, struct ceph_cap *cap,
 
        if (recon_state->flock) {
                int num_fcntl_locks, num_flock_locks;
-               struct ceph_pagelist_cursor trunc_point;
-
-               ceph_pagelist_set_cursor(pagelist, &trunc_point);
-               do {
-                       lock_flocks();
-                       ceph_count_locks(inode, &num_fcntl_locks,
-                                        &num_flock_locks);
-                       rec.v2.flock_len = (2*sizeof(u32) +
-                                           (num_fcntl_locks+num_flock_locks) *
-                                           sizeof(struct ceph_filelock));
-                       unlock_flocks();
-
-                       /* pre-alloc pagelist */
-                       ceph_pagelist_truncate(pagelist, &trunc_point);
-                       err = ceph_pagelist_append(pagelist, &rec, reclen);
-                       if (!err)
-                               err = ceph_pagelist_reserve(pagelist,
-                                                           rec.v2.flock_len);
-
-                       /* encode locks */
-                       if (!err) {
-                               lock_flocks();
-                               err = ceph_encode_locks(inode,
-                                                       pagelist,
-                                                       num_fcntl_locks,
-                                                       num_flock_locks);
-                               unlock_flocks();
-                       }
-               } while (err == -ENOSPC);
+               struct ceph_filelock *flocks;
+
+encode_again:
+               lock_flocks();
+               ceph_count_locks(inode, &num_fcntl_locks, &num_flock_locks);
+               unlock_flocks();
+               flocks = kmalloc((num_fcntl_locks+num_flock_locks) *
+                                sizeof(struct ceph_filelock), GFP_NOFS);
+               if (!flocks) {
+                       err = -ENOMEM;
+                       goto out_free;
+               }
+               lock_flocks();
+               err = ceph_encode_locks_to_buffer(inode, flocks,
+                                                 num_fcntl_locks,
+                                                 num_flock_locks);
+               unlock_flocks();
+               if (err) {
+                       kfree(flocks);
+                       if (err == -ENOSPC)
+                               goto encode_again;
+                       goto out_free;
+               }
+               /*
+                * number of encoded locks is stable, so copy to pagelist
+                */
+               rec.v2.flock_len = cpu_to_le32(2*sizeof(u32) +
+                                   (num_fcntl_locks+num_flock_locks) *
+                                   sizeof(struct ceph_filelock));
+               err = ceph_pagelist_append(pagelist, &rec, reclen);
+               if (!err)
+                       err = ceph_locks_to_pagelist(flocks, pagelist,
+                                                    num_fcntl_locks,
+                                                    num_flock_locks);
+               kfree(flocks);
        } else {
                err = ceph_pagelist_append(pagelist, &rec, reclen);
        }
-
 out_free:
        kfree(path);
 out_dput:
index 8696be2..7ccfdb4 100644 (file)
@@ -822,8 +822,13 @@ extern const struct export_operations ceph_export_ops;
 extern int ceph_lock(struct file *file, int cmd, struct file_lock *fl);
 extern int ceph_flock(struct file *file, int cmd, struct file_lock *fl);
 extern void ceph_count_locks(struct inode *inode, int *p_num, int *f_num);
-extern int ceph_encode_locks(struct inode *i, struct ceph_pagelist *p,
-                            int p_locks, int f_locks);
+extern int ceph_encode_locks_to_buffer(struct inode *inode,
+                                      struct ceph_filelock *flocks,
+                                      int num_fcntl_locks,
+                                      int num_flock_locks);
+extern int ceph_locks_to_pagelist(struct ceph_filelock *flocks,
+                                 struct ceph_pagelist *pagelist,
+                                 int num_fcntl_locks, int num_flock_locks);
 extern int lock_to_ceph_filelock(struct file_lock *fl, struct ceph_filelock *c);
 
 /* debugfs.c */
index 8e33ec6..58df174 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/slab.h>
 #include <linux/vfs.h>
 #include <linux/fs.h>
+#include <linux/inet.h>
 #include "cifsglob.h"
 #include "cifsproto.h"
 #include "cifsfs.h"
@@ -48,58 +49,74 @@ void cifs_dfs_release_automount_timer(void)
 }
 
 /**
- * cifs_get_share_name -       extracts share name from UNC
- * @node_name: pointer to UNC string
+ * cifs_build_devname - build a devicename from a UNC and optional prepath
+ * @nodename:  pointer to UNC string
+ * @prepath:   pointer to prefixpath (or NULL if there isn't one)
  *
- * Extracts sharename form full UNC.
- * i.e. strips from UNC trailing path that is not part of share
- * name and fixup missing '\' in the beginning of DFS node refferal
- * if necessary.
- * Returns pointer to share name on success or ERR_PTR on error.
- * Caller is responsible for freeing returned string.
+ * Build a new cifs devicename after chasing a DFS referral. Allocate a buffer
+ * big enough to hold the final thing. Copy the UNC from the nodename, and
+ * concatenate the prepath onto the end of it if there is one.
+ *
+ * Returns pointer to the built string, or a ERR_PTR. Caller is responsible
+ * for freeing the returned string.
  */
-static char *cifs_get_share_name(const char *node_name)
+static char *
+cifs_build_devname(char *nodename, const char *prepath)
 {
-       int len;
-       char *UNC;
-       char *pSep;
-
-       len = strlen(node_name);
-       UNC = kmalloc(len+2 /*for term null and additional \ if it's missed */,
-                        GFP_KERNEL);
-       if (!UNC)
-               return ERR_PTR(-ENOMEM);
+       size_t pplen;
+       size_t unclen;
+       char *dev;
+       char *pos;
+
+       /* skip over any preceding delimiters */
+       nodename += strspn(nodename, "\\");
+       if (!*nodename)
+               return ERR_PTR(-EINVAL);
 
-       /* get share name and server name */
-       if (node_name[1] != '\\') {
-               UNC[0] = '\\';
-               strncpy(UNC+1, node_name, len);
-               len++;
-               UNC[len] = 0;
-       } else {
-               strncpy(UNC, node_name, len);
-               UNC[len] = 0;
-       }
+       /* get length of UNC and set pos to last char */
+       unclen = strlen(nodename);
+       pos = nodename + unclen - 1;
 
-       /* find server name end */
-       pSep = memchr(UNC+2, '\\', len-2);
-       if (!pSep) {
-               cifs_dbg(VFS, "%s: no server name end in node name: %s\n",
-                        __func__, node_name);
-               kfree(UNC);
-               return ERR_PTR(-EINVAL);
+       /* trim off any trailing delimiters */
+       while (*pos == '\\') {
+               --pos;
+               --unclen;
        }
 
-       /* find sharename end */
-       pSep++;
-       pSep = memchr(UNC+(pSep-UNC), '\\', len-(pSep-UNC));
-       if (pSep) {
-               /* trim path up to sharename end
-                * now we have share name in UNC */
-               *pSep = 0;
+       /* allocate a buffer:
+        * +2 for preceding "//"
+        * +1 for delimiter between UNC and prepath
+        * +1 for trailing NULL
+        */
+       pplen = prepath ? strlen(prepath) : 0;
+       dev = kmalloc(2 + unclen + 1 + pplen + 1, GFP_KERNEL);
+       if (!dev)
+               return ERR_PTR(-ENOMEM);
+
+       pos = dev;
+       /* add the initial "//" */
+       *pos = '/';
+       ++pos;
+       *pos = '/';
+       ++pos;
+
+       /* copy in the UNC portion from referral */
+       memcpy(pos, nodename, unclen);
+       pos += unclen;
+
+       /* copy the prefixpath remainder (if there is one) */
+       if (pplen) {
+               *pos = '/';
+               ++pos;
+               memcpy(pos, prepath, pplen);
+               pos += pplen;
        }
 
-       return UNC;
+       /* NULL terminator */
+       *pos = '\0';
+
+       convert_delimiter(dev, '/');
+       return dev;
 }
 
 
@@ -123,6 +140,7 @@ char *cifs_compose_mount_options(const char *sb_mountdata,
 {
        int rc;
        char *mountdata = NULL;
+       const char *prepath = NULL;
        int md_len;
        char *tkn_e;
        char *srvIP = NULL;
@@ -132,7 +150,10 @@ char *cifs_compose_mount_options(const char *sb_mountdata,
        if (sb_mountdata == NULL)
                return ERR_PTR(-EINVAL);
 
-       *devname = cifs_get_share_name(ref->node_name);
+       if (strlen(fullpath) - ref->path_consumed)
+               prepath = fullpath + ref->path_consumed;
+
+       *devname = cifs_build_devname(ref->node_name, prepath);
        if (IS_ERR(*devname)) {
                rc = PTR_ERR(*devname);
                *devname = NULL;
@@ -146,12 +167,14 @@ char *cifs_compose_mount_options(const char *sb_mountdata,
                goto compose_mount_options_err;
        }
 
-       /* md_len = strlen(...) + 12 for 'sep+prefixpath='
-        * assuming that we have 'unc=' and 'ip=' in
-        * the original sb_mountdata
+       /*
+        * In most cases, we'll be building a shorter string than the original,
+        * but we do have to assume that the address in the ip= option may be
+        * much longer than the original. Add the max length of an address
+        * string to the length of the original string to allow for worst case.
         */
-       md_len = strlen(sb_mountdata) + rc + strlen(ref->node_name) + 12;
-       mountdata = kzalloc(md_len+1, GFP_KERNEL);
+       md_len = strlen(sb_mountdata) + INET6_ADDRSTRLEN;
+       mountdata = kzalloc(md_len + 1, GFP_KERNEL);
        if (mountdata == NULL) {
                rc = -ENOMEM;
                goto compose_mount_options_err;
@@ -195,26 +218,6 @@ char *cifs_compose_mount_options(const char *sb_mountdata,
                strncat(mountdata, &sep, 1);
        strcat(mountdata, "ip=");
        strcat(mountdata, srvIP);
-       strncat(mountdata, &sep, 1);
-       strcat(mountdata, "unc=");
-       strcat(mountdata, *devname);
-
-       /* find & copy prefixpath */
-       tkn_e = strchr(ref->node_name + 2, '\\');
-       if (tkn_e == NULL) {
-               /* invalid unc, missing share name*/
-               rc = -EINVAL;
-               goto compose_mount_options_err;
-       }
-
-       tkn_e = strchr(tkn_e + 1, '\\');
-       if (tkn_e || (strlen(fullpath) - ref->path_consumed)) {
-               strncat(mountdata, &sep, 1);
-               strcat(mountdata, "prefixpath=");
-               if (tkn_e)
-                       strcat(mountdata, tkn_e + 1);
-               strcat(mountdata, fullpath + ref->path_consumed);
-       }
 
        /*cifs_dbg(FYI, "%s: parent mountdata: %s\n", __func__, sb_mountdata);*/
        /*cifs_dbg(FYI, "%s: submount mountdata: %s\n", __func__, mountdata );*/
index 72e4efe..3752b9f 100644 (file)
@@ -372,9 +372,6 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
        cifs_show_security(s, tcon->ses->server);
        cifs_show_cache_flavor(s, cifs_sb);
 
-       seq_printf(s, ",unc=");
-       seq_escape(s, tcon->treeName, " \t\n\\");
-
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER)
                seq_printf(s, ",multiuser");
        else if (tcon->ses->user_name)
index 99eeaa1..e3bc39b 100644 (file)
@@ -1061,6 +1061,7 @@ static int cifs_parse_security_flavors(char *value,
 #endif
        case Opt_sec_none:
                vol->nullauth = 1;
+               vol->secFlg |= CIFSSEC_MAY_NTLM;
                break;
        default:
                cifs_dbg(VFS, "bad security option: %s\n", value);
@@ -1257,14 +1258,18 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
        vol->backupuid_specified = false; /* no backup intent for a user */
        vol->backupgid_specified = false; /* no backup intent for a group */
 
-       /*
-        * For now, we ignore -EINVAL errors under the assumption that the
-        * unc= and prefixpath= options will be usable.
-        */
-       if (cifs_parse_devname(devname, vol) == -ENOMEM) {
-               printk(KERN_ERR "CIFS: Unable to allocate memory to parse "
-                               "device string.\n");
-               goto out_nomem;
+       switch (cifs_parse_devname(devname, vol)) {
+       case 0:
+               break;
+       case -ENOMEM:
+               cifs_dbg(VFS, "Unable to allocate memory for devname.\n");
+               goto cifs_parse_mount_err;
+       case -EINVAL:
+               cifs_dbg(VFS, "Malformed UNC in devname.\n");
+               goto cifs_parse_mount_err;
+       default:
+               cifs_dbg(VFS, "Unknown error parsing devname.\n");
+               goto cifs_parse_mount_err;
        }
 
        while ((data = strsep(&options, separator)) != NULL) {
@@ -1826,7 +1831,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
        }
 #endif
        if (!vol->UNC) {
-               cifs_dbg(VFS, "CIFS mount error: No usable UNC path provided in device string or in unc= option!\n");
+               cifs_dbg(VFS, "CIFS mount error: No usable UNC path provided in device string!\n");
                goto cifs_parse_mount_err;
        }
 
@@ -3274,8 +3279,8 @@ build_unc_path_to_root(const struct smb_vol *vol,
        pos = full_path + unc_len;
 
        if (pplen) {
-               *pos++ = CIFS_DIR_SEP(cifs_sb);
-               strncpy(pos, vol->prepath, pplen);
+               *pos = CIFS_DIR_SEP(cifs_sb);
+               strncpy(pos + 1, vol->prepath, pplen);
                pos += pplen;
        }
 
index e7512e4..7ede730 100644 (file)
@@ -34,7 +34,7 @@
 
 /**
  * dns_resolve_server_name_to_ip - Resolve UNC server name to ip address.
- * @unc: UNC path specifying the server
+ * @unc: UNC path specifying the server (with '/' as delimiter)
  * @ip_addr: Where to return the IP address.
  *
  * The IP address will be returned in string form, and the caller is
@@ -64,7 +64,7 @@ dns_resolve_server_name_to_ip(const char *unc, char **ip_addr)
        hostname = unc + 2;
 
        /* Search for server name delimiter */
-       sep = memchr(hostname, '\\', len);
+       sep = memchr(hostname, '/', len);
        if (sep)
                len = sep - hostname;
        else
index fc30251..20efd81 100644 (file)
@@ -171,7 +171,8 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
 
        if (fattr->cf_flags & CIFS_FATTR_DFS_REFERRAL)
                inode->i_flags |= S_AUTOMOUNT;
-       cifs_set_ops(inode);
+       if (inode->i_state & I_NEW)
+               cifs_set_ops(inode);
 }
 
 void
index d5c25db..f71ec12 100644 (file)
@@ -243,7 +243,7 @@ void ecryptfs_destroy_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat)
        struct ecryptfs_key_sig *key_sig, *key_sig_tmp;
 
        if (crypt_stat->tfm)
-               crypto_free_blkcipher(crypt_stat->tfm);
+               crypto_free_ablkcipher(crypt_stat->tfm);
        if (crypt_stat->hash_tfm)
                crypto_free_hash(crypt_stat->hash_tfm);
        list_for_each_entry_safe(key_sig, key_sig_tmp,
@@ -319,6 +319,22 @@ int virt_to_scatterlist(const void *addr, int size, struct scatterlist *sg,
        return i;
 }
 
+struct extent_crypt_result {
+       struct completion completion;
+       int rc;
+};
+
+static void extent_crypt_complete(struct crypto_async_request *req, int rc)
+{
+       struct extent_crypt_result *ecr = req->data;
+
+       if (rc == -EINPROGRESS)
+               return;
+
+       ecr->rc = rc;
+       complete(&ecr->completion);
+}
+
 /**
  * encrypt_scatterlist
  * @crypt_stat: Pointer to the crypt_stat struct to initialize.
@@ -334,11 +350,8 @@ static int encrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat,
                               struct scatterlist *src_sg, int size,
                               unsigned char *iv)
 {
-       struct blkcipher_desc desc = {
-               .tfm = crypt_stat->tfm,
-               .info = iv,
-               .flags = CRYPTO_TFM_REQ_MAY_SLEEP
-       };
+       struct ablkcipher_request *req = NULL;
+       struct extent_crypt_result ecr;
        int rc = 0;
 
        BUG_ON(!crypt_stat || !crypt_stat->tfm
@@ -349,24 +362,47 @@ static int encrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat,
                ecryptfs_dump_hex(crypt_stat->key,
                                  crypt_stat->key_size);
        }
-       /* Consider doing this once, when the file is opened */
+
+       init_completion(&ecr.completion);
+
        mutex_lock(&crypt_stat->cs_tfm_mutex);
-       if (!(crypt_stat->flags & ECRYPTFS_KEY_SET)) {
-               rc = crypto_blkcipher_setkey(crypt_stat->tfm, crypt_stat->key,
-                                            crypt_stat->key_size);
-               crypt_stat->flags |= ECRYPTFS_KEY_SET;
-       }
-       if (rc) {
-               ecryptfs_printk(KERN_ERR, "Error setting key; rc = [%d]\n",
-                               rc);
+       req = ablkcipher_request_alloc(crypt_stat->tfm, GFP_NOFS);
+       if (!req) {
                mutex_unlock(&crypt_stat->cs_tfm_mutex);
-               rc = -EINVAL;
+               rc = -ENOMEM;
                goto out;
        }
-       ecryptfs_printk(KERN_DEBUG, "Encrypting [%d] bytes.\n", size);
-       crypto_blkcipher_encrypt_iv(&desc, dest_sg, src_sg, size);
+
+       ablkcipher_request_set_callback(req,
+                       CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP,
+                       extent_crypt_complete, &ecr);
+       /* Consider doing this once, when the file is opened */
+       if (!(crypt_stat->flags & ECRYPTFS_KEY_SET)) {
+               rc = crypto_ablkcipher_setkey(crypt_stat->tfm, crypt_stat->key,
+                                             crypt_stat->key_size);
+               if (rc) {
+                       ecryptfs_printk(KERN_ERR,
+                                       "Error setting key; rc = [%d]\n",
+                                       rc);
+                       mutex_unlock(&crypt_stat->cs_tfm_mutex);
+                       rc = -EINVAL;
+                       goto out;
+               }
+               crypt_stat->flags |= ECRYPTFS_KEY_SET;
+       }
        mutex_unlock(&crypt_stat->cs_tfm_mutex);
+       ecryptfs_printk(KERN_DEBUG, "Encrypting [%d] bytes.\n", size);
+       ablkcipher_request_set_crypt(req, src_sg, dest_sg, size, iv);
+       rc = crypto_ablkcipher_encrypt(req);
+       if (rc == -EINPROGRESS || rc == -EBUSY) {
+               struct extent_crypt_result *ecr = req->base.data;
+
+               wait_for_completion(&ecr->completion);
+               rc = ecr->rc;
+               INIT_COMPLETION(ecr->completion);
+       }
 out:
+       ablkcipher_request_free(req);
        return rc;
 }
 
@@ -624,35 +660,61 @@ static int decrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat,
                               struct scatterlist *src_sg, int size,
                               unsigned char *iv)
 {
-       struct blkcipher_desc desc = {
-               .tfm = crypt_stat->tfm,
-               .info = iv,
-               .flags = CRYPTO_TFM_REQ_MAY_SLEEP
-       };
+       struct ablkcipher_request *req = NULL;
+       struct extent_crypt_result ecr;
        int rc = 0;
 
-       /* Consider doing this once, when the file is opened */
+       BUG_ON(!crypt_stat || !crypt_stat->tfm
+              || !(crypt_stat->flags & ECRYPTFS_STRUCT_INITIALIZED));
+       if (unlikely(ecryptfs_verbosity > 0)) {
+               ecryptfs_printk(KERN_DEBUG, "Key size [%zd]; key:\n",
+                               crypt_stat->key_size);
+               ecryptfs_dump_hex(crypt_stat->key,
+                                 crypt_stat->key_size);
+       }
+
+       init_completion(&ecr.completion);
+
        mutex_lock(&crypt_stat->cs_tfm_mutex);
-       rc = crypto_blkcipher_setkey(crypt_stat->tfm, crypt_stat->key,
-                                    crypt_stat->key_size);
-       if (rc) {
-               ecryptfs_printk(KERN_ERR, "Error setting key; rc = [%d]\n",
-                               rc);
+       req = ablkcipher_request_alloc(crypt_stat->tfm, GFP_NOFS);
+       if (!req) {
                mutex_unlock(&crypt_stat->cs_tfm_mutex);
-               rc = -EINVAL;
+               rc = -ENOMEM;
                goto out;
        }
-       ecryptfs_printk(KERN_DEBUG, "Decrypting [%d] bytes.\n", size);
-       rc = crypto_blkcipher_decrypt_iv(&desc, dest_sg, src_sg, size);
+
+       ablkcipher_request_set_callback(req,
+                       CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP,
+                       extent_crypt_complete, &ecr);
+       /* Consider doing this once, when the file is opened */
+       if (!(crypt_stat->flags & ECRYPTFS_KEY_SET)) {
+               rc = crypto_ablkcipher_setkey(crypt_stat->tfm, crypt_stat->key,
+                                             crypt_stat->key_size);
+               if (rc) {
+                       ecryptfs_printk(KERN_ERR,
+                                       "Error setting key; rc = [%d]\n",
+                                       rc);
+                       mutex_unlock(&crypt_stat->cs_tfm_mutex);
+                       rc = -EINVAL;
+                       goto out;
+               }
+               crypt_stat->flags |= ECRYPTFS_KEY_SET;
+       }
        mutex_unlock(&crypt_stat->cs_tfm_mutex);
-       if (rc) {
-               ecryptfs_printk(KERN_ERR, "Error decrypting; rc = [%d]\n",
-                               rc);
-               goto out;
+       ecryptfs_printk(KERN_DEBUG, "Decrypting [%d] bytes.\n", size);
+       ablkcipher_request_set_crypt(req, src_sg, dest_sg, size, iv);
+       rc = crypto_ablkcipher_decrypt(req);
+       if (rc == -EINPROGRESS || rc == -EBUSY) {
+               struct extent_crypt_result *ecr = req->base.data;
+
+               wait_for_completion(&ecr->completion);
+               rc = ecr->rc;
+               INIT_COMPLETION(ecr->completion);
        }
-       rc = size;
 out:
+       ablkcipher_request_free(req);
        return rc;
+
 }
 
 /**
@@ -746,8 +808,7 @@ int ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat)
                                                    crypt_stat->cipher, "cbc");
        if (rc)
                goto out_unlock;
-       crypt_stat->tfm = crypto_alloc_blkcipher(full_alg_name, 0,
-                                                CRYPTO_ALG_ASYNC);
+       crypt_stat->tfm = crypto_alloc_ablkcipher(full_alg_name, 0, 0);
        kfree(full_alg_name);
        if (IS_ERR(crypt_stat->tfm)) {
                rc = PTR_ERR(crypt_stat->tfm);
@@ -757,7 +818,7 @@ int ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat)
                                crypt_stat->cipher);
                goto out_unlock;
        }
-       crypto_blkcipher_set_flags(crypt_stat->tfm, CRYPTO_TFM_REQ_WEAK_KEY);
+       crypto_ablkcipher_set_flags(crypt_stat->tfm, CRYPTO_TFM_REQ_WEAK_KEY);
        rc = 0;
 out_unlock:
        mutex_unlock(&crypt_stat->cs_tfm_mutex);
index dd299b3..f622a73 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/nsproxy.h>
 #include <linux/backing-dev.h>
 #include <linux/ecryptfs.h>
+#include <linux/crypto.h>
 
 #define ECRYPTFS_DEFAULT_IV_BYTES 16
 #define ECRYPTFS_DEFAULT_EXTENT_SIZE 4096
@@ -233,7 +234,7 @@ struct ecryptfs_crypt_stat {
        size_t extent_shift;
        unsigned int extent_mask;
        struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
-       struct crypto_blkcipher *tfm;
+       struct crypto_ablkcipher *tfm;
        struct crypto_hash *hash_tfm; /* Crypto context for generating
                                       * the initialization vectors */
        unsigned char cipher[ECRYPTFS_MAX_CIPHER_NAME_SIZE];
index 201f0a0..a7abbea 100644 (file)
@@ -295,6 +295,12 @@ static int ecryptfs_release(struct inode *inode, struct file *file)
 static int
 ecryptfs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 {
+       int rc;
+
+       rc = filemap_write_and_wait(file->f_mapping);
+       if (rc)
+               return rc;
+
        return vfs_fsync(ecryptfs_file_to_lower(file), datasync);
 }
 
index bfb5315..8dd524f 100644 (file)
@@ -44,8 +44,11 @@ static ssize_t efivarfs_file_write(struct file *file,
 
        bytes = efivar_entry_set_get_size(var, attributes, &datasize,
                                          data, &set);
-       if (!set && bytes)
+       if (!set && bytes) {
+               if (bytes == -ENOENT)
+                       bytes = -EIO;
                goto out;
+       }
 
        if (bytes == -ENOENT) {
                drop_nlink(inode);
@@ -76,7 +79,14 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf,
        int err;
 
        err = efivar_entry_size(var, &datasize);
-       if (err)
+
+       /*
+        * efivarfs represents uncommitted variables with
+        * zero-length files. Reading them should return EOF.
+        */
+       if (err == -ENOENT)
+               return 0;
+       else if (err)
                return err;
 
        data = kmalloc(datasize + sizeof(attributes), GFP_KERNEL);
index 0aabb34..5aae3d1 100644 (file)
@@ -209,7 +209,6 @@ typedef struct ext4_io_end {
        ssize_t                 size;           /* size of the extent */
        struct kiocb            *iocb;          /* iocb struct for AIO */
        int                     result;         /* error value for AIO */
-       atomic_t                count;          /* reference counter */
 } ext4_io_end_t;
 
 struct ext4_io_submit {
@@ -2651,14 +2650,11 @@ extern int ext4_move_extents(struct file *o_filp, struct file *d_filp,
 
 /* page-io.c */
 extern int __init ext4_init_pageio(void);
+extern void ext4_add_complete_io(ext4_io_end_t *io_end);
 extern void ext4_exit_pageio(void);
 extern void ext4_ioend_shutdown(struct inode *);
+extern void ext4_free_io_end(ext4_io_end_t *io);
 extern ext4_io_end_t *ext4_init_io_end(struct inode *inode, gfp_t flags);
-extern ext4_io_end_t *ext4_get_io_end(ext4_io_end_t *io_end);
-extern int ext4_put_io_end(ext4_io_end_t *io_end);
-extern void ext4_put_io_end_defer(ext4_io_end_t *io_end);
-extern void ext4_io_submit_init(struct ext4_io_submit *io,
-                               struct writeback_control *wbc);
 extern void ext4_end_io_work(struct work_struct *work);
 extern void ext4_io_submit(struct ext4_io_submit *io);
 extern int ext4_bio_write_page(struct ext4_io_submit *io,
index 107936d..bc0f191 100644 (file)
@@ -3642,7 +3642,7 @@ int ext4_find_delalloc_range(struct inode *inode,
 {
        struct extent_status es;
 
-       ext4_es_find_delayed_extent(inode, lblk_start, &es);
+       ext4_es_find_delayed_extent_range(inode, lblk_start, lblk_end, &es);
        if (es.es_len == 0)
                return 0; /* there is no delay extent in this tree */
        else if (es.es_lblk <= lblk_start &&
@@ -4608,9 +4608,10 @@ static int ext4_find_delayed_extent(struct inode *inode,
        struct extent_status es;
        ext4_lblk_t block, next_del;
 
-       ext4_es_find_delayed_extent(inode, newes->es_lblk, &es);
-
        if (newes->es_pblk == 0) {
+               ext4_es_find_delayed_extent_range(inode, newes->es_lblk,
+                               newes->es_lblk + newes->es_len - 1, &es);
+
                /*
                 * No extent in extent-tree contains block @newes->es_pblk,
                 * then the block may stay in 1)a hole or 2)delayed-extent.
@@ -4630,7 +4631,7 @@ static int ext4_find_delayed_extent(struct inode *inode,
        }
 
        block = newes->es_lblk + newes->es_len;
-       ext4_es_find_delayed_extent(inode, block, &es);
+       ext4_es_find_delayed_extent_range(inode, block, EXT_MAX_BLOCKS, &es);
        if (es.es_len == 0)
                next_del = EXT_MAX_BLOCKS;
        else
index fe3337a..e6941e6 100644 (file)
@@ -232,14 +232,16 @@ static struct extent_status *__es_tree_search(struct rb_root *root,
 }
 
 /*
- * ext4_es_find_delayed_extent: find the 1st delayed extent covering @es->lblk
- * if it exists, otherwise, the next extent after @es->lblk.
+ * ext4_es_find_delayed_extent_range: find the 1st delayed extent covering
+ * @es->lblk if it exists, otherwise, the next extent after @es->lblk.
  *
  * @inode: the inode which owns delayed extents
  * @lblk: the offset where we start to search
+ * @end: the offset where we stop to search
  * @es: delayed extent that we found
  */
-void ext4_es_find_delayed_extent(struct inode *inode, ext4_lblk_t lblk,
+void ext4_es_find_delayed_extent_range(struct inode *inode,
+                                ext4_lblk_t lblk, ext4_lblk_t end,
                                 struct extent_status *es)
 {
        struct ext4_es_tree *tree = NULL;
@@ -247,7 +249,8 @@ void ext4_es_find_delayed_extent(struct inode *inode, ext4_lblk_t lblk,
        struct rb_node *node;
 
        BUG_ON(es == NULL);
-       trace_ext4_es_find_delayed_extent_enter(inode, lblk);
+       BUG_ON(end < lblk);
+       trace_ext4_es_find_delayed_extent_range_enter(inode, lblk);
 
        read_lock(&EXT4_I(inode)->i_es_lock);
        tree = &EXT4_I(inode)->i_es_tree;
@@ -270,6 +273,10 @@ out:
        if (es1 && !ext4_es_is_delayed(es1)) {
                while ((node = rb_next(&es1->rb_node)) != NULL) {
                        es1 = rb_entry(node, struct extent_status, rb_node);
+                       if (es1->es_lblk > end) {
+                               es1 = NULL;
+                               break;
+                       }
                        if (ext4_es_is_delayed(es1))
                                break;
                }
@@ -285,7 +292,7 @@ out:
        read_unlock(&EXT4_I(inode)->i_es_lock);
 
        ext4_es_lru_add(inode);
-       trace_ext4_es_find_delayed_extent_exit(inode, es);
+       trace_ext4_es_find_delayed_extent_range_exit(inode, es);
 }
 
 static struct extent_status *
index d8e2d4d..f740eb0 100644 (file)
@@ -62,7 +62,8 @@ extern int ext4_es_insert_extent(struct inode *inode, ext4_lblk_t lblk,
                                 unsigned long long status);
 extern int ext4_es_remove_extent(struct inode *inode, ext4_lblk_t lblk,
                                 ext4_lblk_t len);
-extern void ext4_es_find_delayed_extent(struct inode *inode, ext4_lblk_t lblk,
+extern void ext4_es_find_delayed_extent_range(struct inode *inode,
+                                       ext4_lblk_t lblk, ext4_lblk_t end,
                                        struct extent_status *es);
 extern int ext4_es_lookup_extent(struct inode *inode, ext4_lblk_t lblk,
                                 struct extent_status *es);
index 4959e29..b1b4d51 100644 (file)
@@ -465,7 +465,7 @@ static loff_t ext4_seek_data(struct file *file, loff_t offset, loff_t maxsize)
                 * If there is a delay extent at this offset,
                 * it will be as a data.
                 */
-               ext4_es_find_delayed_extent(inode, last, &es);
+               ext4_es_find_delayed_extent_range(inode, last, last, &es);
                if (es.es_len != 0 && in_range(last, es.es_lblk, es.es_len)) {
                        if (last != start)
                                dataoff = last << blkbits;
@@ -548,7 +548,7 @@ static loff_t ext4_seek_hole(struct file *file, loff_t offset, loff_t maxsize)
                 * If there is a delay extent at this offset,
                 * we will skip this extent.
                 */
-               ext4_es_find_delayed_extent(inode, last, &es);
+               ext4_es_find_delayed_extent_range(inode, last, last, &es);
                if (es.es_len != 0 && in_range(last, es.es_lblk, es.es_len)) {
                        last = es.es_lblk + es.es_len;
                        holeoff = last << blkbits;
index 0723774..d6382b8 100644 (file)
@@ -1488,10 +1488,7 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd,
        struct ext4_io_submit io_submit;
 
        BUG_ON(mpd->next_page <= mpd->first_page);
-       ext4_io_submit_init(&io_submit, mpd->wbc);
-       io_submit.io_end = ext4_init_io_end(inode, GFP_NOFS);
-       if (!io_submit.io_end)
-               return -ENOMEM;
+       memset(&io_submit, 0, sizeof(io_submit));
        /*
         * We need to start from the first_page to the next_page - 1
         * to make sure we also write the mapped dirty buffer_heads.
@@ -1579,8 +1576,6 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd,
                pagevec_release(&pvec);
        }
        ext4_io_submit(&io_submit);
-       /* Drop io_end reference we got from init */
-       ext4_put_io_end_defer(io_submit.io_end);
        return ret;
 }
 
@@ -2239,16 +2234,9 @@ static int ext4_writepage(struct page *page,
                 */
                return __ext4_journalled_writepage(page, len);
 
-       ext4_io_submit_init(&io_submit, wbc);
-       io_submit.io_end = ext4_init_io_end(inode, GFP_NOFS);
-       if (!io_submit.io_end) {
-               redirty_page_for_writepage(wbc, page);
-               return -ENOMEM;
-       }
+       memset(&io_submit, 0, sizeof(io_submit));
        ret = ext4_bio_write_page(&io_submit, page, len, wbc);
        ext4_io_submit(&io_submit);
-       /* Drop io_end reference we got from init */
-       ext4_put_io_end_defer(io_submit.io_end);
        return ret;
 }
 
@@ -3079,13 +3067,9 @@ static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset,
        struct inode *inode = file_inode(iocb->ki_filp);
         ext4_io_end_t *io_end = iocb->private;
 
-       /* if not async direct IO just return */
-       if (!io_end) {
-               inode_dio_done(inode);
-               if (is_async)
-                       aio_complete(iocb, ret, 0);
-               return;
-       }
+       /* if not async direct IO or dio with 0 bytes write, just return */
+       if (!io_end || !size)
+               goto out;
 
        ext_debug("ext4_end_io_dio(): io_end 0x%p "
                  "for inode %lu, iocb 0x%p, offset %llu, size %zd\n",
@@ -3093,13 +3077,25 @@ static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset,
                  size);
 
        iocb->private = NULL;
+
+       /* if not aio dio with unwritten extents, just free io and return */
+       if (!(io_end->flag & EXT4_IO_END_UNWRITTEN)) {
+               ext4_free_io_end(io_end);
+out:
+               inode_dio_done(inode);
+               if (is_async)
+                       aio_complete(iocb, ret, 0);
+               return;
+       }
+
        io_end->offset = offset;
        io_end->size = size;
        if (is_async) {
                io_end->iocb = iocb;
                io_end->result = ret;
        }
-       ext4_put_io_end_defer(io_end);
+
+       ext4_add_complete_io(io_end);
 }
 
 /*
@@ -3133,7 +3129,6 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb,
        get_block_t *get_block_func = NULL;
        int dio_flags = 0;
        loff_t final_size = offset + count;
-       ext4_io_end_t *io_end = NULL;
 
        /* Use the old path for reads and writes beyond i_size. */
        if (rw != WRITE || final_size > inode->i_size)
@@ -3172,16 +3167,13 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb,
        iocb->private = NULL;
        ext4_inode_aio_set(inode, NULL);
        if (!is_sync_kiocb(iocb)) {
-               io_end = ext4_init_io_end(inode, GFP_NOFS);
+               ext4_io_end_t *io_end = ext4_init_io_end(inode, GFP_NOFS);
                if (!io_end) {
                        ret = -ENOMEM;
                        goto retake_lock;
                }
                io_end->flag |= EXT4_IO_END_DIRECT;
-               /*
-                * Grab reference for DIO. Will be dropped in ext4_end_io_dio()
-                */
-               iocb->private = ext4_get_io_end(io_end);
+               iocb->private = io_end;
                /*
                 * we save the io structure for current async direct
                 * IO, so that later ext4_map_blocks() could flag the
@@ -3205,27 +3197,26 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb,
                                   NULL,
                                   dio_flags);
 
+       if (iocb->private)
+               ext4_inode_aio_set(inode, NULL);
        /*
-        * Put our reference to io_end. This can free the io_end structure e.g.
-        * in sync IO case or in case of error. It can even perform extent
-        * conversion if all bios we submitted finished before we got here.
-        * Note that in that case iocb->private can be already set to NULL
-        * here.
+        * The io_end structure takes a reference to the inode, that
+        * structure needs to be destroyed and the reference to the
+        * inode need to be dropped, when IO is complete, even with 0
+        * byte write, or failed.
+        *
+        * In the successful AIO DIO case, the io_end structure will
+        * be destroyed and the reference to the inode will be dropped
+        * after the end_io call back function is called.
+        *
+        * In the case there is 0 byte write, or error case, since VFS
+        * direct IO won't invoke the end_io call back function, we
+        * need to free the end_io structure here.
         */
-       if (io_end) {
-               ext4_inode_aio_set(inode, NULL);
-               ext4_put_io_end(io_end);
-               /*
-                * In case of error or no write ext4_end_io_dio() was not
-                * called so we have to put iocb's reference.
-                */
-               if (ret <= 0 && ret != -EIOCBQUEUED) {
-                       WARN_ON(iocb->private != io_end);
-                       ext4_put_io_end(io_end);
-                       iocb->private = NULL;
-               }
-       }
-       if (ret > 0 && !overwrite && ext4_test_inode_state(inode,
+       if (ret != -EIOCBQUEUED && ret <= 0 && iocb->private) {
+               ext4_free_io_end(iocb->private);
+               iocb->private = NULL;
+       } else if (ret > 0 && !overwrite && ext4_test_inode_state(inode,
                                                EXT4_STATE_DIO_UNWRITTEN)) {
                int err;
                /*
index b1ed9e0..def8408 100644 (file)
@@ -2105,7 +2105,11 @@ repeat:
                group = ac->ac_g_ex.fe_group;
 
                for (i = 0; i < ngroups; group++, i++) {
-                       if (group == ngroups)
+                       /*
+                        * Artificially restricted ngroups for non-extent
+                        * files makes group > ngroups possible on first loop.
+                        */
+                       if (group >= ngroups)
                                group = 0;
 
                        /* This now checks without needing the buddy page */
index 19599bd..4acf1f7 100644 (file)
@@ -62,28 +62,15 @@ void ext4_ioend_shutdown(struct inode *inode)
                cancel_work_sync(&EXT4_I(inode)->i_unwritten_work);
 }
 
-static void ext4_release_io_end(ext4_io_end_t *io_end)
+void ext4_free_io_end(ext4_io_end_t *io)
 {
-       BUG_ON(!list_empty(&io_end->list));
-       BUG_ON(io_end->flag & EXT4_IO_END_UNWRITTEN);
-
-       if (atomic_dec_and_test(&EXT4_I(io_end->inode)->i_ioend_count))
-               wake_up_all(ext4_ioend_wq(io_end->inode));
-       if (io_end->flag & EXT4_IO_END_DIRECT)
-               inode_dio_done(io_end->inode);
-       if (io_end->iocb)
-               aio_complete(io_end->iocb, io_end->result, 0);
-       kmem_cache_free(io_end_cachep, io_end);
-}
-
-static void ext4_clear_io_unwritten_flag(ext4_io_end_t *io_end)
-{
-       struct inode *inode = io_end->inode;
+       BUG_ON(!io);
+       BUG_ON(!list_empty(&io->list));
+       BUG_ON(io->flag & EXT4_IO_END_UNWRITTEN);
 
-       io_end->flag &= ~EXT4_IO_END_UNWRITTEN;
-       /* Wake up anyone waiting on unwritten extent conversion */
-       if (atomic_dec_and_test(&EXT4_I(inode)->i_unwritten))
-               wake_up_all(ext4_ioend_wq(inode));
+       if (atomic_dec_and_test(&EXT4_I(io->inode)->i_ioend_count))
+               wake_up_all(ext4_ioend_wq(io->inode));
+       kmem_cache_free(io_end_cachep, io);
 }
 
 /* check a range of space and convert unwritten extents to written. */
@@ -106,8 +93,13 @@ static int ext4_end_io(ext4_io_end_t *io)
                         "(inode %lu, offset %llu, size %zd, error %d)",
                         inode->i_ino, offset, size, ret);
        }
-       ext4_clear_io_unwritten_flag(io);
-       ext4_release_io_end(io);
+       /* Wake up anyone waiting on unwritten extent conversion */
+       if (atomic_dec_and_test(&EXT4_I(inode)->i_unwritten))
+               wake_up_all(ext4_ioend_wq(inode));
+       if (io->flag & EXT4_IO_END_DIRECT)
+               inode_dio_done(inode);
+       if (io->iocb)
+               aio_complete(io->iocb, io->result, 0);
        return ret;
 }
 
@@ -138,7 +130,7 @@ static void dump_completed_IO(struct inode *inode)
 }
 
 /* Add the io_end to per-inode completed end_io list. */
-static void ext4_add_complete_io(ext4_io_end_t *io_end)
+void ext4_add_complete_io(ext4_io_end_t *io_end)
 {
        struct ext4_inode_info *ei = EXT4_I(io_end->inode);
        struct workqueue_struct *wq;
@@ -175,6 +167,8 @@ static int ext4_do_flush_completed_IO(struct inode *inode)
                err = ext4_end_io(io);
                if (unlikely(!ret && err))
                        ret = err;
+               io->flag &= ~EXT4_IO_END_UNWRITTEN;
+               ext4_free_io_end(io);
        }
        return ret;
 }
@@ -206,43 +200,10 @@ ext4_io_end_t *ext4_init_io_end(struct inode *inode, gfp_t flags)
                atomic_inc(&EXT4_I(inode)->i_ioend_count);
                io->inode = inode;
                INIT_LIST_HEAD(&io->list);
-               atomic_set(&io->count, 1);
        }
        return io;
 }
 
-void ext4_put_io_end_defer(ext4_io_end_t *io_end)
-{
-       if (atomic_dec_and_test(&io_end->count)) {
-               if (!(io_end->flag & EXT4_IO_END_UNWRITTEN) || !io_end->size) {
-                       ext4_release_io_end(io_end);
-                       return;
-               }
-               ext4_add_complete_io(io_end);
-       }
-}
-
-int ext4_put_io_end(ext4_io_end_t *io_end)
-{
-       int err = 0;
-
-       if (atomic_dec_and_test(&io_end->count)) {
-               if (io_end->flag & EXT4_IO_END_UNWRITTEN) {
-                       err = ext4_convert_unwritten_extents(io_end->inode,
-                                               io_end->offset, io_end->size);
-                       ext4_clear_io_unwritten_flag(io_end);
-               }
-               ext4_release_io_end(io_end);
-       }
-       return err;
-}
-
-ext4_io_end_t *ext4_get_io_end(ext4_io_end_t *io_end)
-{
-       atomic_inc(&io_end->count);
-       return io_end;
-}
-
 /*
  * Print an buffer I/O error compatible with the fs/buffer.c.  This
  * provides compatibility with dmesg scrapers that look for a specific
@@ -325,7 +286,12 @@ static void ext4_end_bio(struct bio *bio, int error)
                             bi_sector >> (inode->i_blkbits - 9));
        }
 
-       ext4_put_io_end_defer(io_end);
+       if (!(io_end->flag & EXT4_IO_END_UNWRITTEN)) {
+               ext4_free_io_end(io_end);
+               return;
+       }
+
+       ext4_add_complete_io(io_end);
 }
 
 void ext4_io_submit(struct ext4_io_submit *io)
@@ -339,37 +305,40 @@ void ext4_io_submit(struct ext4_io_submit *io)
                bio_put(io->io_bio);
        }
        io->io_bio = NULL;
-}
-
-void ext4_io_submit_init(struct ext4_io_submit *io,
-                        struct writeback_control *wbc)
-{
-       io->io_op = (wbc->sync_mode == WB_SYNC_ALL ?  WRITE_SYNC : WRITE);
-       io->io_bio = NULL;
+       io->io_op = 0;
        io->io_end = NULL;
 }
 
-static int io_submit_init_bio(struct ext4_io_submit *io,
-                             struct buffer_head *bh)
+static int io_submit_init(struct ext4_io_submit *io,
+                         struct inode *inode,
+                         struct writeback_control *wbc,
+                         struct buffer_head *bh)
 {
+       ext4_io_end_t *io_end;
+       struct page *page = bh->b_page;
        int nvecs = bio_get_nr_vecs(bh->b_bdev);
        struct bio *bio;
 
+       io_end = ext4_init_io_end(inode, GFP_NOFS);
+       if (!io_end)
+               return -ENOMEM;
        bio = bio_alloc(GFP_NOIO, min(nvecs, BIO_MAX_PAGES));
        bio->bi_sector = bh->b_blocknr * (bh->b_size >> 9);
        bio->bi_bdev = bh->b_bdev;
+       bio->bi_private = io->io_end = io_end;
        bio->bi_end_io = ext4_end_bio;
-       bio->bi_private = ext4_get_io_end(io->io_end);
-       if (!io->io_end->size)
-               io->io_end->offset = (bh->b_page->index << PAGE_CACHE_SHIFT)
-                                    + bh_offset(bh);
+
+       io_end->offset = (page->index << PAGE_CACHE_SHIFT) + bh_offset(bh);
+
        io->io_bio = bio;
+       io->io_op = (wbc->sync_mode == WB_SYNC_ALL ?  WRITE_SYNC : WRITE);
        io->io_next_block = bh->b_blocknr;
        return 0;
 }
 
 static int io_submit_add_bh(struct ext4_io_submit *io,
                            struct inode *inode,
+                           struct writeback_control *wbc,
                            struct buffer_head *bh)
 {
        ext4_io_end_t *io_end;
@@ -380,18 +349,18 @@ submit_and_retry:
                ext4_io_submit(io);
        }
        if (io->io_bio == NULL) {
-               ret = io_submit_init_bio(io, bh);
+               ret = io_submit_init(io, inode, wbc, bh);
                if (ret)
                        return ret;
        }
-       ret = bio_add_page(io->io_bio, bh->b_page, bh->b_size, bh_offset(bh));
-       if (ret != bh->b_size)
-               goto submit_and_retry;
        io_end = io->io_end;
        if (test_clear_buffer_uninit(bh))
                ext4_set_io_unwritten_flag(inode, io_end);
-       io_end->size += bh->b_size;
+       io->io_end->size += bh->b_size;
        io->io_next_block++;
+       ret = bio_add_page(io->io_bio, bh->b_page, bh->b_size, bh_offset(bh));
+       if (ret != bh->b_size)
+               goto submit_and_retry;
        return 0;
 }
 
@@ -463,7 +432,7 @@ int ext4_bio_write_page(struct ext4_io_submit *io,
        do {
                if (!buffer_async_write(bh))
                        continue;
-               ret = io_submit_add_bh(io, inode, bh);
+               ret = io_submit_add_bh(io, inode, wbc, bh);
                if (ret) {
                        /*
                         * We only get here on ENOMEM.  Not much else
index dfce656..5d4513c 100644 (file)
@@ -1229,6 +1229,19 @@ static int fat_read_root(struct inode *inode)
        return 0;
 }
 
+static unsigned long calc_fat_clusters(struct super_block *sb)
+{
+       struct msdos_sb_info *sbi = MSDOS_SB(sb);
+
+       /* Divide first to avoid overflow */
+       if (sbi->fat_bits != 12) {
+               unsigned long ent_per_sec = sb->s_blocksize * 8 / sbi->fat_bits;
+               return ent_per_sec * sbi->fat_length;
+       }
+
+       return sbi->fat_length * sb->s_blocksize * 8 / sbi->fat_bits;
+}
+
 /*
  * Read the super block of an MS-DOS FS.
  */
@@ -1434,7 +1447,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat,
                sbi->dirty = b->fat16.state & FAT_STATE_DIRTY;
 
        /* check that FAT table does not overflow */
-       fat_clusters = sbi->fat_length * sb->s_blocksize * 8 / sbi->fat_bits;
+       fat_clusters = calc_fat_clusters(sb);
        total_clusters = min(total_clusters, fat_clusters - FAT_START_ENT);
        if (total_clusters > MAX_FAT(sb)) {
                if (!silent)
index 254df56..f3f783d 100644 (file)
@@ -180,6 +180,8 @@ u64 fuse_get_attr_version(struct fuse_conn *fc)
 static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
 {
        struct inode *inode;
+       struct dentry *parent;
+       struct fuse_conn *fc;
 
        inode = ACCESS_ONCE(entry->d_inode);
        if (inode && is_bad_inode(inode))
@@ -187,10 +189,8 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
        else if (fuse_dentry_time(entry) < get_jiffies_64()) {
                int err;
                struct fuse_entry_out outarg;
-               struct fuse_conn *fc;
                struct fuse_req *req;
                struct fuse_forget_link *forget;
-               struct dentry *parent;
                u64 attr_version;
 
                /* For negative dentries, always do a fresh lookup */
@@ -241,8 +241,14 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
                                       entry_attr_timeout(&outarg),
                                       attr_version);
                fuse_change_entry_timeout(entry, &outarg);
+       } else if (inode) {
+               fc = get_fuse_conn(inode);
+               if (fc->readdirplus_auto) {
+                       parent = dget_parent(entry);
+                       fuse_advise_use_readdirplus(parent->d_inode);
+                       dput(parent);
+               }
        }
-       fuse_advise_use_readdirplus(inode);
        return 1;
 }
 
index d1c9b85..e570081 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/compat.h>
 #include <linux/swap.h>
 #include <linux/aio.h>
+#include <linux/falloc.h>
 
 static const struct file_operations fuse_direct_io_file_operations;
 
@@ -1278,7 +1279,10 @@ ssize_t fuse_direct_io(struct fuse_io_priv *io, const struct iovec *iov,
 
        iov_iter_init(&ii, iov, nr_segs, count, 0);
 
-       req = fuse_get_req(fc, fuse_iter_npages(&ii));
+       if (io->async)
+               req = fuse_get_req_for_background(fc, fuse_iter_npages(&ii));
+       else
+               req = fuse_get_req(fc, fuse_iter_npages(&ii));
        if (IS_ERR(req))
                return PTR_ERR(req);
 
@@ -1314,7 +1318,11 @@ ssize_t fuse_direct_io(struct fuse_io_priv *io, const struct iovec *iov,
                        break;
                if (count) {
                        fuse_put_request(fc, req);
-                       req = fuse_get_req(fc, fuse_iter_npages(&ii));
+                       if (io->async)
+                               req = fuse_get_req_for_background(fc,
+                                       fuse_iter_npages(&ii));
+                       else
+                               req = fuse_get_req(fc, fuse_iter_npages(&ii));
                        if (IS_ERR(req))
                                break;
                }
@@ -2365,6 +2373,11 @@ static void fuse_do_truncate(struct file *file)
        fuse_do_setattr(inode, &attr, file);
 }
 
+static inline loff_t fuse_round_up(loff_t off)
+{
+       return round_up(off, FUSE_MAX_PAGES_PER_REQ << PAGE_SHIFT);
+}
+
 static ssize_t
 fuse_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
                        loff_t offset, unsigned long nr_segs)
@@ -2372,6 +2385,7 @@ fuse_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
        ssize_t ret = 0;
        struct file *file = iocb->ki_filp;
        struct fuse_file *ff = file->private_data;
+       bool async_dio = ff->fc->async_dio;
        loff_t pos = 0;
        struct inode *inode;
        loff_t i_size;
@@ -2383,10 +2397,10 @@ fuse_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
        i_size = i_size_read(inode);
 
        /* optimization for short read */
-       if (rw != WRITE && offset + count > i_size) {
+       if (async_dio && rw != WRITE && offset + count > i_size) {
                if (offset >= i_size)
                        return 0;
-               count = i_size - offset;
+               count = min_t(loff_t, count, fuse_round_up(i_size - offset));
        }
 
        io = kmalloc(sizeof(struct fuse_io_priv), GFP_KERNEL);
@@ -2404,7 +2418,7 @@ fuse_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
         * By default, we want to optimize all I/Os with async request
         * submission to the client filesystem if supported.
         */
-       io->async = ff->fc->async_dio;
+       io->async = async_dio;
        io->iocb = iocb;
 
        /*
@@ -2412,7 +2426,7 @@ fuse_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
         * to wait on real async I/O requests, so we must submit this request
         * synchronously.
         */
-       if (!is_sync_kiocb(iocb) && (offset + count > i_size))
+       if (!is_sync_kiocb(iocb) && (offset + count > i_size) && rw == WRITE)
                io->async = false;
 
        if (rw == WRITE)
@@ -2424,7 +2438,7 @@ fuse_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
                fuse_aio_complete(io, ret < 0 ? ret : 0, -1);
 
                /* we have a non-extending, async request, so return */
-               if (ret > 0 && !is_sync_kiocb(iocb))
+               if (!is_sync_kiocb(iocb))
                        return -EIOCBQUEUED;
 
                ret = wait_on_sync_kiocb(iocb);
@@ -2446,6 +2460,7 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
                                loff_t length)
 {
        struct fuse_file *ff = file->private_data;
+       struct inode *inode = file->f_inode;
        struct fuse_conn *fc = ff->fc;
        struct fuse_req *req;
        struct fuse_fallocate_in inarg = {
@@ -2459,9 +2474,16 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
        if (fc->no_fallocate)
                return -EOPNOTSUPP;
 
+       if (mode & FALLOC_FL_PUNCH_HOLE) {
+               mutex_lock(&inode->i_mutex);
+               fuse_set_nowrite(inode);
+       }
+
        req = fuse_get_req_nopages(fc);
-       if (IS_ERR(req))
-               return PTR_ERR(req);
+       if (IS_ERR(req)) {
+               err = PTR_ERR(req);
+               goto out;
+       }
 
        req->in.h.opcode = FUSE_FALLOCATE;
        req->in.h.nodeid = ff->nodeid;
@@ -2476,6 +2498,24 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
        }
        fuse_put_request(fc, req);
 
+       if (err)
+               goto out;
+
+       /* we could have extended the file */
+       if (!(mode & FALLOC_FL_KEEP_SIZE))
+               fuse_write_update_size(inode, offset + length);
+
+       if (mode & FALLOC_FL_PUNCH_HOLE)
+               truncate_pagecache_range(inode, offset, offset + length - 1);
+
+       fuse_invalidate_attr(inode);
+
+out:
+       if (mode & FALLOC_FL_PUNCH_HOLE) {
+               fuse_release_nowrite(inode);
+               mutex_unlock(&inode->i_mutex);
+       }
+
        return err;
 }
 
index 6201f81..9a0cdde 100644 (file)
@@ -867,10 +867,11 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
                                fc->dont_mask = 1;
                        if (arg->flags & FUSE_AUTO_INVAL_DATA)
                                fc->auto_inval_data = 1;
-                       if (arg->flags & FUSE_DO_READDIRPLUS)
+                       if (arg->flags & FUSE_DO_READDIRPLUS) {
                                fc->do_readdirplus = 1;
-                       if (arg->flags & FUSE_READDIRPLUS_AUTO)
-                               fc->readdirplus_auto = 1;
+                               if (arg->flags & FUSE_READDIRPLUS_AUTO)
+                                       fc->readdirplus_auto = 1;
+                       }
                        if (arg->flags & FUSE_ASYNC_DIO)
                                fc->async_dio = 1;
                } else {
index eb08c9e..5a376ab 100644 (file)
@@ -26,7 +26,7 @@ config GFS2_FS
 config GFS2_FS_LOCKING_DLM
        bool "GFS2 DLM locking"
        depends on (GFS2_FS!=n) && NET && INET && (IPV6 || IPV6=n) && \
-               HOTPLUG && DLM && CONFIGFS_FS && SYSFS
+               HOTPLUG && CONFIGFS_FS && SYSFS && (DLM=y || DLM=GFS2_FS)
        help
          Multiple node locking module for GFS2
 
index 1dc9a13..93b5809 100644 (file)
@@ -1286,17 +1286,26 @@ int gfs2_setattr_size(struct inode *inode, u64 newsize)
        if (ret)
                return ret;
 
+       ret = get_write_access(inode);
+       if (ret)
+               return ret;
+
        inode_dio_wait(inode);
 
        ret = gfs2_rs_alloc(GFS2_I(inode));
        if (ret)
-               return ret;
+               goto out;
 
        oldsize = inode->i_size;
-       if (newsize >= oldsize)
-               return do_grow(inode, newsize);
+       if (newsize >= oldsize) {
+               ret = do_grow(inode, newsize);
+               goto out;
+       }
 
-       return do_shrink(inode, oldsize, newsize);
+       ret = do_shrink(inode, oldsize, newsize);
+out:
+       put_write_access(inode);
+       return ret;
 }
 
 int gfs2_truncatei_resume(struct gfs2_inode *ip)
index c3e82bd..b631c90 100644 (file)
@@ -354,22 +354,31 @@ static __be64 *gfs2_dir_get_hash_table(struct gfs2_inode *ip)
                return ERR_PTR(-EIO);
        }
 
-       hc = kmalloc(hsize, GFP_NOFS);
-       ret = -ENOMEM;
+       hc = kmalloc(hsize, GFP_NOFS | __GFP_NOWARN);
+       if (hc == NULL)
+               hc = __vmalloc(hsize, GFP_NOFS, PAGE_KERNEL);
+
        if (hc == NULL)
                return ERR_PTR(-ENOMEM);
 
        ret = gfs2_dir_read_data(ip, hc, hsize);
        if (ret < 0) {
-               kfree(hc);
+               if (is_vmalloc_addr(hc))
+                       vfree(hc);
+               else
+                       kfree(hc);
                return ERR_PTR(ret);
        }
 
        spin_lock(&inode->i_lock);
-       if (ip->i_hash_cache)
-               kfree(hc);
-       else
+       if (ip->i_hash_cache) {
+               if (is_vmalloc_addr(hc))
+                       vfree(hc);
+               else
+                       kfree(hc);
+       } else {
                ip->i_hash_cache = hc;
+       }
        spin_unlock(&inode->i_lock);
 
        return ip->i_hash_cache;
@@ -385,7 +394,10 @@ void gfs2_dir_hash_inval(struct gfs2_inode *ip)
 {
        __be64 *hc = ip->i_hash_cache;
        ip->i_hash_cache = NULL;
-       kfree(hc);
+       if (is_vmalloc_addr(hc))
+               vfree(hc);
+       else
+               kfree(hc);
 }
 
 static inline int gfs2_dirent_sentinel(const struct gfs2_dirent *dent)
@@ -1113,7 +1125,10 @@ static int dir_double_exhash(struct gfs2_inode *dip)
        if (IS_ERR(hc))
                return PTR_ERR(hc);
 
-       h = hc2 = kmalloc(hsize_bytes * 2, GFP_NOFS);
+       h = hc2 = kmalloc(hsize_bytes * 2, GFP_NOFS | __GFP_NOWARN);
+       if (hc2 == NULL)
+               hc2 = __vmalloc(hsize_bytes * 2, GFP_NOFS, PAGE_KERNEL);
+
        if (!hc2)
                return -ENOMEM;
 
@@ -1145,7 +1160,10 @@ fail:
        gfs2_dinode_out(dip, dibh->b_data);
        brelse(dibh);
 out_kfree:
-       kfree(hc2);
+       if (is_vmalloc_addr(hc2))
+               vfree(hc2);
+       else
+               kfree(hc2);
        return error;
 }
 
@@ -1846,6 +1864,8 @@ static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len,
        memset(&rlist, 0, sizeof(struct gfs2_rgrp_list));
 
        ht = kzalloc(size, GFP_NOFS);
+       if (ht == NULL)
+               ht = vzalloc(size);
        if (!ht)
                return -ENOMEM;
 
@@ -1933,7 +1953,10 @@ out_rlist:
        gfs2_rlist_free(&rlist);
        gfs2_quota_unhold(dip);
 out:
-       kfree(ht);
+       if (is_vmalloc_addr(ht))
+               vfree(ht);
+       else
+               kfree(ht);
        return error;
 }
 
index acd1676..ad0dc38 100644 (file)
@@ -402,16 +402,20 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
        /* Update file times before taking page lock */
        file_update_time(vma->vm_file);
 
+       ret = get_write_access(inode);
+       if (ret)
+               goto out;
+
        ret = gfs2_rs_alloc(ip);
        if (ret)
-               return ret;
+               goto out_write_access;
 
        gfs2_size_hint(vma->vm_file, pos, PAGE_CACHE_SIZE);
 
        gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
        ret = gfs2_glock_nq(&gh);
        if (ret)
-               goto out;
+               goto out_uninit;
 
        set_bit(GLF_DIRTY, &ip->i_gl->gl_flags);
        set_bit(GIF_SW_PAGED, &ip->i_flags);
@@ -480,12 +484,15 @@ out_quota_unlock:
        gfs2_quota_unlock(ip);
 out_unlock:
        gfs2_glock_dq(&gh);
-out:
+out_uninit:
        gfs2_holder_uninit(&gh);
        if (ret == 0) {
                set_page_dirty(page);
                wait_for_stable_page(page);
        }
+out_write_access:
+       put_write_access(inode);
+out:
        sb_end_pagefault(inode->i_sb);
        return block_page_mkwrite_return(ret);
 }
@@ -594,10 +601,10 @@ static int gfs2_release(struct inode *inode, struct file *file)
        kfree(file->private_data);
        file->private_data = NULL;
 
-       if ((file->f_mode & FMODE_WRITE) &&
-           (atomic_read(&inode->i_writecount) == 1))
-               gfs2_rs_delete(ip);
+       if (!(file->f_mode & FMODE_WRITE))
+               return 0;
 
+       gfs2_rs_delete(ip);
        return 0;
 }
 
index 8833a4f..62b484e 100644 (file)
@@ -189,6 +189,7 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type,
        return inode;
 
 fail_refresh:
+       ip->i_iopen_gh.gh_flags |= GL_NOCACHE;
        ip->i_iopen_gh.gh_gl->gl_object = NULL;
        gfs2_glock_dq_uninit(&ip->i_iopen_gh);
 fail_iopen:
index c5fa758..6c33d7b 100644 (file)
@@ -212,7 +212,7 @@ static void gfs2_end_log_write(struct bio *bio, int error)
                fs_err(sdp, "Error %d writing to log\n", error);
        }
 
-       bio_for_each_segment(bvec, bio, i) {
+       bio_for_each_segment_all(bvec, bio, i) {
                page = bvec->bv_page;
                if (page_has_buffers(page))
                        gfs2_end_log_write_bh(sdp, bvec, error);
@@ -419,7 +419,9 @@ static void gfs2_before_commit(struct gfs2_sbd *sdp, unsigned int limit,
                if (total > limit)
                        num = limit;
                gfs2_log_unlock(sdp);
-               page = gfs2_get_log_desc(sdp, GFS2_LOG_DESC_METADATA, num + 1, num);
+               page = gfs2_get_log_desc(sdp,
+                                        is_databuf ? GFS2_LOG_DESC_JDATA :
+                                        GFS2_LOG_DESC_METADATA, num + 1, num);
                ld = page_address(page);
                gfs2_log_lock(sdp);
                ptr = (__be64 *)(ld + 1);
index c7c840e..c253b13 100644 (file)
@@ -121,7 +121,7 @@ static u64 qd2index(struct gfs2_quota_data *qd)
 {
        struct kqid qid = qd->qd_id;
        return (2 * (u64)from_kqid(&init_user_ns, qid)) +
-               (qid.type == USRQUOTA) ? 0 : 1;
+               ((qid.type == USRQUOTA) ? 0 : 1);
 }
 
 static u64 qd2offset(struct gfs2_quota_data *qd)
@@ -721,7 +721,7 @@ get_a_page:
                        goto unlock_out;
        }
 
-       gfs2_trans_add_meta(ip->i_gl, bh);
+       gfs2_trans_add_data(ip->i_gl, bh);
 
        kaddr = kmap_atomic(page);
        if (offset + sizeof(struct gfs2_quota) > PAGE_CACHE_SIZE)
index 0c5a575..9809156 100644 (file)
@@ -638,8 +638,10 @@ void gfs2_rs_deltree(struct gfs2_blkreserv *rs)
  */
 void gfs2_rs_delete(struct gfs2_inode *ip)
 {
+       struct inode *inode = &ip->i_inode;
+
        down_write(&ip->i_rw_mutex);
-       if (ip->i_res) {
+       if (ip->i_res && atomic_read(&inode->i_writecount) <= 1) {
                gfs2_rs_deltree(ip->i_res);
                BUG_ON(ip->i_res->rs_free);
                kmem_cache_free(gfs2_rsrv_cachep, ip->i_res);
@@ -1401,9 +1403,14 @@ static void rg_mblk_search(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip,
        u32 extlen;
        u32 free_blocks = rgd->rd_free_clone - rgd->rd_reserved;
        int ret;
+       struct inode *inode = &ip->i_inode;
 
-       extlen = max_t(u32, atomic_read(&rs->rs_sizehint), requested);
-       extlen = clamp(extlen, RGRP_RSRV_MINBLKS, free_blocks);
+       if (S_ISDIR(inode->i_mode))
+               extlen = 1;
+       else {
+               extlen = max_t(u32, atomic_read(&rs->rs_sizehint), requested);
+               extlen = clamp(extlen, RGRP_RSRV_MINBLKS, free_blocks);
+       }
        if ((rgd->rd_free_clone < rgd->rd_reserved) || (free_blocks < extlen))
                return;
 
index 917c8e1..e5639de 100644 (file)
@@ -1444,6 +1444,7 @@ static void gfs2_evict_inode(struct inode *inode)
        /* Must not read inode block until block type has been verified */
        error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_SKIP, &gh);
        if (unlikely(error)) {
+               ip->i_iopen_gh.gh_flags |= GL_NOCACHE;
                gfs2_glock_dq_uninit(&ip->i_iopen_gh);
                goto out;
        }
@@ -1514,8 +1515,10 @@ out_unlock:
        if (gfs2_rs_active(ip->i_res))
                gfs2_rs_deltree(ip->i_res);
 
-       if (test_bit(HIF_HOLDER, &ip->i_iopen_gh.gh_iflags))
+       if (test_bit(HIF_HOLDER, &ip->i_iopen_gh.gh_iflags)) {
+               ip->i_iopen_gh.gh_flags |= GL_NOCACHE;
                gfs2_glock_dq(&ip->i_iopen_gh);
+       }
        gfs2_holder_uninit(&ip->i_iopen_gh);
        gfs2_glock_dq_uninit(&gh);
        if (error && error != GLR_TRYFAILED && error != -EROFS)
@@ -1534,6 +1537,7 @@ out:
        ip->i_gl = NULL;
        if (ip->i_iopen_gh.gh_gl) {
                ip->i_iopen_gh.gh_gl->gl_object = NULL;
+               ip->i_iopen_gh.gh_flags |= GL_NOCACHE;
                gfs2_glock_dq_uninit(&ip->i_iopen_gh);
        }
 }
index f3b1a15..d3fa6bd 100644 (file)
@@ -415,7 +415,11 @@ struct hfs_bnode *hfs_bnode_create(struct hfs_btree *tree, u32 num)
        spin_lock(&tree->hash_lock);
        node = hfs_bnode_findhash(tree, num);
        spin_unlock(&tree->hash_lock);
-       BUG_ON(node);
+       if (node) {
+               pr_crit("new node %u already hashed?\n", num);
+               WARN_ON(1);
+               return node;
+       }
        node = __hfs_bnode_create(tree, num);
        if (!node)
                return ERR_PTR(-ENOMEM);
index 546f6d3..834ac13 100644 (file)
@@ -33,25 +33,27 @@ static loff_t hpfs_dir_lseek(struct file *filp, loff_t off, int whence)
        if (whence == SEEK_DATA || whence == SEEK_HOLE)
                return -EINVAL;
 
+       mutex_lock(&i->i_mutex);
        hpfs_lock(s);
 
        /*printk("dir lseek\n");*/
        if (new_off == 0 || new_off == 1 || new_off == 11 || new_off == 12 || new_off == 13) goto ok;
-       mutex_lock(&i->i_mutex);
        pos = ((loff_t) hpfs_de_as_down_as_possible(s, hpfs_inode->i_dno) << 4) + 1;
        while (pos != new_off) {
                if (map_pos_dirent(i, &pos, &qbh)) hpfs_brelse4(&qbh);
                else goto fail;
                if (pos == 12) goto fail;
        }
-       mutex_unlock(&i->i_mutex);
+       hpfs_add_pos(i, &filp->f_pos);
 ok:
+       filp->f_pos = new_off;
        hpfs_unlock(s);
-       return filp->f_pos = new_off;
-fail:
        mutex_unlock(&i->i_mutex);
+       return new_off;
+fail:
        /*printk("illegal lseek: %016llx\n", new_off);*/
        hpfs_unlock(s);
+       mutex_unlock(&i->i_mutex);
        return -ESPIPE;
 }
 
index 3027f4d..e4ba5fe 100644 (file)
@@ -109,10 +109,14 @@ static void hpfs_write_failed(struct address_space *mapping, loff_t to)
 {
        struct inode *inode = mapping->host;
 
+       hpfs_lock(inode->i_sb);
+
        if (to > inode->i_size) {
                truncate_pagecache(inode, to, inode->i_size);
                hpfs_truncate(inode);
        }
+
+       hpfs_unlock(inode->i_sb);
 }
 
 static int hpfs_write_begin(struct file *file, struct address_space *mapping,
index c57499d..360d27c 100644 (file)
@@ -2009,7 +2009,13 @@ static int lbmRead(struct jfs_log * log, int pn, struct lbuf ** bpp)
 
        bio->bi_end_io = lbmIODone;
        bio->bi_private = bp;
-       submit_bio(READ_SYNC, bio);
+       /*check if journaling to disk has been disabled*/
+       if (log->no_integrity) {
+               bio->bi_size = 0;
+               lbmIODone(bio, 0);
+       } else {
+               submit_bio(READ_SYNC, bio);
+       }
 
        wait_event(bp->l_ioevent, (bp->l_flag != lbmREAD));
 
index 2003e83..788e0a9 100644 (file)
@@ -611,11 +611,28 @@ static int jfs_freeze(struct super_block *sb)
 {
        struct jfs_sb_info *sbi = JFS_SBI(sb);
        struct jfs_log *log = sbi->log;
+       int rc = 0;
 
        if (!(sb->s_flags & MS_RDONLY)) {
                txQuiesce(sb);
-               lmLogShutdown(log);
-               updateSuper(sb, FM_CLEAN);
+               rc = lmLogShutdown(log);
+               if (rc) {
+                       jfs_error(sb, "jfs_freeze: lmLogShutdown failed");
+
+                       /* let operations fail rather than hang */
+                       txResume(sb);
+
+                       return rc;
+               }
+               rc = updateSuper(sb, FM_CLEAN);
+               if (rc) {
+                       jfs_err("jfs_freeze: updateSuper failed\n");
+                       /*
+                        * Don't fail here. Everything succeeded except
+                        * marking the superblock clean, so there's really
+                        * no harm in leaving it frozen for now.
+                        */
+               }
        }
        return 0;
 }
@@ -627,13 +644,18 @@ static int jfs_unfreeze(struct super_block *sb)
        int rc = 0;
 
        if (!(sb->s_flags & MS_RDONLY)) {
-               updateSuper(sb, FM_MOUNT);
-               if ((rc = lmLogInit(log)))
-                       jfs_err("jfs_unlock failed with return code %d", rc);
-               else
-                       txResume(sb);
+               rc = updateSuper(sb, FM_MOUNT);
+               if (rc) {
+                       jfs_error(sb, "jfs_unfreeze: updateSuper failed");
+                       goto out;
+               }
+               rc = lmLogInit(log);
+               if (rc)
+                       jfs_error(sb, "jfs_unfreeze: lmLogInit failed");
+out:
+               txResume(sb);
        }
-       return 0;
+       return rc;
 }
 
 static struct dentry *jfs_do_mount(struct file_system_type *fs_type,
index 57ae9c8..85e40d1 100644 (file)
@@ -2740,7 +2740,7 @@ static int do_last(struct nameidata *nd, struct path *path,
                if (error)
                        return error;
 
-               audit_inode(name, dir, 0);
+               audit_inode(name, dir, LOOKUP_PARENT);
                error = -EISDIR;
                /* trailing slashes? */
                if (nd->last.name[nd->last.len])
index a13d26e..0bc2768 100644 (file)
@@ -414,7 +414,7 @@ __be32 nfs4_callback_sequence(struct cb_sequenceargs *args,
 
        spin_lock(&tbl->slot_tbl_lock);
        /* state manager is resetting the session */
-       if (test_bit(NFS4_SESSION_DRAINING, &clp->cl_session->session_state)) {
+       if (test_bit(NFS4_SLOT_TBL_DRAINING, &tbl->slot_tbl_state)) {
                spin_unlock(&tbl->slot_tbl_lock);
                status = htonl(NFS4ERR_DELAY);
                /* Return NFS4ERR_BADSESSION if we're draining the session
index 59461c9..a35582c 100644 (file)
@@ -763,7 +763,7 @@ static void nfs4_callback_free_slot(struct nfs4_session *session)
         * A single slot, so highest used slotid is either 0 or -1
         */
        tbl->highest_used_slotid = NFS4_NO_SLOT;
-       nfs4_session_drain_complete(session, tbl);
+       nfs4_slot_tbl_drain_complete(tbl);
        spin_unlock(&tbl->slot_tbl_lock);
 }
 
index 947b0c9..4cbad5d 100644 (file)
@@ -203,7 +203,7 @@ struct nfs_client *nfs4_init_client(struct nfs_client *clp,
        __set_bit(NFS_CS_DISCRTRY, &clp->cl_flags);
        error = nfs_create_rpc_client(clp, timeparms, RPC_AUTH_GSS_KRB5I);
        if (error == -EINVAL)
-               error = nfs_create_rpc_client(clp, timeparms, RPC_AUTH_NULL);
+               error = nfs_create_rpc_client(clp, timeparms, RPC_AUTH_UNIX);
        if (error < 0)
                goto error;
 
index 8fbc100..d7ba561 100644 (file)
@@ -572,7 +572,7 @@ int nfs41_setup_sequence(struct nfs4_session *session,
        task->tk_timeout = 0;
 
        spin_lock(&tbl->slot_tbl_lock);
-       if (test_bit(NFS4_SESSION_DRAINING, &session->session_state) &&
+       if (test_bit(NFS4_SLOT_TBL_DRAINING, &tbl->slot_tbl_state) &&
            !args->sa_privileged) {
                /* The state manager will wait until the slot table is empty */
                dprintk("%s session is draining\n", __func__);
@@ -1078,7 +1078,7 @@ static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata)
        struct nfs4_state *state = opendata->state;
        struct nfs_inode *nfsi = NFS_I(state->inode);
        struct nfs_delegation *delegation;
-       int open_mode = opendata->o_arg.open_flags & (O_EXCL|O_TRUNC);
+       int open_mode = opendata->o_arg.open_flags;
        fmode_t fmode = opendata->o_arg.fmode;
        nfs4_stateid stateid;
        int ret = -EAGAIN;
index ebda5f4..c4e225e 100644 (file)
@@ -73,7 +73,7 @@ void nfs4_free_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *slot)
                        tbl->highest_used_slotid = new_max;
                else {
                        tbl->highest_used_slotid = NFS4_NO_SLOT;
-                       nfs4_session_drain_complete(tbl->session, tbl);
+                       nfs4_slot_tbl_drain_complete(tbl);
                }
        }
        dprintk("%s: slotid %u highest_used_slotid %d\n", __func__,
@@ -226,7 +226,7 @@ static bool nfs41_assign_slot(struct rpc_task *task, void *pslot)
        struct nfs4_slot *slot = pslot;
        struct nfs4_slot_table *tbl = slot->table;
 
-       if (nfs4_session_draining(tbl->session) && !args->sa_privileged)
+       if (nfs4_slot_tbl_draining(tbl) && !args->sa_privileged)
                return false;
        slot->generation = tbl->generation;
        args->sa_slot = slot;
index 6f3cb39..ff7d9f0 100644 (file)
@@ -25,6 +25,10 @@ struct nfs4_slot {
 };
 
 /* Sessions */
+enum nfs4_slot_tbl_state {
+       NFS4_SLOT_TBL_DRAINING,
+};
+
 #define SLOT_TABLE_SZ DIV_ROUND_UP(NFS4_MAX_SLOT_TABLE, 8*sizeof(long))
 struct nfs4_slot_table {
        struct nfs4_session *session;           /* Parent session */
@@ -43,6 +47,7 @@ struct nfs4_slot_table {
        unsigned long   generation;             /* Generation counter for
                                                   target_highest_slotid */
        struct completion complete;
+       unsigned long   slot_tbl_state;
 };
 
 /*
@@ -68,7 +73,6 @@ struct nfs4_session {
 
 enum nfs4_session_state {
        NFS4_SESSION_INITING,
-       NFS4_SESSION_DRAINING,
 };
 
 #if defined(CONFIG_NFS_V4_1)
@@ -88,12 +92,11 @@ extern void nfs4_destroy_session(struct nfs4_session *session);
 extern int nfs4_init_session(struct nfs_server *server);
 extern int nfs4_init_ds_session(struct nfs_client *, unsigned long);
 
-extern void nfs4_session_drain_complete(struct nfs4_session *session,
-               struct nfs4_slot_table *tbl);
+extern void nfs4_slot_tbl_drain_complete(struct nfs4_slot_table *tbl);
 
-static inline bool nfs4_session_draining(struct nfs4_session *session)
+static inline bool nfs4_slot_tbl_draining(struct nfs4_slot_table *tbl)
 {
-       return !!test_bit(NFS4_SESSION_DRAINING, &session->session_state);
+       return !!test_bit(NFS4_SLOT_TBL_DRAINING, &tbl->slot_tbl_state);
 }
 
 bool nfs41_wake_and_assign_slot(struct nfs4_slot_table *tbl,
index 300d17d..1fab140 100644 (file)
@@ -241,7 +241,7 @@ static void nfs4_end_drain_session(struct nfs_client *clp)
        if (ses == NULL)
                return;
        tbl = &ses->fc_slot_table;
-       if (test_and_clear_bit(NFS4_SESSION_DRAINING, &ses->session_state)) {
+       if (test_and_clear_bit(NFS4_SLOT_TBL_DRAINING, &tbl->slot_tbl_state)) {
                spin_lock(&tbl->slot_tbl_lock);
                nfs41_wake_slot_table(tbl);
                spin_unlock(&tbl->slot_tbl_lock);
@@ -251,15 +251,15 @@ static void nfs4_end_drain_session(struct nfs_client *clp)
 /*
  * Signal state manager thread if session fore channel is drained
  */
-void nfs4_session_drain_complete(struct nfs4_session *session,
-               struct nfs4_slot_table *tbl)
+void nfs4_slot_tbl_drain_complete(struct nfs4_slot_table *tbl)
 {
-       if (nfs4_session_draining(session))
+       if (nfs4_slot_tbl_draining(tbl))
                complete(&tbl->complete);
 }
 
-static int nfs4_wait_on_slot_tbl(struct nfs4_slot_table *tbl)
+static int nfs4_drain_slot_tbl(struct nfs4_slot_table *tbl)
 {
+       set_bit(NFS4_SLOT_TBL_DRAINING, &tbl->slot_tbl_state);
        spin_lock(&tbl->slot_tbl_lock);
        if (tbl->highest_used_slotid != NFS4_NO_SLOT) {
                INIT_COMPLETION(tbl->complete);
@@ -275,13 +275,12 @@ static int nfs4_begin_drain_session(struct nfs_client *clp)
        struct nfs4_session *ses = clp->cl_session;
        int ret = 0;
 
-       set_bit(NFS4_SESSION_DRAINING, &ses->session_state);
        /* back channel */
-       ret = nfs4_wait_on_slot_tbl(&ses->bc_slot_table);
+       ret = nfs4_drain_slot_tbl(&ses->bc_slot_table);
        if (ret)
                return ret;
        /* fore channel */
-       return nfs4_wait_on_slot_tbl(&ses->fc_slot_table);
+       return nfs4_drain_slot_tbl(&ses->fc_slot_table);
 }
 
 static void nfs41_finish_session_reset(struct nfs_client *clp)
index a366107..2d7525f 100644 (file)
@@ -1942,6 +1942,7 @@ static int nfs23_validate_mount_data(void *options,
                args->namlen            = data->namlen;
                args->bsize             = data->bsize;
 
+               args->auth_flavors[0] = RPC_AUTH_UNIX;
                if (data->flags & NFS_MOUNT_SECFLAVOUR)
                        args->auth_flavors[0] = data->pseudoflavor;
                if (!args->nfs_server.hostname)
@@ -2637,6 +2638,7 @@ static int nfs4_validate_mount_data(void *options,
                        goto out_no_address;
                args->nfs_server.port = ntohs(((struct sockaddr_in *)sap)->sin_port);
 
+               args->auth_flavors[0] = RPC_AUTH_UNIX;
                if (data->auth_flavourlen) {
                        if (data->auth_flavourlen > 1)
                                goto out_inval_auth;
index 8ae5abf..27d74a2 100644 (file)
@@ -279,6 +279,7 @@ do_open_fhandle(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, str
 {
        struct svc_fh *current_fh = &cstate->current_fh;
        __be32 status;
+       int accmode = 0;
 
        /* We don't know the target directory, and therefore can not
        * set the change info
@@ -290,9 +291,19 @@ do_open_fhandle(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, str
 
        open->op_truncate = (open->op_iattr.ia_valid & ATTR_SIZE) &&
                (open->op_iattr.ia_size == 0);
+       /*
+        * In the delegation case, the client is telling us about an
+        * open that it *already* performed locally, some time ago.  We
+        * should let it succeed now if possible.
+        *
+        * In the case of a CLAIM_FH open, on the other hand, the client
+        * may be counting on us to enforce permissions (the Linux 4.1
+        * client uses this for normal opens, for example).
+        */
+       if (open->op_claim_type == NFS4_OPEN_CLAIM_DELEG_CUR_FH)
+               accmode = NFSD_MAY_OWNER_OVERRIDE;
 
-       status = do_open_permission(rqstp, current_fh, open,
-                                   NFSD_MAY_OWNER_OVERRIDE);
+       status = do_open_permission(rqstp, current_fh, open, accmode);
 
        return status;
 }
index 899ca26..4e9a21d 100644 (file)
@@ -146,7 +146,7 @@ out_no_tfm:
  * then disable recovery tracking.
  */
 static void
-legacy_recdir_name_error(int error)
+legacy_recdir_name_error(struct nfs4_client *clp, int error)
 {
        printk(KERN_ERR "NFSD: unable to generate recoverydir "
                        "name (%d).\n", error);
@@ -159,9 +159,7 @@ legacy_recdir_name_error(int error)
        if (error == -ENOENT) {
                printk(KERN_ERR "NFSD: disabling legacy clientid tracking. "
                        "Reboot recovery will not function correctly!\n");
-
-               /* the argument is ignored by the legacy exit function */
-               nfsd4_client_tracking_exit(NULL);
+               nfsd4_client_tracking_exit(clp->net);
        }
 }
 
@@ -184,7 +182,7 @@ nfsd4_create_clid_dir(struct nfs4_client *clp)
 
        status = nfs4_make_rec_clidname(dname, &clp->cl_name);
        if (status)
-               return legacy_recdir_name_error(status);
+               return legacy_recdir_name_error(clp, status);
 
        status = nfs4_save_creds(&original_cred);
        if (status < 0)
@@ -341,7 +339,7 @@ nfsd4_remove_clid_dir(struct nfs4_client *clp)
 
        status = nfs4_make_rec_clidname(dname, &clp->cl_name);
        if (status)
-               return legacy_recdir_name_error(status);
+               return legacy_recdir_name_error(clp, status);
 
        status = mnt_want_write_file(nn->rec_file);
        if (status)
@@ -601,7 +599,7 @@ nfsd4_check_legacy_client(struct nfs4_client *clp)
 
        status = nfs4_make_rec_clidname(dname, &clp->cl_name);
        if (status) {
-               legacy_recdir_name_error(status);
+               legacy_recdir_name_error(clp, status);
                return status;
        }
 
index 689fb60..bccfec8 100644 (file)
@@ -219,13 +219,32 @@ static int nilfs_writepage(struct page *page, struct writeback_control *wbc)
 
 static int nilfs_set_page_dirty(struct page *page)
 {
-       int ret = __set_page_dirty_buffers(page);
+       int ret = __set_page_dirty_nobuffers(page);
 
-       if (ret) {
+       if (page_has_buffers(page)) {
                struct inode *inode = page->mapping->host;
-               unsigned nr_dirty = 1 << (PAGE_SHIFT - inode->i_blkbits);
+               unsigned nr_dirty = 0;
+               struct buffer_head *bh, *head;
 
-               nilfs_set_file_dirty(inode, nr_dirty);
+               /*
+                * This page is locked by callers, and no other thread
+                * concurrently marks its buffers dirty since they are
+                * only dirtied through routines in fs/buffer.c in
+                * which call sites of mark_buffer_dirty are protected
+                * by page lock.
+                */
+               bh = head = page_buffers(page);
+               do {
+                       /* Do not mark hole blocks dirty */
+                       if (buffer_dirty(bh) || !buffer_mapped(bh))
+                               continue;
+
+                       set_buffer_dirty(bh);
+                       nr_dirty++;
+               } while (bh = bh->b_this_page, bh != head);
+
+               if (nr_dirty)
+                       nilfs_set_file_dirty(inode, nr_dirty);
        }
        return ret;
 }
index d0be29f..6c80083 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/slab.h>
 #include <linux/types.h>
 #include <linux/uaccess.h>
+#include <linux/compat.h>
 
 #include <asm/ioctls.h>
 
@@ -857,6 +858,22 @@ fput_and_out:
        return ret;
 }
 
+#ifdef CONFIG_COMPAT
+COMPAT_SYSCALL_DEFINE6(fanotify_mark,
+                               int, fanotify_fd, unsigned int, flags,
+                               __u32, mask0, __u32, mask1, int, dfd,
+                               const char  __user *, pathname)
+{
+       return sys_fanotify_mark(fanotify_fd, flags,
+#ifdef __BIG_ENDIAN
+                               ((__u64)mask1 << 32) | mask0,
+#else
+                               ((__u64)mask0 << 32) | mask1,
+#endif
+                                dfd, pathname);
+}
+#endif
+
 /*
  * fanotify_user_setup - Our initialization function.  Note that we cannot return
  * error because we have compiled-in VFS hooks.  So an (unlikely) failure here
index b3fdd1a..e68588e 100644 (file)
@@ -1408,6 +1408,7 @@ int dlm_mig_lockres_handler(struct o2net_msg *msg, u32 len, void *data,
                                     mres->lockname_len, mres->lockname);
                                ret = -EFAULT;
                                spin_unlock(&res->spinlock);
+                               dlm_lockres_put(res);
                                goto leave;
                        }
                        res->state |= DLM_LOCK_RES_MIGRATING;
index 1c39efb..2487116 100644 (file)
@@ -790,7 +790,7 @@ int ocfs2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
                                                 &hole_size, &rec, &is_last);
                if (ret) {
                        mlog_errno(ret);
-                       goto out;
+                       goto out_unlock;
                }
 
                if (rec.e_blkno == 0ULL) {
index 8a7509f..ff54014 100644 (file)
@@ -2288,7 +2288,7 @@ relock:
                ret = ocfs2_inode_lock(inode, NULL, 1);
                if (ret < 0) {
                        mlog_errno(ret);
-                       goto out_sems;
+                       goto out;
                }
 
                ocfs2_inode_unlock(inode, 1);
index 04ee1b5..b4a5cdf 100644 (file)
@@ -947,7 +947,7 @@ leave:
        ocfs2_free_dir_lookup_result(&orphan_insert);
        ocfs2_free_dir_lookup_result(&lookup);
 
-       if (status)
+       if (status && (status != -ENOTEMPTY))
                mlog_errno(status);
 
        return status;
@@ -2216,7 +2216,7 @@ out:
 
        brelse(orphan_dir_bh);
 
-       return 0;
+       return ret;
 }
 
 int ocfs2_create_inode_in_orphan(struct inode *dir,
index 3d2a714..9af0df1 100644 (file)
@@ -83,7 +83,8 @@ static int do_make_slave(struct mount *mnt)
                if (peer_mnt == mnt)
                        peer_mnt = NULL;
        }
-       if (IS_MNT_SHARED(mnt) && list_empty(&mnt->mnt_share))
+       if (mnt->mnt_group_id && IS_MNT_SHARED(mnt) &&
+           list_empty(&mnt->mnt_share))
                mnt_release_group_id(mnt);
 
        list_del_init(&mnt->mnt_share);
index dd51e50..c3834da 100644 (file)
@@ -2118,6 +2118,7 @@ static int show_timer(struct seq_file *m, void *v)
                nstr[notify & ~SIGEV_THREAD_ID],
                (notify & SIGEV_THREAD_ID) ? "tid" : "pid",
                pid_nr_ns(timer->it_pid, tp->ns));
+       seq_printf(m, "ClockID: %d\n", timer->it_clock);
 
        return 0;
 }
index bd4b5a7..bdfabda 100644 (file)
@@ -21,12 +21,12 @@ extern wait_queue_head_t log_wait;
 
 static int kmsg_open(struct inode * inode, struct file * file)
 {
-       return do_syslog(SYSLOG_ACTION_OPEN, NULL, 0, SYSLOG_FROM_FILE);
+       return do_syslog(SYSLOG_ACTION_OPEN, NULL, 0, SYSLOG_FROM_PROC);
 }
 
 static int kmsg_release(struct inode * inode, struct file * file)
 {
-       (void) do_syslog(SYSLOG_ACTION_CLOSE, NULL, 0, SYSLOG_FROM_FILE);
+       (void) do_syslog(SYSLOG_ACTION_CLOSE, NULL, 0, SYSLOG_FROM_PROC);
        return 0;
 }
 
@@ -34,15 +34,15 @@ static ssize_t kmsg_read(struct file *file, char __user *buf,
                         size_t count, loff_t *ppos)
 {
        if ((file->f_flags & O_NONBLOCK) &&
-           !do_syslog(SYSLOG_ACTION_SIZE_UNREAD, NULL, 0, SYSLOG_FROM_FILE))
+           !do_syslog(SYSLOG_ACTION_SIZE_UNREAD, NULL, 0, SYSLOG_FROM_PROC))
                return -EAGAIN;
-       return do_syslog(SYSLOG_ACTION_READ, buf, count, SYSLOG_FROM_FILE);
+       return do_syslog(SYSLOG_ACTION_READ, buf, count, SYSLOG_FROM_PROC);
 }
 
 static unsigned int kmsg_poll(struct file *file, poll_table *wait)
 {
        poll_wait(file, &log_wait, wait);
-       if (do_syslog(SYSLOG_ACTION_SIZE_UNREAD, NULL, 0, SYSLOG_FROM_FILE))
+       if (do_syslog(SYSLOG_ACTION_SIZE_UNREAD, NULL, 0, SYSLOG_FROM_PROC))
                return POLLIN | POLLRDNORM;
        return 0;
 }
index 8798d06..afa6be6 100644 (file)
@@ -120,7 +120,7 @@ static int qnx6_readdir(struct file *filp, void *dirent, filldir_t filldir)
        struct inode *inode = file_inode(filp);
        struct super_block *s = inode->i_sb;
        struct qnx6_sb_info *sbi = QNX6_SB(s);
-       loff_t pos = filp->f_pos & (QNX6_DIR_ENTRY_SIZE - 1);
+       loff_t pos = filp->f_pos & ~(QNX6_DIR_ENTRY_SIZE - 1);
        unsigned long npages = dir_pages(inode);
        unsigned long n = pos >> PAGE_CACHE_SHIFT;
        unsigned start = (pos & ~PAGE_CACHE_MASK) / QNX6_DIR_ENTRY_SIZE;
index 66c53b6..6c2d136 100644 (file)
@@ -204,6 +204,8 @@ int reiserfs_readdir_dentry(struct dentry *dentry, void *dirent,
                                next_pos = deh_offset(deh) + 1;
 
                                if (item_moved(&tmp_ih, &path_to_entry)) {
+                                       set_cpu_key_k_offset(&pos_key,
+                                                            next_pos);
                                        goto research;
                                }
                        }       /* for */
index 77d6d47..f844533 100644 (file)
@@ -1811,11 +1811,16 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
                                  TYPE_STAT_DATA, SD_SIZE, MAX_US_INT);
        memcpy(INODE_PKEY(inode), &(ih.ih_key), KEY_SIZE);
        args.dirid = le32_to_cpu(ih.ih_key.k_dir_id);
-       if (insert_inode_locked4(inode, args.objectid,
-                            reiserfs_find_actor, &args) < 0) {
+
+       reiserfs_write_unlock(inode->i_sb);
+       err = insert_inode_locked4(inode, args.objectid,
+                            reiserfs_find_actor, &args);
+       reiserfs_write_lock(inode->i_sb);
+       if (err) {
                err = -EINVAL;
                goto out_bad_inode;
        }
+
        if (old_format_only(sb))
                /* not a perfect generation count, as object ids can be reused, but
                 ** this is as good as reiserfs can do right now.
index 4cce1d9..821bcf7 100644 (file)
@@ -318,7 +318,19 @@ static int delete_one_xattr(struct dentry *dentry, void *data)
 static int chown_one_xattr(struct dentry *dentry, void *data)
 {
        struct iattr *attrs = data;
-       return reiserfs_setattr(dentry, attrs);
+       int ia_valid = attrs->ia_valid;
+       int err;
+
+       /*
+        * We only want the ownership bits. Otherwise, we'll do
+        * things like change a directory to a regular file if
+        * ATTR_MODE is set.
+        */
+       attrs->ia_valid &= (ATTR_UID|ATTR_GID);
+       err = reiserfs_setattr(dentry, attrs);
+       attrs->ia_valid = ia_valid;
+
+       return err;
 }
 
 /* No i_mutex, but the inode is unconnected. */
index d7c01ef..6c8767f 100644 (file)
@@ -443,6 +443,9 @@ int reiserfs_acl_chmod(struct inode *inode)
        int depth;
        int error;
 
+       if (IS_PRIVATE(inode))
+               return 0;
+
        if (S_ISLNK(inode->i_mode))
                return -EOPNOTSUPP;
 
index 1d32f1d..306d883 100644 (file)
@@ -21,6 +21,8 @@
 #include "xfs_bmap_btree.h"
 #include "xfs_inode.h"
 #include "xfs_vnodeops.h"
+#include "xfs_sb.h"
+#include "xfs_mount.h"
 #include "xfs_trace.h"
 #include <linux/slab.h>
 #include <linux/xattr.h>
@@ -34,7 +36,9 @@
  */
 
 STATIC struct posix_acl *
-xfs_acl_from_disk(struct xfs_acl *aclp)
+xfs_acl_from_disk(
+       struct xfs_acl  *aclp,
+       int             max_entries)
 {
        struct posix_acl_entry *acl_e;
        struct posix_acl *acl;
@@ -42,7 +46,7 @@ xfs_acl_from_disk(struct xfs_acl *aclp)
        unsigned int count, i;
 
        count = be32_to_cpu(aclp->acl_cnt);
-       if (count > XFS_ACL_MAX_ENTRIES)
+       if (count > max_entries)
                return ERR_PTR(-EFSCORRUPTED);
 
        acl = posix_acl_alloc(count, GFP_KERNEL);
@@ -108,9 +112,9 @@ xfs_get_acl(struct inode *inode, int type)
        struct xfs_inode *ip = XFS_I(inode);
        struct posix_acl *acl;
        struct xfs_acl *xfs_acl;
-       int len = sizeof(struct xfs_acl);
        unsigned char *ea_name;
        int error;
+       int len;
 
        acl = get_cached_acl(inode, type);
        if (acl != ACL_NOT_CACHED)
@@ -133,8 +137,8 @@ xfs_get_acl(struct inode *inode, int type)
         * If we have a cached ACLs value just return it, not need to
         * go out to the disk.
         */
-
-       xfs_acl = kzalloc(sizeof(struct xfs_acl), GFP_KERNEL);
+       len = XFS_ACL_MAX_SIZE(ip->i_mount);
+       xfs_acl = kzalloc(len, GFP_KERNEL);
        if (!xfs_acl)
                return ERR_PTR(-ENOMEM);
 
@@ -153,7 +157,7 @@ xfs_get_acl(struct inode *inode, int type)
                goto out;
        }
 
-       acl = xfs_acl_from_disk(xfs_acl);
+       acl = xfs_acl_from_disk(xfs_acl, XFS_ACL_MAX_ENTRIES(ip->i_mount));
        if (IS_ERR(acl))
                goto out;
 
@@ -189,16 +193,17 @@ xfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
 
        if (acl) {
                struct xfs_acl *xfs_acl;
-               int len;
+               int len = XFS_ACL_MAX_SIZE(ip->i_mount);
 
-               xfs_acl = kzalloc(sizeof(struct xfs_acl), GFP_KERNEL);
+               xfs_acl = kzalloc(len, GFP_KERNEL);
                if (!xfs_acl)
                        return -ENOMEM;
 
                xfs_acl_to_disk(xfs_acl, acl);
-               len = sizeof(struct xfs_acl) -
-                       (sizeof(struct xfs_acl_entry) *
-                        (XFS_ACL_MAX_ENTRIES - acl->a_count));
+
+               /* subtract away the unused acl entries */
+               len -= sizeof(struct xfs_acl_entry) *
+                        (XFS_ACL_MAX_ENTRIES(ip->i_mount) - acl->a_count);
 
                error = -xfs_attr_set(ip, ea_name, (unsigned char *)xfs_acl,
                                len, ATTR_ROOT);
@@ -243,7 +248,7 @@ xfs_set_mode(struct inode *inode, umode_t mode)
 static int
 xfs_acl_exists(struct inode *inode, unsigned char *name)
 {
-       int len = sizeof(struct xfs_acl);
+       int len = XFS_ACL_MAX_SIZE(XFS_M(inode->i_sb));
 
        return (xfs_attr_get(XFS_I(inode), name, NULL, &len,
                            ATTR_ROOT|ATTR_KERNOVAL) == 0);
@@ -379,7 +384,7 @@ xfs_xattr_acl_set(struct dentry *dentry, const char *name,
                goto out_release;
 
        error = -EINVAL;
-       if (acl->a_count > XFS_ACL_MAX_ENTRIES)
+       if (acl->a_count > XFS_ACL_MAX_ENTRIES(XFS_M(inode->i_sb)))
                goto out_release;
 
        if (type == ACL_TYPE_ACCESS) {
index 39632d9..4016a56 100644 (file)
@@ -22,19 +22,36 @@ struct inode;
 struct posix_acl;
 struct xfs_inode;
 
-#define XFS_ACL_MAX_ENTRIES 25
 #define XFS_ACL_NOT_PRESENT (-1)
 
 /* On-disk XFS access control list structure */
+struct xfs_acl_entry {
+       __be32  ae_tag;
+       __be32  ae_id;
+       __be16  ae_perm;
+       __be16  ae_pad;         /* fill the implicit hole in the structure */
+};
+
 struct xfs_acl {
-       __be32          acl_cnt;
-       struct xfs_acl_entry {
-               __be32  ae_tag;
-               __be32  ae_id;
-               __be16  ae_perm;
-       } acl_entry[XFS_ACL_MAX_ENTRIES];
+       __be32                  acl_cnt;
+       struct xfs_acl_entry    acl_entry[0];
 };
 
+/*
+ * The number of ACL entries allowed is defined by the on-disk format.
+ * For v4 superblocks, that is limited to 25 entries. For v5 superblocks, it is
+ * limited only by the maximum size of the xattr that stores the information.
+ */
+#define XFS_ACL_MAX_ENTRIES(mp)        \
+       (xfs_sb_version_hascrc(&mp->m_sb) \
+               ?  (XATTR_SIZE_MAX - sizeof(struct xfs_acl)) / \
+                                               sizeof(struct xfs_acl_entry) \
+               : 25)
+
+#define XFS_ACL_MAX_SIZE(mp) \
+       (sizeof(struct xfs_acl) + \
+               sizeof(struct xfs_acl_entry) * XFS_ACL_MAX_ENTRIES((mp)))
+
 /* On-disk XFS extended attribute names */
 #define SGI_ACL_FILE           (unsigned char *)"SGI_ACL_FILE"
 #define SGI_ACL_DEFAULT                (unsigned char *)"SGI_ACL_DEFAULT"
index 2b2691b..41a6950 100644 (file)
@@ -725,6 +725,25 @@ xfs_convert_page(
                        (xfs_off_t)(page->index + 1) << PAGE_CACHE_SHIFT,
                        i_size_read(inode));
 
+       /*
+        * If the current map does not span the entire page we are about to try
+        * to write, then give up. The only way we can write a page that spans
+        * multiple mappings in a single writeback iteration is via the
+        * xfs_vm_writepage() function. Data integrity writeback requires the
+        * entire page to be written in a single attempt, otherwise the part of
+        * the page we don't write here doesn't get written as part of the data
+        * integrity sync.
+        *
+        * For normal writeback, we also don't attempt to write partial pages
+        * here as it simply means that write_cache_pages() will see it under
+        * writeback and ignore the page until some point in the future, at
+        * which time this will be the only page in the file that needs
+        * writeback.  Hence for more optimal IO patterns, we should always
+        * avoid partial page writeback due to multiple mappings on a page here.
+        */
+       if (!xfs_imap_valid(inode, imap, end_offset))
+               goto fail_unlock_page;
+
        len = 1 << inode->i_blkbits;
        p_offset = min_t(unsigned long, end_offset & (PAGE_CACHE_SIZE - 1),
                                        PAGE_CACHE_SIZE);
index 08d5457..31d3cd1 100644 (file)
@@ -931,20 +931,22 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context)
  */
 int
 xfs_attr_shortform_allfit(
-       struct xfs_buf  *bp,
-       struct xfs_inode *dp)
+       struct xfs_buf          *bp,
+       struct xfs_inode        *dp)
 {
-       xfs_attr_leafblock_t *leaf;
-       xfs_attr_leaf_entry_t *entry;
+       struct xfs_attr_leafblock *leaf;
+       struct xfs_attr_leaf_entry *entry;
        xfs_attr_leaf_name_local_t *name_loc;
-       int bytes, i;
+       struct xfs_attr3_icleaf_hdr leafhdr;
+       int                     bytes;
+       int                     i;
 
        leaf = bp->b_addr;
-       ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
+       xfs_attr3_leaf_hdr_from_disk(&leafhdr, leaf);
+       entry = xfs_attr3_leaf_entryp(leaf);
 
-       entry = &leaf->entries[0];
        bytes = sizeof(struct xfs_attr_sf_hdr);
-       for (i = 0; i < be16_to_cpu(leaf->hdr.count); entry++, i++) {
+       for (i = 0; i < leafhdr.count; entry++, i++) {
                if (entry->flags & XFS_ATTR_INCOMPLETE)
                        continue;               /* don't copy partial entries */
                if (!(entry->flags & XFS_ATTR_LOCAL))
@@ -954,15 +956,15 @@ xfs_attr_shortform_allfit(
                        return(0);
                if (be16_to_cpu(name_loc->valuelen) >= XFS_ATTR_SF_ENTSIZE_MAX)
                        return(0);
-               bytes += sizeof(struct xfs_attr_sf_entry)-1
+               bytes += sizeof(struct xfs_attr_sf_entry) - 1
                                + name_loc->namelen
                                + be16_to_cpu(name_loc->valuelen);
        }
        if ((dp->i_mount->m_flags & XFS_MOUNT_ATTR2) &&
            (dp->i_d.di_format != XFS_DINODE_FMT_BTREE) &&
            (bytes == sizeof(struct xfs_attr_sf_hdr)))
-               return(-1);
-       return(xfs_attr_shortform_bytesfit(dp, bytes));
+               return -1;
+       return xfs_attr_shortform_bytesfit(dp, bytes);
 }
 
 /*
@@ -1410,7 +1412,7 @@ xfs_attr3_leaf_add_work(
                name_rmt->valuelen = 0;
                name_rmt->valueblk = 0;
                args->rmtblkno = 1;
-               args->rmtblkcnt = XFS_B_TO_FSB(mp, args->valuelen);
+               args->rmtblkcnt = xfs_attr3_rmt_blocks(mp, args->valuelen);
        }
        xfs_trans_log_buf(args->trans, bp,
             XFS_DA_LOGRANGE(leaf, xfs_attr3_leaf_name(leaf, args->index),
@@ -1443,11 +1445,12 @@ xfs_attr3_leaf_add_work(
 STATIC void
 xfs_attr3_leaf_compact(
        struct xfs_da_args      *args,
-       struct xfs_attr3_icleaf_hdr *ichdr_d,
+       struct xfs_attr3_icleaf_hdr *ichdr_dst,
        struct xfs_buf          *bp)
 {
-       xfs_attr_leafblock_t    *leaf_s, *leaf_d;
-       struct xfs_attr3_icleaf_hdr ichdr_s;
+       struct xfs_attr_leafblock *leaf_src;
+       struct xfs_attr_leafblock *leaf_dst;
+       struct xfs_attr3_icleaf_hdr ichdr_src;
        struct xfs_trans        *trans = args->trans;
        struct xfs_mount        *mp = trans->t_mountp;
        char                    *tmpbuffer;
@@ -1455,29 +1458,38 @@ xfs_attr3_leaf_compact(
        trace_xfs_attr_leaf_compact(args);
 
        tmpbuffer = kmem_alloc(XFS_LBSIZE(mp), KM_SLEEP);
-       ASSERT(tmpbuffer != NULL);
        memcpy(tmpbuffer, bp->b_addr, XFS_LBSIZE(mp));
        memset(bp->b_addr, 0, XFS_LBSIZE(mp));
+       leaf_src = (xfs_attr_leafblock_t *)tmpbuffer;
+       leaf_dst = bp->b_addr;
 
        /*
-        * Copy basic information
+        * Copy the on-disk header back into the destination buffer to ensure
+        * all the information in the header that is not part of the incore
+        * header structure is preserved.
         */
-       leaf_s = (xfs_attr_leafblock_t *)tmpbuffer;
-       leaf_d = bp->b_addr;
-       ichdr_s = *ichdr_d;     /* struct copy */
-       ichdr_d->firstused = XFS_LBSIZE(mp);
-       ichdr_d->usedbytes = 0;
-       ichdr_d->count = 0;
-       ichdr_d->holes = 0;
-       ichdr_d->freemap[0].base = xfs_attr3_leaf_hdr_size(leaf_s);
-       ichdr_d->freemap[0].size = ichdr_d->firstused - ichdr_d->freemap[0].base;
+       memcpy(bp->b_addr, tmpbuffer, xfs_attr3_leaf_hdr_size(leaf_src));
+
+       /* Initialise the incore headers */
+       ichdr_src = *ichdr_dst; /* struct copy */
+       ichdr_dst->firstused = XFS_LBSIZE(mp);
+       ichdr_dst->usedbytes = 0;
+       ichdr_dst->count = 0;
+       ichdr_dst->holes = 0;
+       ichdr_dst->freemap[0].base = xfs_attr3_leaf_hdr_size(leaf_src);
+       ichdr_dst->freemap[0].size = ichdr_dst->firstused -
+                                               ichdr_dst->freemap[0].base;
+
+
+       /* write the header back to initialise the underlying buffer */
+       xfs_attr3_leaf_hdr_to_disk(leaf_dst, ichdr_dst);
 
        /*
         * Copy all entry's in the same (sorted) order,
         * but allocate name/value pairs packed and in sequence.
         */
-       xfs_attr3_leaf_moveents(leaf_s, &ichdr_s, 0, leaf_d, ichdr_d, 0,
-                               ichdr_s.count, mp);
+       xfs_attr3_leaf_moveents(leaf_src, &ichdr_src, 0, leaf_dst, ichdr_dst, 0,
+                               ichdr_src.count, mp);
        /*
         * this logs the entire buffer, but the caller must write the header
         * back to the buffer when it is finished modifying it.
@@ -2179,14 +2191,24 @@ xfs_attr3_leaf_unbalance(
                struct xfs_attr_leafblock *tmp_leaf;
                struct xfs_attr3_icleaf_hdr tmphdr;
 
-               tmp_leaf = kmem_alloc(state->blocksize, KM_SLEEP);
-               memset(tmp_leaf, 0, state->blocksize);
-               memset(&tmphdr, 0, sizeof(tmphdr));
+               tmp_leaf = kmem_zalloc(state->blocksize, KM_SLEEP);
+
+               /*
+                * Copy the header into the temp leaf so that all the stuff
+                * not in the incore header is present and gets copied back in
+                * once we've moved all the entries.
+                */
+               memcpy(tmp_leaf, save_leaf, xfs_attr3_leaf_hdr_size(save_leaf));
 
+               memset(&tmphdr, 0, sizeof(tmphdr));
                tmphdr.magic = savehdr.magic;
                tmphdr.forw = savehdr.forw;
                tmphdr.back = savehdr.back;
                tmphdr.firstused = state->blocksize;
+
+               /* write the header to the temp buffer to initialise it */
+               xfs_attr3_leaf_hdr_to_disk(tmp_leaf, &tmphdr);
+
                if (xfs_attr3_leaf_order(save_blk->bp, &savehdr,
                                         drop_blk->bp, &drophdr)) {
                        xfs_attr3_leaf_moveents(drop_leaf, &drophdr, 0,
@@ -2330,9 +2352,11 @@ xfs_attr3_leaf_lookup_int(
                        if (!xfs_attr_namesp_match(args->flags, entry->flags))
                                continue;
                        args->index = probe;
+                       args->valuelen = be32_to_cpu(name_rmt->valuelen);
                        args->rmtblkno = be32_to_cpu(name_rmt->valueblk);
-                       args->rmtblkcnt = XFS_B_TO_FSB(args->dp->i_mount,
-                                                  be32_to_cpu(name_rmt->valuelen));
+                       args->rmtblkcnt = xfs_attr3_rmt_blocks(
+                                                       args->dp->i_mount,
+                                                       args->valuelen);
                        return XFS_ERROR(EEXIST);
                }
        }
@@ -2383,7 +2407,8 @@ xfs_attr3_leaf_getvalue(
                ASSERT(memcmp(args->name, name_rmt->name, args->namelen) == 0);
                valuelen = be32_to_cpu(name_rmt->valuelen);
                args->rmtblkno = be32_to_cpu(name_rmt->valueblk);
-               args->rmtblkcnt = XFS_B_TO_FSB(args->dp->i_mount, valuelen);
+               args->rmtblkcnt = xfs_attr3_rmt_blocks(args->dp->i_mount,
+                                                      valuelen);
                if (args->flags & ATTR_KERNOVAL) {
                        args->valuelen = valuelen;
                        return 0;
@@ -2709,7 +2734,8 @@ xfs_attr3_leaf_list_int(
                                args.valuelen = valuelen;
                                args.value = kmem_alloc(valuelen, KM_SLEEP | KM_NOFS);
                                args.rmtblkno = be32_to_cpu(name_rmt->valueblk);
-                               args.rmtblkcnt = XFS_B_TO_FSB(args.dp->i_mount, valuelen);
+                               args.rmtblkcnt = xfs_attr3_rmt_blocks(
+                                                       args.dp->i_mount, valuelen);
                                retval = xfs_attr_rmtval_get(&args);
                                if (retval)
                                        return retval;
@@ -3232,7 +3258,7 @@ xfs_attr3_leaf_inactive(
                        name_rmt = xfs_attr3_leaf_name_remote(leaf, i);
                        if (name_rmt->valueblk) {
                                lp->valueblk = be32_to_cpu(name_rmt->valueblk);
-                               lp->valuelen = XFS_B_TO_FSB(dp->i_mount,
+                               lp->valuelen = xfs_attr3_rmt_blocks(dp->i_mount,
                                                    be32_to_cpu(name_rmt->valuelen));
                                lp++;
                        }
index dee8446..ef6b0c1 100644 (file)
  * Each contiguous block has a header, so it is not just a simple attribute
  * length to FSB conversion.
  */
-static int
+int
 xfs_attr3_rmt_blocks(
        struct xfs_mount *mp,
        int             attrlen)
 {
-       int             buflen = XFS_ATTR3_RMT_BUF_SPACE(mp,
-                                                        mp->m_sb.sb_blocksize);
-       return (attrlen + buflen - 1) / buflen;
+       if (xfs_sb_version_hascrc(&mp->m_sb)) {
+               int buflen = XFS_ATTR3_RMT_BUF_SPACE(mp, mp->m_sb.sb_blocksize);
+               return (attrlen + buflen - 1) / buflen;
+       }
+       return XFS_B_TO_FSB(mp, attrlen);
+}
+
+/*
+ * Checking of the remote attribute header is split into two parts. The verifier
+ * does CRC, location and bounds checking, the unpacking function checks the
+ * attribute parameters and owner.
+ */
+static bool
+xfs_attr3_rmt_hdr_ok(
+       struct xfs_mount        *mp,
+       void                    *ptr,
+       xfs_ino_t               ino,
+       uint32_t                offset,
+       uint32_t                size,
+       xfs_daddr_t             bno)
+{
+       struct xfs_attr3_rmt_hdr *rmt = ptr;
+
+       if (bno != be64_to_cpu(rmt->rm_blkno))
+               return false;
+       if (offset != be32_to_cpu(rmt->rm_offset))
+               return false;
+       if (size != be32_to_cpu(rmt->rm_bytes))
+               return false;
+       if (ino != be64_to_cpu(rmt->rm_owner))
+               return false;
+
+       /* ok */
+       return true;
 }
 
 static bool
 xfs_attr3_rmt_verify(
-       struct xfs_buf          *bp)
+       struct xfs_mount        *mp,
+       void                    *ptr,
+       int                     fsbsize,
+       xfs_daddr_t             bno)
 {
-       struct xfs_mount        *mp = bp->b_target->bt_mount;
-       struct xfs_attr3_rmt_hdr *rmt = bp->b_addr;
+       struct xfs_attr3_rmt_hdr *rmt = ptr;
 
        if (!xfs_sb_version_hascrc(&mp->m_sb))
                return false;
@@ -70,7 +103,9 @@ xfs_attr3_rmt_verify(
                return false;
        if (!uuid_equal(&rmt->rm_uuid, &mp->m_sb.sb_uuid))
                return false;
-       if (bp->b_bn != be64_to_cpu(rmt->rm_blkno))
+       if (be64_to_cpu(rmt->rm_blkno) != bno)
+               return false;
+       if (be32_to_cpu(rmt->rm_bytes) > fsbsize - sizeof(*rmt))
                return false;
        if (be32_to_cpu(rmt->rm_offset) +
                                be32_to_cpu(rmt->rm_bytes) >= XATTR_SIZE_MAX)
@@ -86,17 +121,40 @@ xfs_attr3_rmt_read_verify(
        struct xfs_buf  *bp)
 {
        struct xfs_mount *mp = bp->b_target->bt_mount;
+       char            *ptr;
+       int             len;
+       bool            corrupt = false;
+       xfs_daddr_t     bno;
 
        /* no verification of non-crc buffers */
        if (!xfs_sb_version_hascrc(&mp->m_sb))
                return;
 
-       if (!xfs_verify_cksum(bp->b_addr, BBTOB(bp->b_length),
-                             XFS_ATTR3_RMT_CRC_OFF) ||
-           !xfs_attr3_rmt_verify(bp)) {
+       ptr = bp->b_addr;
+       bno = bp->b_bn;
+       len = BBTOB(bp->b_length);
+       ASSERT(len >= XFS_LBSIZE(mp));
+
+       while (len > 0) {
+               if (!xfs_verify_cksum(ptr, XFS_LBSIZE(mp),
+                                     XFS_ATTR3_RMT_CRC_OFF)) {
+                       corrupt = true;
+                       break;
+               }
+               if (!xfs_attr3_rmt_verify(mp, ptr, XFS_LBSIZE(mp), bno)) {
+                       corrupt = true;
+                       break;
+               }
+               len -= XFS_LBSIZE(mp);
+               ptr += XFS_LBSIZE(mp);
+               bno += mp->m_bsize;
+       }
+
+       if (corrupt) {
                XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
                xfs_buf_ioerror(bp, EFSCORRUPTED);
-       }
+       } else
+               ASSERT(len == 0);
 }
 
 static void
@@ -105,23 +163,39 @@ xfs_attr3_rmt_write_verify(
 {
        struct xfs_mount *mp = bp->b_target->bt_mount;
        struct xfs_buf_log_item *bip = bp->b_fspriv;
+       char            *ptr;
+       int             len;
+       xfs_daddr_t     bno;
 
        /* no verification of non-crc buffers */
        if (!xfs_sb_version_hascrc(&mp->m_sb))
                return;
 
-       if (!xfs_attr3_rmt_verify(bp)) {
-               XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
-               xfs_buf_ioerror(bp, EFSCORRUPTED);
-               return;
-       }
+       ptr = bp->b_addr;
+       bno = bp->b_bn;
+       len = BBTOB(bp->b_length);
+       ASSERT(len >= XFS_LBSIZE(mp));
+
+       while (len > 0) {
+               if (!xfs_attr3_rmt_verify(mp, ptr, XFS_LBSIZE(mp), bno)) {
+                       XFS_CORRUPTION_ERROR(__func__,
+                                           XFS_ERRLEVEL_LOW, mp, bp->b_addr);
+                       xfs_buf_ioerror(bp, EFSCORRUPTED);
+                       return;
+               }
+               if (bip) {
+                       struct xfs_attr3_rmt_hdr *rmt;
+
+                       rmt = (struct xfs_attr3_rmt_hdr *)ptr;
+                       rmt->rm_lsn = cpu_to_be64(bip->bli_item.li_lsn);
+               }
+               xfs_update_cksum(ptr, XFS_LBSIZE(mp), XFS_ATTR3_RMT_CRC_OFF);
 
-       if (bip) {
-               struct xfs_attr3_rmt_hdr *rmt = bp->b_addr;
-               rmt->rm_lsn = cpu_to_be64(bip->bli_item.li_lsn);
+               len -= XFS_LBSIZE(mp);
+               ptr += XFS_LBSIZE(mp);
+               bno += mp->m_bsize;
        }
-       xfs_update_cksum(bp->b_addr, BBTOB(bp->b_length),
-                        XFS_ATTR3_RMT_CRC_OFF);
+       ASSERT(len == 0);
 }
 
 const struct xfs_buf_ops xfs_attr3_rmt_buf_ops = {
@@ -129,15 +203,16 @@ const struct xfs_buf_ops xfs_attr3_rmt_buf_ops = {
        .verify_write = xfs_attr3_rmt_write_verify,
 };
 
-static int
+STATIC int
 xfs_attr3_rmt_hdr_set(
        struct xfs_mount        *mp,
+       void                    *ptr,
        xfs_ino_t               ino,
        uint32_t                offset,
        uint32_t                size,
-       struct xfs_buf          *bp)
+       xfs_daddr_t             bno)
 {
-       struct xfs_attr3_rmt_hdr *rmt = bp->b_addr;
+       struct xfs_attr3_rmt_hdr *rmt = ptr;
 
        if (!xfs_sb_version_hascrc(&mp->m_sb))
                return 0;
@@ -147,36 +222,107 @@ xfs_attr3_rmt_hdr_set(
        rmt->rm_bytes = cpu_to_be32(size);
        uuid_copy(&rmt->rm_uuid, &mp->m_sb.sb_uuid);
        rmt->rm_owner = cpu_to_be64(ino);
-       rmt->rm_blkno = cpu_to_be64(bp->b_bn);
-       bp->b_ops = &xfs_attr3_rmt_buf_ops;
+       rmt->rm_blkno = cpu_to_be64(bno);
 
        return sizeof(struct xfs_attr3_rmt_hdr);
 }
 
 /*
- * Checking of the remote attribute header is split into two parts. the verifier
- * does CRC, location and bounds checking, the unpacking function checks the
- * attribute parameters and owner.
+ * Helper functions to copy attribute data in and out of the one disk extents
  */
-static bool
-xfs_attr3_rmt_hdr_ok(
-       struct xfs_mount        *mp,
-       xfs_ino_t               ino,
-       uint32_t                offset,
-       uint32_t                size,
-       struct xfs_buf          *bp)
+STATIC int
+xfs_attr_rmtval_copyout(
+       struct xfs_mount *mp,
+       struct xfs_buf  *bp,
+       xfs_ino_t       ino,
+       int             *offset,
+       int             *valuelen,
+       char            **dst)
 {
-       struct xfs_attr3_rmt_hdr *rmt = bp->b_addr;
+       char            *src = bp->b_addr;
+       xfs_daddr_t     bno = bp->b_bn;
+       int             len = BBTOB(bp->b_length);
 
-       if (offset != be32_to_cpu(rmt->rm_offset))
-               return false;
-       if (size != be32_to_cpu(rmt->rm_bytes))
-               return false;
-       if (ino != be64_to_cpu(rmt->rm_owner))
-               return false;
+       ASSERT(len >= XFS_LBSIZE(mp));
 
-       /* ok */
-       return true;
+       while (len > 0 && *valuelen > 0) {
+               int hdr_size = 0;
+               int byte_cnt = XFS_ATTR3_RMT_BUF_SPACE(mp, XFS_LBSIZE(mp));
+
+               byte_cnt = min_t(int, *valuelen, byte_cnt);
+
+               if (xfs_sb_version_hascrc(&mp->m_sb)) {
+                       if (!xfs_attr3_rmt_hdr_ok(mp, src, ino, *offset,
+                                                 byte_cnt, bno)) {
+                               xfs_alert(mp,
+"remote attribute header mismatch bno/off/len/owner (0x%llx/0x%x/Ox%x/0x%llx)",
+                                       bno, *offset, byte_cnt, ino);
+                               return EFSCORRUPTED;
+                       }
+                       hdr_size = sizeof(struct xfs_attr3_rmt_hdr);
+               }
+
+               memcpy(*dst, src + hdr_size, byte_cnt);
+
+               /* roll buffer forwards */
+               len -= XFS_LBSIZE(mp);
+               src += XFS_LBSIZE(mp);
+               bno += mp->m_bsize;
+
+               /* roll attribute data forwards */
+               *valuelen -= byte_cnt;
+               *dst += byte_cnt;
+               *offset += byte_cnt;
+       }
+       return 0;
+}
+
+STATIC void
+xfs_attr_rmtval_copyin(
+       struct xfs_mount *mp,
+       struct xfs_buf  *bp,
+       xfs_ino_t       ino,
+       int             *offset,
+       int             *valuelen,
+       char            **src)
+{
+       char            *dst = bp->b_addr;
+       xfs_daddr_t     bno = bp->b_bn;
+       int             len = BBTOB(bp->b_length);
+
+       ASSERT(len >= XFS_LBSIZE(mp));
+
+       while (len > 0 && *valuelen > 0) {
+               int hdr_size;
+               int byte_cnt = XFS_ATTR3_RMT_BUF_SPACE(mp, XFS_LBSIZE(mp));
+
+               byte_cnt = min(*valuelen, byte_cnt);
+               hdr_size = xfs_attr3_rmt_hdr_set(mp, dst, ino, *offset,
+                                                byte_cnt, bno);
+
+               memcpy(dst + hdr_size, *src, byte_cnt);
+
+               /*
+                * If this is the last block, zero the remainder of it.
+                * Check that we are actually the last block, too.
+                */
+               if (byte_cnt + hdr_size < XFS_LBSIZE(mp)) {
+                       ASSERT(*valuelen - byte_cnt == 0);
+                       ASSERT(len == XFS_LBSIZE(mp));
+                       memset(dst + hdr_size + byte_cnt, 0,
+                                       XFS_LBSIZE(mp) - hdr_size - byte_cnt);
+               }
+
+               /* roll buffer forwards */
+               len -= XFS_LBSIZE(mp);
+               dst += XFS_LBSIZE(mp);
+               bno += mp->m_bsize;
+
+               /* roll attribute data forwards */
+               *valuelen -= byte_cnt;
+               *src += byte_cnt;
+               *offset += byte_cnt;
+       }
 }
 
 /*
@@ -190,13 +336,12 @@ xfs_attr_rmtval_get(
        struct xfs_bmbt_irec    map[ATTR_RMTVALUE_MAPSIZE];
        struct xfs_mount        *mp = args->dp->i_mount;
        struct xfs_buf          *bp;
-       xfs_daddr_t             dblkno;
        xfs_dablk_t             lblkno = args->rmtblkno;
-       void                    *dst = args->value;
+       char                    *dst = args->value;
        int                     valuelen = args->valuelen;
        int                     nmap;
        int                     error;
-       int                     blkcnt;
+       int                     blkcnt = args->rmtblkcnt;
        int                     i;
        int                     offset = 0;
 
@@ -207,52 +352,36 @@ xfs_attr_rmtval_get(
        while (valuelen > 0) {
                nmap = ATTR_RMTVALUE_MAPSIZE;
                error = xfs_bmapi_read(args->dp, (xfs_fileoff_t)lblkno,
-                                      args->rmtblkcnt, map, &nmap,
+                                      blkcnt, map, &nmap,
                                       XFS_BMAPI_ATTRFORK);
                if (error)
                        return error;
                ASSERT(nmap >= 1);
 
                for (i = 0; (i < nmap) && (valuelen > 0); i++) {
-                       int     byte_cnt;
-                       char    *src;
+                       xfs_daddr_t     dblkno;
+                       int             dblkcnt;
 
                        ASSERT((map[i].br_startblock != DELAYSTARTBLOCK) &&
                               (map[i].br_startblock != HOLESTARTBLOCK));
                        dblkno = XFS_FSB_TO_DADDR(mp, map[i].br_startblock);
-                       blkcnt = XFS_FSB_TO_BB(mp, map[i].br_blockcount);
+                       dblkcnt = XFS_FSB_TO_BB(mp, map[i].br_blockcount);
                        error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp,
-                                                  dblkno, blkcnt, 0, &bp,
+                                                  dblkno, dblkcnt, 0, &bp,
                                                   &xfs_attr3_rmt_buf_ops);
                        if (error)
                                return error;
 
-                       byte_cnt = min_t(int, valuelen, BBTOB(bp->b_length));
-                       byte_cnt = XFS_ATTR3_RMT_BUF_SPACE(mp, byte_cnt);
-
-                       src = bp->b_addr;
-                       if (xfs_sb_version_hascrc(&mp->m_sb)) {
-                               if (!xfs_attr3_rmt_hdr_ok(mp, args->dp->i_ino,
-                                                       offset, byte_cnt, bp)) {
-                                       xfs_alert(mp,
-"remote attribute header does not match required off/len/owner (0x%x/Ox%x,0x%llx)",
-                                               offset, byte_cnt, args->dp->i_ino);
-                                       xfs_buf_relse(bp);
-                                       return EFSCORRUPTED;
-
-                               }
-
-                               src += sizeof(struct xfs_attr3_rmt_hdr);
-                       }
-
-                       memcpy(dst, src, byte_cnt);
+                       error = xfs_attr_rmtval_copyout(mp, bp, args->dp->i_ino,
+                                                       &offset, &valuelen,
+                                                       &dst);
                        xfs_buf_relse(bp);
+                       if (error)
+                               return error;
 
-                       offset += byte_cnt;
-                       dst += byte_cnt;
-                       valuelen -= byte_cnt;
-
+                       /* roll attribute extent map forwards */
                        lblkno += map[i].br_blockcount;
+                       blkcnt -= map[i].br_blockcount;
                }
        }
        ASSERT(valuelen == 0);
@@ -270,17 +399,13 @@ xfs_attr_rmtval_set(
        struct xfs_inode        *dp = args->dp;
        struct xfs_mount        *mp = dp->i_mount;
        struct xfs_bmbt_irec    map;
-       struct xfs_buf          *bp;
-       xfs_daddr_t             dblkno;
        xfs_dablk_t             lblkno;
        xfs_fileoff_t           lfileoff = 0;
-       void                    *src = args->value;
+       char                    *src = args->value;
        int                     blkcnt;
        int                     valuelen;
        int                     nmap;
        int                     error;
-       int                     hdrcnt = 0;
-       bool                    crcs = xfs_sb_version_hascrc(&mp->m_sb);
        int                     offset = 0;
 
        trace_xfs_attr_rmtval_set(args);
@@ -289,24 +414,14 @@ xfs_attr_rmtval_set(
         * Find a "hole" in the attribute address space large enough for
         * us to drop the new attribute's value into. Because CRC enable
         * attributes have headers, we can't just do a straight byte to FSB
-        * conversion. We calculate the worst case block count in this case
-        * and we may not need that many, so we have to handle this when
-        * allocating the blocks below. 
+        * conversion and have to take the header space into account.
         */
-       if (!crcs)
-               blkcnt = XFS_B_TO_FSB(mp, args->valuelen);
-       else
-               blkcnt = xfs_attr3_rmt_blocks(mp, args->valuelen);
-
+       blkcnt = xfs_attr3_rmt_blocks(mp, args->valuelen);
        error = xfs_bmap_first_unused(args->trans, args->dp, blkcnt, &lfileoff,
                                                   XFS_ATTR_FORK);
        if (error)
                return error;
 
-       /* Start with the attribute data. We'll allocate the rest afterwards. */
-       if (crcs)
-               blkcnt = XFS_B_TO_FSB(mp, args->valuelen);
-
        args->rmtblkno = lblkno = (xfs_dablk_t)lfileoff;
        args->rmtblkcnt = blkcnt;
 
@@ -349,26 +464,6 @@ xfs_attr_rmtval_set(
                       (map.br_startblock != HOLESTARTBLOCK));
                lblkno += map.br_blockcount;
                blkcnt -= map.br_blockcount;
-               hdrcnt++;
-
-               /*
-                * If we have enough blocks for the attribute data, calculate
-                * how many extra blocks we need for headers. We might run
-                * through this multiple times in the case that the additional
-                * headers in the blocks needed for the data fragments spills
-                * into requiring more blocks. e.g. for 512 byte blocks, we'll
-                * spill for another block every 9 headers we require in this
-                * loop.
-                */
-               if (crcs && blkcnt == 0) {
-                       int total_len;
-
-                       total_len = args->valuelen +
-                                   hdrcnt * sizeof(struct xfs_attr3_rmt_hdr);
-                       blkcnt = XFS_B_TO_FSB(mp, total_len);
-                       blkcnt -= args->rmtblkcnt;
-                       args->rmtblkcnt += blkcnt;
-               }
 
                /*
                 * Start the next trans in the chain.
@@ -385,18 +480,19 @@ xfs_attr_rmtval_set(
         * the INCOMPLETE flag.
         */
        lblkno = args->rmtblkno;
+       blkcnt = args->rmtblkcnt;
        valuelen = args->valuelen;
        while (valuelen > 0) {
-               int     byte_cnt;
-               char    *buf;
+               struct xfs_buf  *bp;
+               xfs_daddr_t     dblkno;
+               int             dblkcnt;
+
+               ASSERT(blkcnt > 0);
 
-               /*
-                * Try to remember where we decided to put the value.
-                */
                xfs_bmap_init(args->flist, args->firstblock);
                nmap = 1;
                error = xfs_bmapi_read(dp, (xfs_fileoff_t)lblkno,
-                                      args->rmtblkcnt, &map, &nmap,
+                                      blkcnt, &map, &nmap,
                                       XFS_BMAPI_ATTRFORK);
                if (error)
                        return(error);
@@ -405,41 +501,27 @@ xfs_attr_rmtval_set(
                       (map.br_startblock != HOLESTARTBLOCK));
 
                dblkno = XFS_FSB_TO_DADDR(mp, map.br_startblock),
-               blkcnt = XFS_FSB_TO_BB(mp, map.br_blockcount);
+               dblkcnt = XFS_FSB_TO_BB(mp, map.br_blockcount);
 
-               bp = xfs_buf_get(mp->m_ddev_targp, dblkno, blkcnt, 0);
+               bp = xfs_buf_get(mp->m_ddev_targp, dblkno, dblkcnt, 0);
                if (!bp)
                        return ENOMEM;
                bp->b_ops = &xfs_attr3_rmt_buf_ops;
 
-               byte_cnt = BBTOB(bp->b_length);
-               byte_cnt = XFS_ATTR3_RMT_BUF_SPACE(mp, byte_cnt);
-               if (valuelen < byte_cnt)
-                       byte_cnt = valuelen;
-
-               buf = bp->b_addr;
-               buf += xfs_attr3_rmt_hdr_set(mp, dp->i_ino, offset,
-                                            byte_cnt, bp);
-               memcpy(buf, src, byte_cnt);
-
-               if (byte_cnt < BBTOB(bp->b_length))
-                       xfs_buf_zero(bp, byte_cnt,
-                                    BBTOB(bp->b_length) - byte_cnt);
+               xfs_attr_rmtval_copyin(mp, bp, args->dp->i_ino, &offset,
+                                      &valuelen, &src);
 
                error = xfs_bwrite(bp); /* GROT: NOTE: synchronous write */
                xfs_buf_relse(bp);
                if (error)
                        return error;
 
-               src += byte_cnt;
-               valuelen -= byte_cnt;
-               offset += byte_cnt;
-               hdrcnt--;
 
+               /* roll attribute extent map forwards */
                lblkno += map.br_blockcount;
+               blkcnt -= map.br_blockcount;
        }
        ASSERT(valuelen == 0);
-       ASSERT(hdrcnt == 0);
        return 0;
 }
 
@@ -448,33 +530,40 @@ xfs_attr_rmtval_set(
  * out-of-line buffer that it is stored on.
  */
 int
-xfs_attr_rmtval_remove(xfs_da_args_t *args)
+xfs_attr_rmtval_remove(
+       struct xfs_da_args      *args)
 {
-       xfs_mount_t *mp;
-       xfs_bmbt_irec_t map;
-       xfs_buf_t *bp;
-       xfs_daddr_t dblkno;
-       xfs_dablk_t lblkno;
-       int valuelen, blkcnt, nmap, error, done, committed;
+       struct xfs_mount        *mp = args->dp->i_mount;
+       xfs_dablk_t             lblkno;
+       int                     blkcnt;
+       int                     error;
+       int                     done;
 
        trace_xfs_attr_rmtval_remove(args);
 
-       mp = args->dp->i_mount;
-
        /*
-        * Roll through the "value", invalidating the attribute value's
-        * blocks.
+        * Roll through the "value", invalidating the attribute value's blocks.
+        * Note that args->rmtblkcnt is the minimum number of data blocks we'll
+        * see for a CRC enabled remote attribute. Each extent will have a
+        * header, and so we may have more blocks than we realise here.  If we
+        * fail to map the blocks correctly, we'll have problems with the buffer
+        * lookups.
         */
        lblkno = args->rmtblkno;
-       valuelen = args->rmtblkcnt;
-       while (valuelen > 0) {
+       blkcnt = args->rmtblkcnt;
+       while (blkcnt > 0) {
+               struct xfs_bmbt_irec    map;
+               struct xfs_buf          *bp;
+               xfs_daddr_t             dblkno;
+               int                     dblkcnt;
+               int                     nmap;
+
                /*
                 * Try to remember where we decided to put the value.
                 */
                nmap = 1;
                error = xfs_bmapi_read(args->dp, (xfs_fileoff_t)lblkno,
-                                      args->rmtblkcnt, &map, &nmap,
-                                      XFS_BMAPI_ATTRFORK);
+                                      blkcnt, &map, &nmap, XFS_BMAPI_ATTRFORK);
                if (error)
                        return(error);
                ASSERT(nmap == 1);
@@ -482,21 +571,20 @@ xfs_attr_rmtval_remove(xfs_da_args_t *args)
                       (map.br_startblock != HOLESTARTBLOCK));
 
                dblkno = XFS_FSB_TO_DADDR(mp, map.br_startblock),
-               blkcnt = XFS_FSB_TO_BB(mp, map.br_blockcount);
+               dblkcnt = XFS_FSB_TO_BB(mp, map.br_blockcount);
 
                /*
                 * If the "remote" value is in the cache, remove it.
                 */
-               bp = xfs_incore(mp->m_ddev_targp, dblkno, blkcnt, XBF_TRYLOCK);
+               bp = xfs_incore(mp->m_ddev_targp, dblkno, dblkcnt, XBF_TRYLOCK);
                if (bp) {
                        xfs_buf_stale(bp);
                        xfs_buf_relse(bp);
                        bp = NULL;
                }
 
-               valuelen -= map.br_blockcount;
-
                lblkno += map.br_blockcount;
+               blkcnt -= map.br_blockcount;
        }
 
        /*
@@ -506,6 +594,8 @@ xfs_attr_rmtval_remove(xfs_da_args_t *args)
        blkcnt = args->rmtblkcnt;
        done = 0;
        while (!done) {
+               int committed;
+
                xfs_bmap_init(args->flist, args->firstblock);
                error = xfs_bunmapi(args->trans, args->dp, lblkno, blkcnt,
                                    XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA,
index c7cca60..92a8fd7 100644 (file)
 
 #define XFS_ATTR3_RMT_MAGIC    0x5841524d      /* XARM */
 
+/*
+ * There is one of these headers per filesystem block in a remote attribute.
+ * This is done to ensure there is a 1:1 mapping between the attribute value
+ * length and the number of blocks needed to store the attribute. This makes the
+ * verification of a buffer a little more complex, but greatly simplifies the
+ * allocation, reading and writing of these attributes as we don't have to guess
+ * the number of blocks needed to store the attribute data.
+ */
 struct xfs_attr3_rmt_hdr {
        __be32  rm_magic;
        __be32  rm_offset;
@@ -39,6 +47,8 @@ struct xfs_attr3_rmt_hdr {
 
 extern const struct xfs_buf_ops xfs_attr3_rmt_buf_ops;
 
+int xfs_attr3_rmt_blocks(struct xfs_mount *mp, int attrlen);
+
 int xfs_attr_rmtval_get(struct xfs_da_args *args);
 int xfs_attr_rmtval_set(struct xfs_da_args *args);
 int xfs_attr_rmtval_remove(struct xfs_da_args *args);
index 82b70bd..1b2472a 100644 (file)
@@ -513,6 +513,7 @@ _xfs_buf_find(
                xfs_alert(btp->bt_mount,
                          "%s: Block out of range: block 0x%llx, EOFS 0x%llx ",
                          __func__, blkno, eofs);
+               WARN_ON(1);
                return NULL;
        }
 
@@ -1649,7 +1650,7 @@ xfs_alloc_buftarg(
 {
        xfs_buftarg_t           *btp;
 
-       btp = kmem_zalloc(sizeof(*btp), KM_SLEEP);
+       btp = kmem_zalloc(sizeof(*btp), KM_SLEEP | KM_NOFS);
 
        btp->bt_mount = mp;
        btp->bt_dev =  bdev->bd_dev;
index cf26347..4ec4317 100644 (file)
@@ -262,12 +262,7 @@ xfs_buf_item_format_segment(
                        vecp->i_addr = xfs_buf_offset(bp, buffer_offset);
                        vecp->i_len = nbits * XFS_BLF_CHUNK;
                        vecp->i_type = XLOG_REG_TYPE_BCHUNK;
-/*
- * You would think we need to bump the nvecs here too, but we do not
- * this number is used by recovery, and it gets confused by the boundary
- * split here
- *                     nvecs++;
- */
+                       nvecs++;
                        vecp++;
                        first_bit = next_bit;
                        last_bit = next_bit;
index 9b26a99..0b8b2a1 100644 (file)
@@ -270,6 +270,7 @@ xfs_da3_node_read_verify(
                                break;
                        return;
                case XFS_ATTR_LEAF_MAGIC:
+               case XFS_ATTR3_LEAF_MAGIC:
                        bp->b_ops = &xfs_attr3_leaf_buf_ops;
                        bp->b_ops->verify_read(bp);
                        return;
@@ -2464,7 +2465,8 @@ xfs_buf_map_from_irec(
        ASSERT(nirecs >= 1);
 
        if (nirecs > 1) {
-               map = kmem_zalloc(nirecs * sizeof(struct xfs_buf_map), KM_SLEEP);
+               map = kmem_zalloc(nirecs * sizeof(struct xfs_buf_map),
+                                 KM_SLEEP | KM_NOFS);
                if (!map)
                        return ENOMEM;
                *mapp = map;
@@ -2520,7 +2522,8 @@ xfs_dabuf_map(
                 * Optimize the one-block case.
                 */
                if (nfsb != 1)
-                       irecs = kmem_zalloc(sizeof(irec) * nfsb, KM_SLEEP);
+                       irecs = kmem_zalloc(sizeof(irec) * nfsb,
+                                           KM_SLEEP | KM_NOFS);
 
                nirecs = nfsb;
                error = xfs_bmapi_read(dp, (xfs_fileoff_t)bno, nfsb, irecs,
index f852b08..c407e1c 100644 (file)
@@ -219,6 +219,14 @@ xfs_swap_extents(
        int             taforkblks = 0;
        __uint64_t      tmp;
 
+       /*
+        * We have no way of updating owner information in the BMBT blocks for
+        * each inode on CRC enabled filesystems, so to avoid corrupting the
+        * this metadata we simply don't allow extent swaps to occur.
+        */
+       if (xfs_sb_version_hascrc(&mp->m_sb))
+               return XFS_ERROR(EINVAL);
+
        tempifp = kmem_alloc(sizeof(xfs_ifork_t), KM_MAYFAIL);
        if (!tempifp) {
                error = XFS_ERROR(ENOMEM);
index a3b1bd8..995f1f5 100644 (file)
@@ -715,6 +715,7 @@ struct xfs_dir3_free_hdr {
        __be32                  firstdb;        /* db of first entry */
        __be32                  nvalid;         /* count of valid entries */
        __be32                  nused;          /* count of used entries */
+       __be32                  pad;            /* 64 bit alignment. */
 };
 
 struct xfs_dir3_free {
index 721ba2f..da71a18 100644 (file)
@@ -1336,7 +1336,7 @@ xfs_dir2_leaf_getdents(
                                     mp->m_sb.sb_blocksize);
        map_info = kmem_zalloc(offsetof(struct xfs_dir2_leaf_map_info, map) +
                                (length * sizeof(struct xfs_bmbt_irec)),
-                              KM_SLEEP);
+                              KM_SLEEP | KM_NOFS);
        map_info->map_size = length;
 
        /*
index 5246de4..2226a00 100644 (file)
@@ -263,18 +263,19 @@ xfs_dir3_free_get_buf(
         * Initialize the new block to be empty, and remember
         * its first slot as our empty slot.
         */
-       hdr.magic = XFS_DIR2_FREE_MAGIC;
-       hdr.firstdb = 0;
-       hdr.nused = 0;
-       hdr.nvalid = 0;
+       memset(bp->b_addr, 0, sizeof(struct xfs_dir3_free_hdr));
+       memset(&hdr, 0, sizeof(hdr));
+
        if (xfs_sb_version_hascrc(&mp->m_sb)) {
                struct xfs_dir3_free_hdr *hdr3 = bp->b_addr;
 
                hdr.magic = XFS_DIR3_FREE_MAGIC;
+
                hdr3->hdr.blkno = cpu_to_be64(bp->b_bn);
                hdr3->hdr.owner = cpu_to_be64(dp->i_ino);
                uuid_copy(&hdr3->hdr.uuid, &mp->m_sb.sb_uuid);
-       }
+       } else
+               hdr.magic = XFS_DIR2_FREE_MAGIC;
        xfs_dir3_free_hdr_to_disk(bp->b_addr, &hdr);
        *bpp = bp;
        return 0;
@@ -1921,8 +1922,6 @@ xfs_dir2_node_addname_int(
                         */
                        freehdr.firstdb = (fbno - XFS_DIR2_FREE_FIRSTDB(mp)) *
                                        xfs_dir3_free_max_bests(mp);
-                       free->hdr.nvalid = 0;
-                       free->hdr.nused = 0;
                } else {
                        free = fbp->b_addr;
                        bests = xfs_dir3_free_bests_p(mp, free);
index a41f8bf..044e97a 100644 (file)
@@ -249,8 +249,11 @@ xfs_qm_init_dquot_blk(
                d->dd_diskdq.d_version = XFS_DQUOT_VERSION;
                d->dd_diskdq.d_id = cpu_to_be32(curid);
                d->dd_diskdq.d_flags = type;
-               if (xfs_sb_version_hascrc(&mp->m_sb))
+               if (xfs_sb_version_hascrc(&mp->m_sb)) {
                        uuid_copy(&d->dd_uuid, &mp->m_sb.sb_uuid);
+                       xfs_update_cksum((char *)d, sizeof(struct xfs_dqblk),
+                                        XFS_DQUOT_CRC_OFF);
+               }
        }
 
        xfs_trans_dquot_buf(tp, bp,
@@ -286,23 +289,6 @@ xfs_dquot_set_prealloc_limits(struct xfs_dquot *dqp)
        dqp->q_low_space[XFS_QLOWSP_5_PCNT] = space * 5;
 }
 
-STATIC void
-xfs_dquot_buf_calc_crc(
-       struct xfs_mount        *mp,
-       struct xfs_buf          *bp)
-{
-       struct xfs_dqblk        *d = (struct xfs_dqblk *)bp->b_addr;
-       int                     i;
-
-       if (!xfs_sb_version_hascrc(&mp->m_sb))
-               return;
-
-       for (i = 0; i < mp->m_quotainfo->qi_dqperchunk; i++, d++) {
-               xfs_update_cksum((char *)d, sizeof(struct xfs_dqblk),
-                                offsetof(struct xfs_dqblk, dd_crc));
-       }
-}
-
 STATIC bool
 xfs_dquot_buf_verify_crc(
        struct xfs_mount        *mp,
@@ -328,12 +314,11 @@ xfs_dquot_buf_verify_crc(
 
        for (i = 0; i < ndquots; i++, d++) {
                if (!xfs_verify_cksum((char *)d, sizeof(struct xfs_dqblk),
-                                offsetof(struct xfs_dqblk, dd_crc)))
+                                XFS_DQUOT_CRC_OFF))
                        return false;
                if (!uuid_equal(&d->dd_uuid, &mp->m_sb.sb_uuid))
                        return false;
        }
-
        return true;
 }
 
@@ -393,6 +378,11 @@ xfs_dquot_buf_read_verify(
        }
 }
 
+/*
+ * we don't calculate the CRC here as that is done when the dquot is flushed to
+ * the buffer after the update is done. This ensures that the dquot in the
+ * buffer always has an up-to-date CRC value.
+ */
 void
 xfs_dquot_buf_write_verify(
        struct xfs_buf  *bp)
@@ -404,7 +394,6 @@ xfs_dquot_buf_write_verify(
                xfs_buf_ioerror(bp, EFSCORRUPTED);
                return;
        }
-       xfs_dquot_buf_calc_crc(mp, bp);
 }
 
 const struct xfs_buf_ops xfs_dquot_buf_ops = {
@@ -1151,11 +1140,17 @@ xfs_qm_dqflush(
         * copy the lsn into the on-disk dquot now while we have the in memory
         * dquot here. This can't be done later in the write verifier as we
         * can't get access to the log item at that point in time.
+        *
+        * We also calculate the CRC here so that the on-disk dquot in the
+        * buffer always has a valid CRC. This ensures there is no possibility
+        * of a dquot without an up-to-date CRC getting to disk.
         */
        if (xfs_sb_version_hascrc(&mp->m_sb)) {
                struct xfs_dqblk *dqb = (struct xfs_dqblk *)ddqp;
 
                dqb->dd_lsn = cpu_to_be64(dqp->q_logitem.qli_item.li_lsn);
+               xfs_update_cksum((char *)dqb, sizeof(struct xfs_dqblk),
+                                XFS_DQUOT_CRC_OFF);
        }
 
        /*
index c0f3750..452920a 100644 (file)
@@ -305,11 +305,12 @@ xfs_efi_release(xfs_efi_log_item_t        *efip,
 {
        ASSERT(atomic_read(&efip->efi_next_extent) >= nextents);
        if (atomic_sub_and_test(nextents, &efip->efi_next_extent)) {
-               __xfs_efi_release(efip);
-
                /* recovery needs us to drop the EFI reference, too */
                if (test_bit(XFS_EFI_RECOVERED, &efip->efi_flags))
                        __xfs_efi_release(efip);
+
+               __xfs_efi_release(efip);
+               /* efip may now have been freed, do not reference it again. */
        }
 }
 
index 6dda3f9..d046955 100644 (file)
@@ -236,6 +236,7 @@ typedef struct xfs_fsop_resblks {
 #define XFS_FSOP_GEOM_FLAGS_PROJID32   0x0800  /* 32-bit project IDs   */
 #define XFS_FSOP_GEOM_FLAGS_DIRV2CI    0x1000  /* ASCII only CI names  */
 #define XFS_FSOP_GEOM_FLAGS_LAZYSB     0x4000  /* lazy superblock counters */
+#define XFS_FSOP_GEOM_FLAGS_V5SB       0x8000  /* version 5 superblock */
 
 
 /*
index 87595b2..3c3644e 100644 (file)
@@ -99,7 +99,9 @@ xfs_fs_geometry(
                        (xfs_sb_version_hasattr2(&mp->m_sb) ?
                                XFS_FSOP_GEOM_FLAGS_ATTR2 : 0) |
                        (xfs_sb_version_hasprojid32bit(&mp->m_sb) ?
-                               XFS_FSOP_GEOM_FLAGS_PROJID32 : 0);
+                               XFS_FSOP_GEOM_FLAGS_PROJID32 : 0) |
+                       (xfs_sb_version_hascrc(&mp->m_sb) ?
+                               XFS_FSOP_GEOM_FLAGS_V5SB : 0);
                geo->logsectsize = xfs_sb_version_hassector(&mp->m_sb) ?
                                mp->m_sb.sb_logsectsize : BBSIZE;
                geo->rtsectsize = mp->m_sb.sb_blocksize;
index efbe1ac..7f7be5f 100644 (file)
@@ -1638,6 +1638,10 @@ xfs_iunlink(
                dip->di_next_unlinked = agi->agi_unlinked[bucket_index];
                offset = ip->i_imap.im_boffset +
                        offsetof(xfs_dinode_t, di_next_unlinked);
+
+               /* need to recalc the inode CRC if appropriate */
+               xfs_dinode_calc_crc(mp, dip);
+
                xfs_trans_inode_buf(tp, ibp);
                xfs_trans_log_buf(tp, ibp, offset,
                                  (offset + sizeof(xfs_agino_t) - 1));
@@ -1723,6 +1727,10 @@ xfs_iunlink_remove(
                        dip->di_next_unlinked = cpu_to_be32(NULLAGINO);
                        offset = ip->i_imap.im_boffset +
                                offsetof(xfs_dinode_t, di_next_unlinked);
+
+                       /* need to recalc the inode CRC if appropriate */
+                       xfs_dinode_calc_crc(mp, dip);
+
                        xfs_trans_inode_buf(tp, ibp);
                        xfs_trans_log_buf(tp, ibp, offset,
                                          (offset + sizeof(xfs_agino_t) - 1));
@@ -1796,6 +1804,10 @@ xfs_iunlink_remove(
                        dip->di_next_unlinked = cpu_to_be32(NULLAGINO);
                        offset = ip->i_imap.im_boffset +
                                offsetof(xfs_dinode_t, di_next_unlinked);
+
+                       /* need to recalc the inode CRC if appropriate */
+                       xfs_dinode_calc_crc(mp, dip);
+
                        xfs_trans_inode_buf(tp, ibp);
                        xfs_trans_log_buf(tp, ibp, offset,
                                          (offset + sizeof(xfs_agino_t) - 1));
@@ -1809,6 +1821,10 @@ xfs_iunlink_remove(
                last_dip->di_next_unlinked = cpu_to_be32(next_agino);
                ASSERT(next_agino != 0);
                offset = last_offset + offsetof(xfs_dinode_t, di_next_unlinked);
+
+               /* need to recalc the inode CRC if appropriate */
+               xfs_dinode_calc_crc(mp, last_dip);
+
                xfs_trans_inode_buf(tp, last_ibp);
                xfs_trans_log_buf(tp, last_ibp, offset,
                                  (offset + sizeof(xfs_agino_t) - 1));
index d82efaa..ca9ecaa 100644 (file)
@@ -455,6 +455,28 @@ xfs_vn_getattr(
        return 0;
 }
 
+static void
+xfs_setattr_mode(
+       struct xfs_trans        *tp,
+       struct xfs_inode        *ip,
+       struct iattr            *iattr)
+{
+       struct inode    *inode = VFS_I(ip);
+       umode_t         mode = iattr->ia_mode;
+
+       ASSERT(tp);
+       ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
+
+       if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
+               mode &= ~S_ISGID;
+
+       ip->i_d.di_mode &= S_IFMT;
+       ip->i_d.di_mode |= mode & ~S_IFMT;
+
+       inode->i_mode &= S_IFMT;
+       inode->i_mode |= mode & ~S_IFMT;
+}
+
 int
 xfs_setattr_nonsize(
        struct xfs_inode        *ip,
@@ -606,18 +628,8 @@ xfs_setattr_nonsize(
        /*
         * Change file access modes.
         */
-       if (mask & ATTR_MODE) {
-               umode_t mode = iattr->ia_mode;
-
-               if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
-                       mode &= ~S_ISGID;
-
-               ip->i_d.di_mode &= S_IFMT;
-               ip->i_d.di_mode |= mode & ~S_IFMT;
-
-               inode->i_mode &= S_IFMT;
-               inode->i_mode |= mode & ~S_IFMT;
-       }
+       if (mask & ATTR_MODE)
+               xfs_setattr_mode(tp, ip, iattr);
 
        /*
         * Change file access or modified times.
@@ -714,9 +726,8 @@ xfs_setattr_size(
                return XFS_ERROR(error);
 
        ASSERT(S_ISREG(ip->i_d.di_mode));
-       ASSERT((mask & (ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_ATIME|ATTR_ATIME_SET|
-                       ATTR_MTIME_SET|ATTR_KILL_SUID|ATTR_KILL_SGID|
-                       ATTR_KILL_PRIV|ATTR_TIMES_SET)) == 0);
+       ASSERT((mask & (ATTR_UID|ATTR_GID|ATTR_ATIME|ATTR_ATIME_SET|
+                       ATTR_MTIME_SET|ATTR_KILL_PRIV|ATTR_TIMES_SET)) == 0);
 
        if (!(flags & XFS_ATTR_NOLOCK)) {
                lock_flags |= XFS_IOLOCK_EXCL;
@@ -860,6 +871,12 @@ xfs_setattr_size(
                xfs_inode_clear_eofblocks_tag(ip);
        }
 
+       /*
+        * Change file access modes.
+        */
+       if (mask & ATTR_MODE)
+               xfs_setattr_mode(tp, ip, iattr);
+
        if (mask & ATTR_CTIME) {
                inode->i_ctime = iattr->ia_ctime;
                ip->i_d.di_ctime.t_sec = iattr->ia_ctime.tv_sec;
index e3d0b85..d0833b5 100644 (file)
@@ -139,7 +139,7 @@ xlog_cil_prepare_log_vecs(
 
                new_lv = kmem_zalloc(sizeof(*new_lv) +
                                niovecs * sizeof(struct xfs_log_iovec),
-                               KM_SLEEP);
+                               KM_SLEEP|KM_NOFS);
 
                /* The allocated iovec region lies beyond the log vector. */
                new_lv->lv_iovecp = (struct xfs_log_iovec *)&new_lv[1];
index 93f03ec..45a85ff 100644 (file)
@@ -1599,10 +1599,43 @@ xlog_recover_add_to_trans(
 }
 
 /*
- * Sort the log items in the transaction. Cancelled buffers need
- * to be put first so they are processed before any items that might
- * modify the buffers. If they are cancelled, then the modifications
- * don't need to be replayed.
+ * Sort the log items in the transaction.
+ *
+ * The ordering constraints are defined by the inode allocation and unlink
+ * behaviour. The rules are:
+ *
+ *     1. Every item is only logged once in a given transaction. Hence it
+ *        represents the last logged state of the item. Hence ordering is
+ *        dependent on the order in which operations need to be performed so
+ *        required initial conditions are always met.
+ *
+ *     2. Cancelled buffers are recorded in pass 1 in a separate table and
+ *        there's nothing to replay from them so we can simply cull them
+ *        from the transaction. However, we can't do that until after we've
+ *        replayed all the other items because they may be dependent on the
+ *        cancelled buffer and replaying the cancelled buffer can remove it
+ *        form the cancelled buffer table. Hence they have tobe done last.
+ *
+ *     3. Inode allocation buffers must be replayed before inode items that
+ *        read the buffer and replay changes into it.
+ *
+ *     4. Inode unlink buffers must be replayed after inode items are replayed.
+ *        This ensures that inodes are completely flushed to the inode buffer
+ *        in a "free" state before we remove the unlinked inode list pointer.
+ *
+ * Hence the ordering needs to be inode allocation buffers first, inode items
+ * second, inode unlink buffers third and cancelled buffers last.
+ *
+ * But there's a problem with that - we can't tell an inode allocation buffer
+ * apart from a regular buffer, so we can't separate them. We can, however,
+ * tell an inode unlink buffer from the others, and so we can separate them out
+ * from all the other buffers and move them to last.
+ *
+ * Hence, 4 lists, in order from head to tail:
+ *     - buffer_list for all buffers except cancelled/inode unlink buffers
+ *     - item_list for all non-buffer items
+ *     - inode_buffer_list for inode unlink buffers
+ *     - cancel_list for the cancelled buffers
  */
 STATIC int
 xlog_recover_reorder_trans(
@@ -1612,6 +1645,10 @@ xlog_recover_reorder_trans(
 {
        xlog_recover_item_t     *item, *n;
        LIST_HEAD(sort_list);
+       LIST_HEAD(cancel_list);
+       LIST_HEAD(buffer_list);
+       LIST_HEAD(inode_buffer_list);
+       LIST_HEAD(inode_list);
 
        list_splice_init(&trans->r_itemq, &sort_list);
        list_for_each_entry_safe(item, n, &sort_list, ri_list) {
@@ -1619,12 +1656,18 @@ xlog_recover_reorder_trans(
 
                switch (ITEM_TYPE(item)) {
                case XFS_LI_BUF:
-                       if (!(buf_f->blf_flags & XFS_BLF_CANCEL)) {
+                       if (buf_f->blf_flags & XFS_BLF_CANCEL) {
                                trace_xfs_log_recover_item_reorder_head(log,
                                                        trans, item, pass);
-                               list_move(&item->ri_list, &trans->r_itemq);
+                               list_move(&item->ri_list, &cancel_list);
                                break;
                        }
+                       if (buf_f->blf_flags & XFS_BLF_INODE_BUF) {
+                               list_move(&item->ri_list, &inode_buffer_list);
+                               break;
+                       }
+                       list_move_tail(&item->ri_list, &buffer_list);
+                       break;
                case XFS_LI_INODE:
                case XFS_LI_DQUOT:
                case XFS_LI_QUOTAOFF:
@@ -1632,7 +1675,7 @@ xlog_recover_reorder_trans(
                case XFS_LI_EFI:
                        trace_xfs_log_recover_item_reorder_tail(log,
                                                        trans, item, pass);
-                       list_move_tail(&item->ri_list, &trans->r_itemq);
+                       list_move_tail(&item->ri_list, &inode_list);
                        break;
                default:
                        xfs_warn(log->l_mp,
@@ -1643,6 +1686,14 @@ xlog_recover_reorder_trans(
                }
        }
        ASSERT(list_empty(&sort_list));
+       if (!list_empty(&buffer_list))
+               list_splice(&buffer_list, &trans->r_itemq);
+       if (!list_empty(&inode_list))
+               list_splice_tail(&inode_list, &trans->r_itemq);
+       if (!list_empty(&inode_buffer_list))
+               list_splice_tail(&inode_buffer_list, &trans->r_itemq);
+       if (!list_empty(&cancel_list))
+               list_splice_tail(&cancel_list, &trans->r_itemq);
        return 0;
 }
 
@@ -1861,6 +1912,15 @@ xlog_recover_do_inode_buffer(
                buffer_nextp = (xfs_agino_t *)xfs_buf_offset(bp,
                                              next_unlinked_offset);
                *buffer_nextp = *logged_nextp;
+
+               /*
+                * If necessary, recalculate the CRC in the on-disk inode. We
+                * have to leave the inode in a consistent state for whoever
+                * reads it next....
+                */
+               xfs_dinode_calc_crc(mp, (struct xfs_dinode *)
+                               xfs_buf_offset(bp, i * mp->m_sb.sb_inodesize));
+
        }
 
        return 0;
@@ -2096,6 +2156,17 @@ xlog_recover_do_reg_buffer(
                ASSERT(BBTOB(bp->b_io_length) >=
                       ((uint)bit << XFS_BLF_SHIFT) + (nbits << XFS_BLF_SHIFT));
 
+               /*
+                * The dirty regions logged in the buffer, even though
+                * contiguous, may span multiple chunks. This is because the
+                * dirty region may span a physical page boundary in a buffer
+                * and hence be split into two separate vectors for writing into
+                * the log. Hence we need to trim nbits back to the length of
+                * the current region being copied out of the log.
+                */
+               if (item->ri_buf[i].i_len < (nbits << XFS_BLF_SHIFT))
+                       nbits = item->ri_buf[i].i_len >> XFS_BLF_SHIFT;
+
                /*
                 * Do a sanity check if this is a dquot buffer. Just checking
                 * the first dquot in the buffer should do. XXXThis is
@@ -2255,6 +2326,12 @@ xfs_qm_dqcheck(
        d->dd_diskdq.d_flags = type;
        d->dd_diskdq.d_id = cpu_to_be32(id);
 
+       if (xfs_sb_version_hascrc(&mp->m_sb)) {
+               uuid_copy(&d->dd_uuid, &mp->m_sb.sb_uuid);
+               xfs_update_cksum((char *)d, sizeof(struct xfs_dqblk),
+                                XFS_DQUOT_CRC_OFF);
+       }
+
        return errs;
 }
 
@@ -2782,6 +2859,10 @@ xlog_recover_dquot_pass2(
        }
 
        memcpy(ddq, recddq, item->ri_buf[1].i_len);
+       if (xfs_sb_version_hascrc(&mp->m_sb)) {
+               xfs_update_cksum((char *)ddq, sizeof(struct xfs_dqblk),
+                                XFS_DQUOT_CRC_OFF);
+       }
 
        ASSERT(dq_f->qlf_size == 2);
        ASSERT(bp->b_target->bt_mount == mp);
index f41702b..b75c9bb 100644 (file)
@@ -41,6 +41,7 @@
 #include "xfs_qm.h"
 #include "xfs_trace.h"
 #include "xfs_icache.h"
+#include "xfs_cksum.h"
 
 /*
  * The global quota manager. There is only one of these for the entire
@@ -839,7 +840,7 @@ xfs_qm_reset_dqcounts(
        xfs_dqid_t      id,
        uint            type)
 {
-       xfs_disk_dquot_t        *ddq;
+       struct xfs_dqblk        *dqb;
        int                     j;
 
        trace_xfs_reset_dqcounts(bp, _RET_IP_);
@@ -853,8 +854,12 @@ xfs_qm_reset_dqcounts(
        do_div(j, sizeof(xfs_dqblk_t));
        ASSERT(mp->m_quotainfo->qi_dqperchunk == j);
 #endif
-       ddq = bp->b_addr;
+       dqb = bp->b_addr;
        for (j = 0; j < mp->m_quotainfo->qi_dqperchunk; j++) {
+               struct xfs_disk_dquot   *ddq;
+
+               ddq = (struct xfs_disk_dquot *)&dqb[j];
+
                /*
                 * Do a sanity check, and if needed, repair the dqblk. Don't
                 * output any warnings because it's perfectly possible to
@@ -871,7 +876,12 @@ xfs_qm_reset_dqcounts(
                ddq->d_bwarns = 0;
                ddq->d_iwarns = 0;
                ddq->d_rtbwarns = 0;
-               ddq = (xfs_disk_dquot_t *) ((xfs_dqblk_t *)ddq + 1);
+
+               if (xfs_sb_version_hascrc(&mp->m_sb)) {
+                       xfs_update_cksum((char *)&dqb[j],
+                                        sizeof(struct xfs_dqblk),
+                                        XFS_DQUOT_CRC_OFF);
+               }
        }
 }
 
@@ -907,19 +917,29 @@ xfs_qm_dqiter_bufs(
                              XFS_FSB_TO_DADDR(mp, bno),
                              mp->m_quotainfo->qi_dqchunklen, 0, &bp,
                              &xfs_dquot_buf_ops);
-               if (error)
-                       break;
 
                /*
-                * XXX(hch): need to figure out if it makes sense to validate
-                *           the CRC here.
+                * CRC and validation errors will return a EFSCORRUPTED here. If
+                * this occurs, re-read without CRC validation so that we can
+                * repair the damage via xfs_qm_reset_dqcounts(). This process
+                * will leave a trace in the log indicating corruption has
+                * been detected.
                 */
+               if (error == EFSCORRUPTED) {
+                       error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp,
+                                     XFS_FSB_TO_DADDR(mp, bno),
+                                     mp->m_quotainfo->qi_dqchunklen, 0, &bp,
+                                     NULL);
+               }
+
+               if (error)
+                       break;
+
                xfs_qm_reset_dqcounts(mp, bp, firstid, type);
                xfs_buf_delwri_queue(bp, buffer_list);
                xfs_buf_relse(bp);
-               /*
-                * goto the next block.
-                */
+
+               /* goto the next block. */
                bno++;
                firstid += mp->m_quotainfo->qi_dqperchunk;
        }
index c41190c..6cdf6ff 100644 (file)
@@ -489,31 +489,36 @@ xfs_qm_scall_setqlim(
        if ((newlim->d_fieldmask & XFS_DQ_MASK) == 0)
                return 0;
 
-       tp = xfs_trans_alloc(mp, XFS_TRANS_QM_SETQLIM);
-       error = xfs_trans_reserve(tp, 0, XFS_QM_SETQLIM_LOG_RES(mp),
-                                 0, 0, XFS_DEFAULT_LOG_COUNT);
-       if (error) {
-               xfs_trans_cancel(tp, 0);
-               return (error);
-       }
-
        /*
         * We don't want to race with a quotaoff so take the quotaoff lock.
-        * (We don't hold an inode lock, so there's nothing else to stop
-        * a quotaoff from happening). (XXXThis doesn't currently happen
-        * because we take the vfslock before calling xfs_qm_sysent).
+        * We don't hold an inode lock, so there's nothing else to stop
+        * a quotaoff from happening.
         */
        mutex_lock(&q->qi_quotaofflock);
 
        /*
-        * Get the dquot (locked), and join it to the transaction.
-        * Allocate the dquot if this doesn't exist.
+        * Get the dquot (locked) before we start, as we need to do a
+        * transaction to allocate it if it doesn't exist. Once we have the
+        * dquot, unlock it so we can start the next transaction safely. We hold
+        * a reference to the dquot, so it's safe to do this unlock/lock without
+        * it being reclaimed in the mean time.
         */
-       if ((error = xfs_qm_dqget(mp, NULL, id, type, XFS_QMOPT_DQALLOC, &dqp))) {
-               xfs_trans_cancel(tp, XFS_TRANS_ABORT);
+       error = xfs_qm_dqget(mp, NULL, id, type, XFS_QMOPT_DQALLOC, &dqp);
+       if (error) {
                ASSERT(error != ENOENT);
                goto out_unlock;
        }
+       xfs_dqunlock(dqp);
+
+       tp = xfs_trans_alloc(mp, XFS_TRANS_QM_SETQLIM);
+       error = xfs_trans_reserve(tp, 0, XFS_QM_SETQLIM_LOG_RES(mp),
+                                 0, 0, XFS_DEFAULT_LOG_COUNT);
+       if (error) {
+               xfs_trans_cancel(tp, 0);
+               goto out_rele;
+       }
+
+       xfs_dqlock(dqp);
        xfs_trans_dqjoin(tp, dqp);
        ddq = &dqp->q_core;
 
@@ -621,9 +626,10 @@ xfs_qm_scall_setqlim(
        xfs_trans_log_dquot(tp, dqp);
 
        error = xfs_trans_commit(tp, 0);
-       xfs_qm_dqrele(dqp);
 
- out_unlock:
+out_rele:
+       xfs_qm_dqrele(dqp);
+out_unlock:
        mutex_unlock(&q->qi_quotaofflock);
        return error;
 }
index c61e31c..c38068f 100644 (file)
@@ -87,6 +87,8 @@ typedef struct xfs_dqblk {
        uuid_t            dd_uuid;      /* location information */
 } xfs_dqblk_t;
 
+#define XFS_DQUOT_CRC_OFF      offsetof(struct xfs_dqblk, dd_crc)
+
 /*
  * flags for q_flags field in the dquot.
  */
index ea341ce..3033ba5 100644 (file)
@@ -1372,6 +1372,17 @@ xfs_finish_flags(
                }
        }
 
+       /*
+        * V5 filesystems always use attr2 format for attributes.
+        */
+       if (xfs_sb_version_hascrc(&mp->m_sb) &&
+           (mp->m_flags & XFS_MOUNT_NOATTR2)) {
+               xfs_warn(mp,
+"Cannot mount a V5 filesystem as %s. %s is always enabled for V5 filesystems.",
+                       MNTOPT_NOATTR2, MNTOPT_ATTR2);
+               return XFS_ERROR(EINVAL);
+       }
+
        /*
         * mkfs'ed attr2 will turn on attr2 mount unless explicitly
         * told by noattr2 to turn it off
index 5f23438..195a403 100644 (file)
@@ -56,16 +56,9 @@ xfs_symlink_blocks(
        struct xfs_mount *mp,
        int             pathlen)
 {
-       int             fsblocks = 0;
-       int             len = pathlen;
+       int buflen = XFS_SYMLINK_BUF_SPACE(mp, mp->m_sb.sb_blocksize);
 
-       do {
-               fsblocks++;
-               len -= XFS_SYMLINK_BUF_SPACE(mp, mp->m_sb.sb_blocksize);
-       } while (len > 0);
-
-       ASSERT(fsblocks <= XFS_SYMLINK_MAPS);
-       return fsblocks;
+       return (pathlen + buflen - 1) / buflen;
 }
 
 static int
@@ -405,7 +398,7 @@ xfs_symlink(
        if (pathlen <= XFS_LITINO(mp, dp->i_d.di_version))
                fs_blocks = 0;
        else
-               fs_blocks = XFS_B_TO_FSB(mp, pathlen);
+               fs_blocks = xfs_symlink_blocks(mp, pathlen);
        resblks = XFS_SYMLINK_SPACE_RES(mp, link_name->len, fs_blocks);
        error = xfs_trans_reserve(tp, resblks, XFS_SYMLINK_LOG_RES(mp), 0,
                        XFS_TRANS_PERM_LOG_RES, XFS_SYMLINK_LOG_COUNT);
@@ -512,7 +505,7 @@ xfs_symlink(
                cur_chunk = target_path;
                offset = 0;
                for (n = 0; n < nmaps; n++) {
-                       char *buf;
+                       char    *buf;
 
                        d = XFS_FSB_TO_DADDR(mp, mval[n].br_startblock);
                        byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount);
@@ -525,9 +518,7 @@ xfs_symlink(
                        bp->b_ops = &xfs_symlink_buf_ops;
 
                        byte_cnt = XFS_SYMLINK_BUF_SPACE(mp, byte_cnt);
-                       if (pathlen < byte_cnt) {
-                               byte_cnt = pathlen;
-                       }
+                       byte_cnt = min(byte_cnt, pathlen);
 
                        buf = bp->b_addr;
                        buf += xfs_symlink_hdr_set(mp, ip->i_ino, offset,
@@ -542,6 +533,7 @@ xfs_symlink(
                        xfs_trans_log_buf(tp, bp, 0, (buf + byte_cnt - 1) -
                                                        (char *)bp->b_addr);
                }
+               ASSERT(pathlen == 0);
        }
 
        /*
index 1501f4f..0176bb2 100644 (file)
@@ -1453,7 +1453,7 @@ xfs_free_file_space(
        xfs_mount_t             *mp;
        int                     nimap;
        uint                    resblks;
-       uint                    rounding;
+       xfs_off_t               rounding;
        int                     rt;
        xfs_fileoff_t           startoffset_fsb;
        xfs_trans_t             *tp;
@@ -1482,7 +1482,7 @@ xfs_free_file_space(
                inode_dio_wait(VFS_I(ip));
        }
 
-       rounding = max_t(uint, 1 << mp->m_sb.sb_blocklog, PAGE_CACHE_SIZE);
+       rounding = max_t(xfs_off_t, 1 << mp->m_sb.sb_blocklog, PAGE_CACHE_SIZE);
        ioffset = offset & ~(rounding - 1);
        error = -filemap_write_and_wait_range(VFS_I(ip)->i_mapping,
                                              ioffset, -1);
index 98db31d..636c59f 100644 (file)
@@ -377,7 +377,6 @@ acpi_status acpi_bus_get_status_handle(acpi_handle handle,
                                       unsigned long long *sta);
 int acpi_bus_get_status(struct acpi_device *device);
 
-#ifdef CONFIG_PM
 int acpi_bus_set_power(acpi_handle handle, int state);
 const char *acpi_power_state_string(int state);
 int acpi_device_get_power(struct acpi_device *device, int *state);
@@ -385,41 +384,12 @@ int acpi_device_set_power(struct acpi_device *device, int state);
 int acpi_bus_init_power(struct acpi_device *device);
 int acpi_bus_update_power(acpi_handle handle, int *state_p);
 bool acpi_bus_power_manageable(acpi_handle handle);
+
+#ifdef CONFIG_PM
 bool acpi_bus_can_wakeup(acpi_handle handle);
-#else /* !CONFIG_PM */
-static inline int acpi_bus_set_power(acpi_handle handle, int state)
-{
-       return 0;
-}
-static inline const char *acpi_power_state_string(int state)
-{
-       return "D0";
-}
-static inline int acpi_device_get_power(struct acpi_device *device, int *state)
-{
-       return 0;
-}
-static inline int acpi_device_set_power(struct acpi_device *device, int state)
-{
-       return 0;
-}
-static inline int acpi_bus_init_power(struct acpi_device *device)
-{
-       return 0;
-}
-static inline int acpi_bus_update_power(acpi_handle handle, int *state_p)
-{
-       return 0;
-}
-static inline bool acpi_bus_power_manageable(acpi_handle handle)
-{
-       return false;
-}
-static inline bool acpi_bus_can_wakeup(acpi_handle handle)
-{
-       return false;
-}
-#endif /* !CONFIG_PM */
+#else
+static inline bool acpi_bus_can_wakeup(acpi_handle handle) { return false; }
+#endif
 
 #ifdef CONFIG_ACPI_PROC_EVENT
 int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data);
index 5b3d2bd..64b8c76 100644 (file)
@@ -77,7 +77,7 @@ struct acpi_signal_fatal_info {
 /*
  * OSL Initialization and shutdown primitives
  */
-acpi_status __initdata acpi_os_initialize(void);
+acpi_status __init acpi_os_initialize(void);
 
 acpi_status acpi_os_terminate(void);
 
index b327b5a..ea69367 100644 (file)
@@ -329,10 +329,16 @@ int acpi_processor_power_init(struct acpi_processor *pr);
 int acpi_processor_power_exit(struct acpi_processor *pr);
 int acpi_processor_cst_has_changed(struct acpi_processor *pr);
 int acpi_processor_hotplug(struct acpi_processor *pr);
-int acpi_processor_suspend(struct device *dev);
-int acpi_processor_resume(struct device *dev);
 extern struct cpuidle_driver acpi_idle_driver;
 
+#ifdef CONFIG_PM_SLEEP
+void acpi_processor_syscore_init(void);
+void acpi_processor_syscore_exit(void);
+#else
+static inline void acpi_processor_syscore_init(void) {}
+static inline void acpi_processor_syscore_exit(void) {}
+#endif
+
 /* in processor_thermal.c */
 int acpi_processor_get_limit_info(struct acpi_processor *pr);
 extern const struct thermal_cooling_device_ops processor_cooling_ops;
index ac9da00..d5afe96 100644 (file)
@@ -343,8 +343,12 @@ extern void ioport_unmap(void __iomem *p);
 #endif /* CONFIG_GENERIC_IOMAP */
 #endif /* CONFIG_HAS_IOPORT */
 
+#ifndef xlate_dev_kmem_ptr
 #define xlate_dev_kmem_ptr(p)  p
+#endif
+#ifndef xlate_dev_mem_ptr
 #define xlate_dev_mem_ptr(p)   __va(p)
+#endif
 
 #ifdef CONFIG_VIRT_TO_BUS
 #ifndef virt_to_bus
index 9d96605..fa25bec 100644 (file)
@@ -18,4 +18,9 @@ static inline unsigned int kvm_arch_para_features(void)
        return 0;
 }
 
+static inline bool kvm_para_available(void)
+{
+       return false;
+}
+
 #endif
index b1b1fa6..13821c3 100644 (file)
@@ -97,11 +97,9 @@ struct mmu_gather {
        unsigned long           start;
        unsigned long           end;
        unsigned int            need_flush : 1, /* Did free PTEs */
-                               fast_mode  : 1; /* No batching   */
-
        /* we are in the middle of an operation to clear
         * a full mm and can make some optimizations */
-       unsigned int            fullmm : 1,
+                               fullmm : 1,
        /* we have performed an operation which
         * requires a complete flush of the tlb */
                                need_flush_all : 1;
@@ -114,19 +112,6 @@ struct mmu_gather {
 
 #define HAVE_GENERIC_MMU_GATHER
 
-static inline int tlb_fast_mode(struct mmu_gather *tlb)
-{
-#ifdef CONFIG_SMP
-       return tlb->fast_mode;
-#else
-       /*
-        * For UP we don't need to worry about TLB flush
-        * and page free order so much..
-        */
-       return 1;
-#endif
-}
-
 void tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, bool fullmm);
 void tlb_flush_mmu(struct mmu_gather *tlb);
 void tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start,
index 6119659..63d17ee 100644 (file)
@@ -316,6 +316,7 @@ struct drm_ioctl_desc {
        int flags;
        drm_ioctl_t *func;
        unsigned int cmd_drv;
+       const char *name;
 };
 
 /**
@@ -324,7 +325,7 @@ struct drm_ioctl_desc {
  */
 
 #define DRM_IOCTL_DEF_DRV(ioctl, _func, _flags)                        \
-       [DRM_IOCTL_NR(DRM_##ioctl)] = {.cmd = DRM_##ioctl, .func = _func, .flags = _flags, .cmd_drv = DRM_IOCTL_##ioctl}
+       [DRM_IOCTL_NR(DRM_##ioctl)] = {.cmd = DRM_##ioctl, .func = _func, .flags = _flags, .cmd_drv = DRM_IOCTL_##ioctl, .name = #ioctl}
 
 struct drm_magic_entry {
        struct list_head head;
index 8230b46..471f276 100644 (file)
@@ -50,13 +50,14 @@ struct drm_fb_helper_surface_size {
 
 /**
  * struct drm_fb_helper_funcs - driver callbacks for the fbdev emulation library
- * @gamma_set: - Set the given gamma lut register on the given crtc.
- * @gamma_get: - Read the given gamma lut register on the given crtc, used to
- *              save the current lut when force-restoring the fbdev for e.g.
- *              kdbg.
- * @fb_probe: - Driver callback to allocate and initialize the fbdev info
- *             structure. Futhermore it also needs to allocate the drm
- *             framebuffer used to back the fbdev.
+ * @gamma_set: Set the given gamma lut register on the given crtc.
+ * @gamma_get: Read the given gamma lut register on the given crtc, used to
+ *             save the current lut when force-restoring the fbdev for e.g.
+ *             kdbg.
+ * @fb_probe: Driver callback to allocate and initialize the fbdev info
+ *            structure. Futhermore it also needs to allocate the drm
+ *            framebuffer used to back the fbdev.
+ * @initial_config: Setup an initial fbdev display configuration
  *
  * Driver callbacks used by the fbdev emulation helper library.
  */
index 3933691..675ddf4 100644 (file)
@@ -87,15 +87,6 @@ static __inline__ int mtrr_del(int reg, unsigned long base, unsigned long size)
 /** Other copying of data from kernel space */
 #define DRM_COPY_TO_USER(arg1, arg2, arg3)             \
        copy_to_user(arg1, arg2, arg3)
-/* Macros for copyfrom user, but checking readability only once */
-#define DRM_VERIFYAREA_READ( uaddr, size )             \
-       (access_ok( VERIFY_READ, uaddr, size ) ? 0 : -EFAULT)
-#define DRM_COPY_FROM_USER_UNCHECKED(arg1, arg2, arg3) \
-       __copy_from_user(arg1, arg2, arg3)
-#define DRM_COPY_TO_USER_UNCHECKED(arg1, arg2, arg3)   \
-       __copy_to_user(arg1, arg2, arg3)
-#define DRM_GET_USER_UNCHECKED(val, uaddr)             \
-       __get_user(val, uaddr)
 
 #define DRM_HZ HZ
 
index c2af598..bb1bc48 100644 (file)
        {0x1002, 0x6621, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6623, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6631, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x6660, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAINAN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x6663, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAINAN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x6664, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAINAN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x6665, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAINAN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x6667, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAINAN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x666F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAINAN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6700, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6701, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6702, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \
index d09deab..fb02980 100644 (file)
@@ -37,6 +37,8 @@ struct acpi_dma_spec {
  * @dev:               struct device of this controller
  * @acpi_dma_xlate:    callback function to find a suitable channel
  * @data:              private data used by a callback function
+ * @base_request_line: first supported request line (CSRT)
+ * @end_request_line:  last supported request line (CSRT)
  */
 struct acpi_dma {
        struct list_head        dma_controllers;
@@ -44,6 +46,8 @@ struct acpi_dma {
        struct dma_chan         *(*acpi_dma_xlate)
                                (struct acpi_dma_spec *, struct acpi_dma *);
        void                    *data;
+       unsigned short          base_request_line;
+       unsigned short          end_request_line;
 };
 
 /* Used with acpi_dma_simple_xlate() */
index ec10e1b..737f90a 100644 (file)
@@ -49,10 +49,11 @@ static inline int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev)
 }
 #endif
 
-extern void cper_print_aer(const char *prefix, struct pci_dev *dev,
+extern void cper_print_aer(struct pci_dev *dev,
                           int cper_severity, struct aer_capability_regs *aer);
 extern int cper_severity_to_aer(int cper_severity);
 extern void aer_recover_queue(int domain, unsigned int bus, unsigned int devfn,
-                             int severity);
+                             int severity,
+                             struct aer_capability_regs *aer_regs);
 #endif //_AER_H_
 
index 5a6d718..b20b038 100644 (file)
@@ -84,8 +84,13 @@ extern int audit_classify_arch(int arch);
 #define        AUDIT_TYPE_CHILD_DELETE 3       /* a child being deleted */
 #define        AUDIT_TYPE_CHILD_CREATE 4       /* a child being created */
 
+/* maximized args number that audit_socketcall can process */
+#define AUDITSC_ARGS           6
+
 struct filename;
 
+extern void audit_log_session_info(struct audit_buffer *ab);
+
 #ifdef CONFIG_AUDITSYSCALL
 /* These are defined in auditsc.c */
                                /* Public API */
@@ -120,7 +125,7 @@ static inline void audit_syscall_entry(int arch, int major, unsigned long a0,
                                       unsigned long a1, unsigned long a2,
                                       unsigned long a3)
 {
-       if (unlikely(!audit_dummy_context()))
+       if (unlikely(current->audit_context))
                __audit_syscall_entry(arch, major, a0, a1, a2, a3);
 }
 static inline void audit_syscall_exit(void *pt_regs)
@@ -185,12 +190,10 @@ static inline int audit_get_sessionid(struct task_struct *tsk)
        return tsk->sessionid;
 }
 
-extern void audit_log_task_context(struct audit_buffer *ab);
-extern void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk);
 extern void __audit_ipc_obj(struct kern_ipc_perm *ipcp);
 extern void __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, umode_t mode);
 extern int __audit_bprm(struct linux_binprm *bprm);
-extern void __audit_socketcall(int nargs, unsigned long *args);
+extern int __audit_socketcall(int nargs, unsigned long *args);
 extern int __audit_sockaddr(int len, void *addr);
 extern void __audit_fd_pair(int fd1, int fd2);
 extern void __audit_mq_open(int oflag, umode_t mode, struct mq_attr *attr);
@@ -224,10 +227,11 @@ static inline int audit_bprm(struct linux_binprm *bprm)
                return __audit_bprm(bprm);
        return 0;
 }
-static inline void audit_socketcall(int nargs, unsigned long *args)
+static inline int audit_socketcall(int nargs, unsigned long *args)
 {
        if (unlikely(!audit_dummy_context()))
-               __audit_socketcall(nargs, args);
+               return __audit_socketcall(nargs, args);
+       return 0;
 }
 static inline int audit_sockaddr(int len, void *addr)
 {
@@ -340,11 +344,6 @@ static inline int audit_get_sessionid(struct task_struct *tsk)
 {
        return -1;
 }
-static inline void audit_log_task_context(struct audit_buffer *ab)
-{ }
-static inline void audit_log_task_info(struct audit_buffer *ab,
-                                      struct task_struct *tsk)
-{ }
 static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp)
 { }
 static inline void audit_ipc_set_perm(unsigned long qbytes, uid_t uid,
@@ -354,8 +353,10 @@ static inline int audit_bprm(struct linux_binprm *bprm)
 {
        return 0;
 }
-static inline void audit_socketcall(int nargs, unsigned long *args)
-{ }
+static inline int audit_socketcall(int nargs, unsigned long *args)
+{
+       return 0;
+}
 static inline void audit_fd_pair(int fd1, int fd2)
 { }
 static inline int audit_sockaddr(int len, void *addr)
@@ -390,6 +391,11 @@ static inline void audit_ptrace(struct task_struct *t)
 #define audit_signals 0
 #endif /* CONFIG_AUDITSYSCALL */
 
+static inline bool audit_loginuid_set(struct task_struct *tsk)
+{
+       return uid_valid(audit_get_loginuid(tsk));
+}
+
 #ifdef CONFIG_AUDIT
 /* These are defined in audit.c */
                                /* Public API */
@@ -429,14 +435,17 @@ static inline void            audit_log_secctx(struct audit_buffer *ab, u32 secid)
 { }
 #endif
 
+extern int audit_log_task_context(struct audit_buffer *ab);
+extern void audit_log_task_info(struct audit_buffer *ab,
+                               struct task_struct *tsk);
+
 extern int                 audit_update_lsm_rules(void);
 
                                /* Private API (for audit.c only) */
-extern int audit_filter_user(void);
+extern int audit_filter_user(int type);
 extern int audit_filter_type(int type);
 extern int  audit_receive_filter(int type, int pid, int seq,
-                               void *data, size_t datasz, kuid_t loginuid,
-                               u32 sessionid, u32 sid);
+                               void *data, size_t datasz);
 extern int audit_enabled;
 #else /* CONFIG_AUDIT */
 static inline __printf(4, 5)
@@ -476,6 +485,13 @@ static inline void audit_log_link_denied(const char *string,
 { }
 static inline void audit_log_secctx(struct audit_buffer *ab, u32 secid)
 { }
+static inline int audit_log_task_context(struct audit_buffer *ab)
+{
+       return 0;
+}
+static inline void audit_log_task_info(struct audit_buffer *ab,
+                                      struct task_struct *tsk)
+{ }
 #define audit_enabled 0
 #endif /* CONFIG_AUDIT */
 static inline void audit_log_string(struct audit_buffer *ab, const char *buf)
index f14a98a..2e34db8 100644 (file)
@@ -134,7 +134,10 @@ struct bcma_host_ops {
 #define BCMA_CORE_I2S                  0x834
 #define BCMA_CORE_SDR_DDR1_MEM_CTL     0x835   /* SDR/DDR1 memory controller core */
 #define BCMA_CORE_SHIM                 0x837   /* SHIM component in ubus/6362 */
-#define BCMA_CORE_ARM_CR4              0x83e
+#define BCMA_CORE_PHY_AC               0x83B
+#define BCMA_CORE_PCIE2                        0x83C   /* PCI Express Gen2 */
+#define BCMA_CORE_USB30_DEV            0x83D
+#define BCMA_CORE_ARM_CR4              0x83E
 #define BCMA_CORE_DEFAULT              0xFFF
 
 #define BCMA_MAX_NR_CORES              16
index b840a49..677b4f0 100644 (file)
@@ -1,3 +1,6 @@
+#ifndef _LINUX_BRCMPHY_H
+#define _LINUX_BRCMPHY_H
+
 #define PHY_ID_BCM50610                        0x0143bd60
 #define PHY_ID_BCM50610M               0x0143bd70
 #define PHY_ID_BCM5241                 0x0143bc30
@@ -29,3 +32,5 @@
 #define PHY_BRCM_CLEAR_RGMII_MODE      0x00004000
 #define PHY_BRCM_DIS_TXCRXC_NOENRGY    0x00008000
 #define PHY_BCM_FLAGS_VALID            0x80000000
+
+#endif /* _LINUX_BRCMPHY_H */
index 5047355..8bda129 100644 (file)
@@ -707,7 +707,7 @@ struct cgroup *cgroup_rightmost_descendant(struct cgroup *pos);
  *
  * If a subsystem synchronizes against the parent in its ->css_online() and
  * before starting iterating, and synchronizes against @pos on each
- * iteration, any descendant cgroup which finished ->css_offline() is
+ * iteration, any descendant cgroup which finished ->css_online() is
  * guaranteed to be visible in the future iterations.
  *
  * In other words, the following guarantees that a descendant can't escape
index d53c353..7f0c1dd 100644 (file)
@@ -673,6 +673,8 @@ int __compat_save_altstack(compat_stack_t __user *, unsigned long);
 asmlinkage long compat_sys_sched_rr_get_interval(compat_pid_t pid,
                                                 struct compat_timespec __user *interval);
 
+asmlinkage long compat_sys_fanotify_mark(int, unsigned int, __u32, __u32,
+                                           int, const char __user *);
 #else
 
 #define is_compat_task() (0)
index c6f6e08..9f3c7e8 100644 (file)
@@ -175,6 +175,8 @@ extern struct bus_type cpu_subsys;
 
 extern void get_online_cpus(void);
 extern void put_online_cpus(void);
+extern void cpu_hotplug_disable(void);
+extern void cpu_hotplug_enable(void);
 #define hotcpu_notifier(fn, pri)       cpu_notifier(fn, pri)
 #define register_hotcpu_notifier(nb)   register_cpu_notifier(nb)
 #define unregister_hotcpu_notifier(nb) unregister_cpu_notifier(nb)
@@ -198,6 +200,8 @@ static inline void cpu_hotplug_driver_unlock(void)
 
 #define get_online_cpus()      do { } while (0)
 #define put_online_cpus()      do { } while (0)
+#define cpu_hotplug_disable()  do { } while (0)
+#define cpu_hotplug_enable()   do { } while (0)
 #define hotcpu_notifier(fn, pri)       do { (void)(fn); } while (0)
 /* These aren't inline functions due to a GCC bug. */
 #define register_hotcpu_notifier(nb)   ({ (void)(nb); 0; })
index 3c86faa..8f04062 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/completion.h>
 #include <linux/hrtimer.h>
 
-#define CPUIDLE_STATE_MAX      8
+#define CPUIDLE_STATE_MAX      10
 #define CPUIDLE_NAME_LEN       16
 #define CPUIDLE_DESC_LEN       32
 
index 1e483fa..3cd3247 100644 (file)
@@ -79,11 +79,26 @@ typedef int (*dm_ioctl_fn) (struct dm_target *ti, unsigned int cmd,
 typedef int (*dm_merge_fn) (struct dm_target *ti, struct bvec_merge_data *bvm,
                            struct bio_vec *biovec, int max_size);
 
+/*
+ * These iteration functions are typically used to check (and combine)
+ * properties of underlying devices.
+ * E.g. Does at least one underlying device support flush?
+ *      Does any underlying device not support WRITE_SAME?
+ *
+ * The callout function is called once for each contiguous section of
+ * an underlying device.  State can be maintained in *data.
+ * Return non-zero to stop iterating through any further devices.
+ */
 typedef int (*iterate_devices_callout_fn) (struct dm_target *ti,
                                           struct dm_dev *dev,
                                           sector_t start, sector_t len,
                                           void *data);
 
+/*
+ * This function must iterate through each section of device used by the
+ * target until it encounters a non-zero return code, which it then returns.
+ * Returns zero if no callout returned non-zero.
+ */
 typedef int (*dm_iterate_devices_fn) (struct dm_target *ti,
                                      iterate_devices_callout_fn fn,
                                      void *data);
index c050dcc..f65f5a6 100644 (file)
@@ -46,6 +46,7 @@ extern int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk);
 extern int sk_detach_filter(struct sock *sk);
 extern int sk_chk_filter(struct sock_filter *filter, unsigned int flen);
 extern int sk_get_filter(struct sock *sk, struct sock_filter __user *filter, unsigned len);
+extern void sk_decode_filter(struct sock_filter *filt, struct sock_filter *to);
 
 #ifdef CONFIG_BPF_JIT
 #include <stdarg.h>
index f83e17a..99d0fbc 100644 (file)
@@ -90,6 +90,8 @@ typedef void (*ftrace_func_t)(unsigned long ip, unsigned long parent_ip,
  *            not set this, then the ftrace infrastructure will add recursion
  *            protection for the caller.
  * STUB   - The ftrace_ops is just a place holder.
+ * INITIALIZED - The ftrace_ops has already been initialized (first use time
+ *            register_ftrace_function() is called, it will initialized the ops)
  */
 enum {
        FTRACE_OPS_FL_ENABLED                   = 1 << 0,
@@ -100,6 +102,7 @@ enum {
        FTRACE_OPS_FL_SAVE_REGS_IF_SUPPORTED    = 1 << 5,
        FTRACE_OPS_FL_RECURSION_SAFE            = 1 << 6,
        FTRACE_OPS_FL_STUB                      = 1 << 7,
+       FTRACE_OPS_FL_INITIALIZED               = 1 << 8,
 };
 
 struct ftrace_ops {
@@ -110,6 +113,7 @@ struct ftrace_ops {
 #ifdef CONFIG_DYNAMIC_FTRACE
        struct ftrace_hash              *notrace_hash;
        struct ftrace_hash              *filter_hash;
+       struct mutex                    regex_lock;
 #endif
 };
 
index 34e00fb..4372658 100644 (file)
@@ -293,6 +293,7 @@ struct ftrace_event_file {
         * caching and such. Which is mostly OK ;-)
         */
        unsigned long           flags;
+       atomic_t                sm_ref; /* soft-mode reference counter */
 };
 
 #define __TRACE_EVENT_FLAGS(name, value)                               \
index 4474557..16fae64 100644 (file)
@@ -249,12 +249,12 @@ team_get_first_port_txable_rcu(struct team *team, struct team_port *port)
                return port;
        cur = port;
        list_for_each_entry_continue_rcu(cur, &team->port_list, list)
-               if (team_port_txable(port))
+               if (team_port_txable(cur))
                        return cur;
        list_for_each_entry_rcu(cur, &team->port_list, list) {
                if (cur == port)
                        break;
-               if (team_port_txable(port))
+               if (team_port_txable(cur))
                        return cur;
        }
        return NULL;
index 13a3da2..98cd41b 100644 (file)
@@ -30,15 +30,19 @@ struct journal_head {
 
        /*
         * Journalling list for this buffer [jbd_lock_bh_state()]
+        * NOTE: We *cannot* combine this with b_modified into a bitfield
+        * as gcc would then (which the C standard allows but which is
+        * very unuseful) make 64-bit accesses to the bitfield and clobber
+        * b_jcount if its update races with bitfield modification.
         */
-       unsigned b_jlist:4;
+       unsigned b_jlist;
 
        /*
         * This flag signals the buffer has been modified by
         * the currently running transaction
         * [jbd_lock_bh_state()]
         */
-       unsigned b_modified:1;
+       unsigned b_modified;
 
        /*
         * Copy of the buffer data frozen for writing to the log.
index e96329c..e9ef6d6 100644 (file)
@@ -562,6 +562,9 @@ int __trace_bprintk(unsigned long ip, const char *fmt, ...);
 extern __printf(2, 3)
 int __trace_printk(unsigned long ip, const char *fmt, ...);
 
+extern int __trace_bputs(unsigned long ip, const char *str);
+extern int __trace_puts(unsigned long ip, const char *str, int size);
+
 /**
  * trace_puts - write a string into the ftrace buffer
  * @str: the string to record
@@ -587,8 +590,6 @@ int __trace_printk(unsigned long ip, const char *fmt, ...);
  *  (1 when __trace_bputs is used, strlen(str) when __trace_puts is used)
  */
 
-extern int __trace_bputs(unsigned long ip, const char *str);
-extern int __trace_puts(unsigned long ip, const char *str, int size);
 #define trace_puts(str) ({                                             \
        static const char *trace_printk_fmt                             \
                __attribute__((section("__trace_printk_fmt"))) =        \
index e15828f..484604d 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/atomic.h>
 #include <linux/kernel.h>
 #include <linux/mutex.h>
+#include <linux/spinlock.h>
 
 struct kref {
        atomic_t refcount;
@@ -98,6 +99,38 @@ static inline int kref_put(struct kref *kref, void (*release)(struct kref *kref)
        return kref_sub(kref, 1, release);
 }
 
+/**
+ * kref_put_spinlock_irqsave - decrement refcount for object.
+ * @kref: object.
+ * @release: pointer to the function that will clean up the object when the
+ *          last reference to the object is released.
+ *          This pointer is required, and it is not acceptable to pass kfree
+ *          in as this function.
+ * @lock: lock to take in release case
+ *
+ * Behaves identical to kref_put with one exception.  If the reference count
+ * drops to zero, the lock will be taken atomically wrt dropping the reference
+ * count.  The release function has to call spin_unlock() without _irqrestore.
+ */
+static inline int kref_put_spinlock_irqsave(struct kref *kref,
+               void (*release)(struct kref *kref),
+               spinlock_t *lock)
+{
+       unsigned long flags;
+
+       WARN_ON(release == NULL);
+       if (atomic_add_unless(&kref->refcount, -1, 1))
+               return 0;
+       spin_lock_irqsave(lock, flags);
+       if (atomic_dec_and_test(&kref->refcount)) {
+               release(kref);
+               local_irq_restore(flags);
+               return 1;
+       }
+       spin_unlock_irqrestore(lock, flags);
+       return 0;
+}
+
 static inline int kref_put_mutex(struct kref *kref,
                                 void (*release)(struct kref *kref),
                                 struct mutex *lock)
index 6a1f8df..b83e565 100644 (file)
@@ -361,6 +361,17 @@ static inline void list_splice_tail_init(struct list_head *list,
 #define list_first_entry(ptr, type, member) \
        list_entry((ptr)->next, type, member)
 
+/**
+ * list_first_entry_or_null - get the first element from a list
+ * @ptr:       the list head to take the element from.
+ * @type:      the type of the struct this is embedded in.
+ * @member:    the name of the list_struct within the struct.
+ *
+ * Note that if the list is empty, it returns NULL.
+ */
+#define list_first_entry_or_null(ptr, type, member) \
+       (!list_empty(ptr) ? list_first_entry(ptr, type, member) : NULL)
+
 /**
  * list_for_each       -       iterate over a list
  * @pos:       the &struct list_head to use as a loop cursor.
index b8ba855..2913b86 100644 (file)
@@ -6,7 +6,8 @@
 
 #if BITS_PER_LONG == 64
 
-#define div64_long(x,y) div64_s64((x),(y))
+#define div64_long(x, y) div64_s64((x), (y))
+#define div64_ul(x, y)   div64_u64((x), (y))
 
 /**
  * div_u64_rem - unsigned 64bit divide with 32bit divisor with remainder
@@ -47,7 +48,8 @@ static inline s64 div64_s64(s64 dividend, s64 divisor)
 
 #elif BITS_PER_LONG == 32
 
-#define div64_long(x,y) div_s64((x),(y))
+#define div64_long(x, y) div_s64((x), (y))
+#define div64_ul(x, y)   div_u64((x), (y))
 
 #ifndef div_u64_rem
 static inline u64 div_u64_rem(u64 dividend, u32 divisor, u32 *remainder)
index fb1bf7d..0390d59 100644 (file)
@@ -373,13 +373,11 @@ struct ab8500_sysctrl_platform_data;
 /**
  * struct ab8500_platform_data - AB8500 platform data
  * @irq_base: start of AB8500 IRQs, AB8500_NR_IRQS will be used
- * @pm_power_off: Should machine pm power off hook be registered or not
  * @init: board-specific initialization after detection of ab8500
  * @regulator: machine-specific constraints for regulators
  */
 struct ab8500_platform_data {
        int irq_base;
-       bool pm_power_off;
        void (*init) (struct ab8500 *);
        struct ab8500_regulator_platform_data *regulator;
        struct abx500_gpio_platform_data *gpio;
index 67f46ad..352eec9 100644 (file)
@@ -126,7 +126,7 @@ struct mlx4_rss_context {
 
 struct mlx4_qp_path {
        u8                      fl;
-       u8                      reserved1[1];
+       u8                      vlan_control;
        u8                      disable_pkey_check;
        u8                      pkey_index;
        u8                      counter_index;
@@ -141,11 +141,32 @@ struct mlx4_qp_path {
        u8                      sched_queue;
        u8                      vlan_index;
        u8                      feup;
-       u8                      reserved3;
+       u8                      fvl_rx;
        u8                      reserved4[2];
        u8                      dmac[6];
 };
 
+enum { /* fl */
+       MLX4_FL_CV      = 1 << 6,
+       MLX4_FL_ETH_HIDE_CQE_VLAN       = 1 << 2
+};
+enum { /* vlan_control */
+       MLX4_VLAN_CTRL_ETH_TX_BLOCK_TAGGED      = 1 << 6,
+       MLX4_VLAN_CTRL_ETH_RX_BLOCK_TAGGED      = 1 << 2,
+       MLX4_VLAN_CTRL_ETH_RX_BLOCK_PRIO_TAGGED = 1 << 1, /* 802.1p priority tag */
+       MLX4_VLAN_CTRL_ETH_RX_BLOCK_UNTAGGED    = 1 << 0
+};
+
+enum { /* feup */
+       MLX4_FEUP_FORCE_ETH_UP          = 1 << 6, /* force Eth UP */
+       MLX4_FSM_FORCE_ETH_SRC_MAC      = 1 << 5, /* force Source MAC */
+       MLX4_FVL_FORCE_ETH_VLAN         = 1 << 3  /* force Eth vlan */
+};
+
+enum { /* fvl_rx */
+       MLX4_FVL_RX_FORCE_ETH_VLAN      = 1 << 0 /* enforce Eth rx vlan */
+};
+
 struct mlx4_qp_context {
        __be32                  flags;
        __be32                  pd;
@@ -185,6 +206,10 @@ struct mlx4_qp_context {
        u32                     reserved5[10];
 };
 
+enum { /* param3 */
+       MLX4_STRIP_VLAN = 1 << 30
+};
+
 /* Which firmware version adds support for NEC (NoErrorCompletion) bit */
 #define MLX4_FW_VER_WQE_CTRL_NEC mlx4_fw_ver(2, 2, 232)
 
index a94a5a0..60584b1 100644 (file)
@@ -2733,6 +2733,17 @@ static inline netdev_features_t netdev_get_wanted_features(
 }
 netdev_features_t netdev_increment_features(netdev_features_t all,
        netdev_features_t one, netdev_features_t mask);
+
+/* Allow TSO being used on stacked device :
+ * Performing the GSO segmentation before last device
+ * is a performance improvement.
+ */
+static inline netdev_features_t netdev_add_tso_features(netdev_features_t features,
+                                                       netdev_features_t mask)
+{
+       return netdev_increment_features(features, NETIF_F_ALL_TSO, mask);
+}
+
 int __netdev_update_features(struct net_device *dev);
 void netdev_update_features(struct net_device *dev);
 void netdev_change_features(struct net_device *dev);
index 98ffb54..2d4df6c 100644 (file)
@@ -17,6 +17,22 @@ extern __sum16 nf_ip6_checksum(struct sk_buff *skb, unsigned int hook,
 
 extern int ipv6_netfilter_init(void);
 extern void ipv6_netfilter_fini(void);
+
+/*
+ * Hook functions for ipv6 to allow xt_* modules to be built-in even
+ * if IPv6 is a module.
+ */
+struct nf_ipv6_ops {
+       int (*chk_addr)(struct net *net, const struct in6_addr *addr,
+                       const struct net_device *dev, int strict);
+};
+
+extern const struct nf_ipv6_ops __rcu *nf_ipv6_ops;
+static inline const struct nf_ipv6_ops *nf_get_ipv6_ops(void)
+{
+       return rcu_dereference(nf_ipv6_ops);
+}
+
 #else /* CONFIG_NETFILTER */
 static inline int ipv6_netfilter_init(void) { return 0; }
 static inline void ipv6_netfilter_fini(void) { return; }
index 3863a4d..2a93b64 100644 (file)
  *
  */
 
-#ifdef CONFIG_OF_DEVICE
 #include <linux/device.h>
 #include <linux/mod_devicetable.h>
+
+#ifdef CONFIG_OF_DEVICE
 #include <linux/pm.h>
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
@@ -100,7 +101,7 @@ extern int of_platform_populate(struct device_node *root,
 
 #if !defined(CONFIG_OF_ADDRESS)
 struct of_dev_auxdata;
-struct device;
+struct device_node;
 static inline int of_platform_populate(struct device_node *root,
                                        const struct of_device_id *matches,
                                        const struct of_dev_auxdata *lookup,
index 81b3161..1704479 100644 (file)
@@ -60,11 +60,13 @@ static inline void acpi_pci_slot_remove(struct pci_bus *bus) { }
 void acpiphp_init(void);
 void acpiphp_enumerate_slots(struct pci_bus *bus, acpi_handle handle);
 void acpiphp_remove_slots(struct pci_bus *bus);
+void acpiphp_check_host_bridge(acpi_handle handle);
 #else
 static inline void acpiphp_init(void) { }
 static inline void acpiphp_enumerate_slots(struct pci_bus *bus,
                                           acpi_handle handle) { }
 static inline void acpiphp_remove_slots(struct pci_bus *bus) { }
+static inline void acpiphp_check_host_bridge(acpi_handle handle) { }
 #endif
 
 #else  /* CONFIG_ACPI */
index 2b85c52..c129162 100644 (file)
 #define PCI_DEVICE_ID_TIGON3_5705M_2   0x165e
 #define PCI_DEVICE_ID_NX2_57712                0x1662
 #define PCI_DEVICE_ID_NX2_57712E       0x1663
+#define PCI_DEVICE_ID_NX2_57712_MF     0x1663
 #define PCI_DEVICE_ID_TIGON3_5714      0x1668
 #define PCI_DEVICE_ID_TIGON3_5714S     0x1669
 #define PCI_DEVICE_ID_TIGON3_5780      0x166a
 #define PCI_DEVICE_ID_TIGON3_5780S     0x166b
 #define PCI_DEVICE_ID_TIGON3_5705F     0x166e
+#define PCI_DEVICE_ID_NX2_57712_VF     0x166f
 #define PCI_DEVICE_ID_TIGON3_5754M     0x1672
 #define PCI_DEVICE_ID_TIGON3_5755M     0x1673
 #define PCI_DEVICE_ID_TIGON3_5756      0x1674
 #define PCI_DEVICE_ID_TIGON3_5787      0x169b
 #define PCI_DEVICE_ID_TIGON3_5788      0x169c
 #define PCI_DEVICE_ID_TIGON3_5789      0x169d
+#define PCI_DEVICE_ID_NX2_57840_4_10   0x16a1
+#define PCI_DEVICE_ID_NX2_57840_2_20   0x16a2
+#define PCI_DEVICE_ID_NX2_57840_MF     0x16a4
 #define PCI_DEVICE_ID_NX2_57800_MF     0x16a5
 #define PCI_DEVICE_ID_TIGON3_5702X     0x16a6
 #define PCI_DEVICE_ID_TIGON3_5703X     0x16a7
 #define PCI_DEVICE_ID_TIGON3_5704S     0x16a8
 #define PCI_DEVICE_ID_NX2_57800_VF     0x16a9
 #define PCI_DEVICE_ID_NX2_5706S                0x16aa
-#define PCI_DEVICE_ID_NX2_57840_MF     0x16a4
 #define PCI_DEVICE_ID_NX2_5708S                0x16ac
 #define PCI_DEVICE_ID_NX2_57840_VF     0x16ad
 #define PCI_DEVICE_ID_NX2_57810_MF     0x16ae
index 72474e1..6aa2380 100644 (file)
  *     if it is 0, pull-down is disabled.
  * @PIN_CONFIG_DRIVE_PUSH_PULL: the pin will be driven actively high and
  *     low, this is the most typical case and is typically achieved with two
- *     active transistors on the output. Sending this config will enabale
+ *     active transistors on the output. Setting this config will enable
  *     push-pull mode, the argument is ignored.
  * @PIN_CONFIG_DRIVE_OPEN_DRAIN: the pin will be driven with open drain (open
  *     collector) which means it is usually wired with other output ports
- *     which are then pulled up with an external resistor. Sending this
- *     config will enabale open drain mode, the argument is ignored.
+ *     which are then pulled up with an external resistor. Setting this
+ *     config will enable open drain mode, the argument is ignored.
  * @PIN_CONFIG_DRIVE_OPEN_SOURCE: the pin will be driven with open source
- *     (open emitter). Sending this config will enabale open drain mode, the
+ *     (open emitter). Setting this config will enable open drain mode, the
  *     argument is ignored.
- * @PIN_CONFIG_DRIVE_STRENGTH: the pin will output the current passed as
- *     argument. The argument is in mA.
+ * @PIN_CONFIG_DRIVE_STRENGTH: the pin will sink or source at most the current
+ *     passed as argument. The argument is in mA.
  * @PIN_CONFIG_INPUT_SCHMITT_ENABLE: control schmitt-trigger mode on the pin.
  *      If the argument != 0, schmitt-trigger mode is enabled. If it's 0,
  *      schmitt-trigger mode is disabled.
index 528e73c..2390199 100644 (file)
 #ifndef __CLK_LPSS_H
 #define __CLK_LPSS_H
 
+struct lpss_clk_data {
+       const char *name;
+       struct clk *clk;
+};
+
 extern int lpt_clk_init(void);
 
 #endif /* __CLK_LPSS_H */
index ff9b0aa..c860c1b 100644 (file)
@@ -43,8 +43,6 @@ struct omap_uart_port_info {
        int                     DTR_present;
 
        int (*get_context_loss_count)(struct device *);
-       void (*set_forceidle)(struct device *);
-       void (*set_noidle)(struct device *);
        void (*enable_wakeup)(struct device *, bool);
 };
 
index 6af944a..22c7052 100644 (file)
@@ -4,6 +4,7 @@
 #include <stdarg.h>
 #include <linux/init.h>
 #include <linux/kern_levels.h>
+#include <linux/linkage.h>
 
 extern const char linux_banner[];
 extern const char linux_proc_banner[];
index 8089e35..f4b1001 100644 (file)
@@ -460,6 +460,26 @@ static inline void hlist_add_after_rcu(struct hlist_node *prev,
                pos = hlist_entry_safe(rcu_dereference_raw(hlist_next_rcu(\
                        &(pos)->member)), typeof(*(pos)), member))
 
+/**
+ * hlist_for_each_entry_rcu_notrace - iterate over rcu list of given type (for tracing)
+ * @pos:       the type * to use as a loop cursor.
+ * @head:      the head for your list.
+ * @member:    the name of the hlist_node within the struct.
+ *
+ * This list-traversal primitive may safely run concurrently with
+ * the _rcu list-mutation primitives such as hlist_add_head_rcu()
+ * as long as the traversal is guarded by rcu_read_lock().
+ *
+ * This is the same as hlist_for_each_entry_rcu() except that it does
+ * not do any RCU debugging or tracing.
+ */
+#define hlist_for_each_entry_rcu_notrace(pos, head, member)                    \
+       for (pos = hlist_entry_safe (rcu_dereference_raw_notrace(hlist_first_rcu(head)),\
+                       typeof(*(pos)), member);                        \
+               pos;                                                    \
+               pos = hlist_entry_safe(rcu_dereference_raw_notrace(hlist_next_rcu(\
+                       &(pos)->member)), typeof(*(pos)), member))
+
 /**
  * hlist_for_each_entry_rcu_bh - iterate over rcu list of given type
  * @pos:       the type * to use as a loop cursor.
index 2ae1371..1c33dd7 100644 (file)
@@ -105,9 +105,14 @@ static inline void hlist_nulls_add_head_rcu(struct hlist_nulls_node *n,
  * @head:      the head for your list.
  * @member:    the name of the hlist_nulls_node within the struct.
  *
+ * The barrier() is needed to make sure compiler doesn't cache first element [1],
+ * as this loop can be restarted [2]
+ * [1] Documentation/atomic_ops.txt around line 114
+ * [2] Documentation/RCU/rculist_nulls.txt around line 146
  */
 #define hlist_nulls_for_each_entry_rcu(tpos, pos, head, member)                        \
-       for (pos = rcu_dereference_raw(hlist_nulls_first_rcu(head));            \
+       for (({barrier();}),                                                    \
+            pos = rcu_dereference_raw(hlist_nulls_first_rcu(head));            \
                (!is_a_nulls(pos)) &&                                           \
                ({ tpos = hlist_nulls_entry(pos, typeof(*tpos), member); 1; }); \
                pos = rcu_dereference_raw(hlist_nulls_next_rcu(pos)))
index 4ccd68e..ddcc782 100644 (file)
@@ -640,6 +640,15 @@ static inline void rcu_preempt_sleep_check(void)
 
 #define rcu_dereference_raw(p) rcu_dereference_check(p, 1) /*@@@ needed? @@@*/
 
+/*
+ * The tracing infrastructure traces RCU (we want that), but unfortunately
+ * some of the RCU checks causes tracing to lock up the system.
+ *
+ * The tracing version of rcu_dereference_raw() must not call
+ * rcu_read_lock_held().
+ */
+#define rcu_dereference_raw_notrace(p) __rcu_dereference_check((p), 1, __rcu)
+
 /**
  * rcu_access_index() - fetch RCU index with no dereferencing
  * @p: The index to read
index a3e7842..18e0993 100644 (file)
@@ -83,7 +83,6 @@
 
 extern struct bus_type rio_bus_type;
 extern struct device rio_bus;
-extern struct list_head rio_devices;   /* list of all devices */
 
 struct rio_mport;
 struct rio_dev;
@@ -237,6 +236,7 @@ enum rio_phy_type {
  * @name: Port name string
  * @priv: Master port private data
  * @dma: DMA device associated with mport
+ * @nscan: RapidIO network enumeration/discovery operations
  */
 struct rio_mport {
        struct list_head dbells;        /* list of doorbell events */
@@ -262,8 +262,14 @@ struct rio_mport {
 #ifdef CONFIG_RAPIDIO_DMA_ENGINE
        struct dma_device       dma;
 #endif
+       struct rio_scan *nscan;
 };
 
+/*
+ * Enumeration/discovery control flags
+ */
+#define RIO_SCAN_ENUM_NO_WAIT  0x00000001 /* Do not wait for enum completed */
+
 struct rio_id_table {
        u16 start;      /* logical minimal id */
        u32 max;        /* max number of IDs in table */
@@ -460,6 +466,16 @@ static inline struct rio_mport *dma_to_mport(struct dma_device *ddev)
 }
 #endif /* CONFIG_RAPIDIO_DMA_ENGINE */
 
+/**
+ * struct rio_scan - RIO enumeration and discovery operations
+ * @enumerate: Callback to perform RapidIO fabric enumeration.
+ * @discover: Callback to perform RapidIO fabric discovery.
+ */
+struct rio_scan {
+       int (*enumerate)(struct rio_mport *mport, u32 flags);
+       int (*discover)(struct rio_mport *mport, u32 flags);
+};
+
 /* Architecture and hardware-specific functions */
 extern int rio_register_mport(struct rio_mport *);
 extern int rio_open_inb_mbox(struct rio_mport *, void *, int, int);
index b75c059..5059994 100644 (file)
@@ -433,5 +433,6 @@ extern u16 rio_local_get_device_id(struct rio_mport *port);
 extern struct rio_dev *rio_get_device(u16 vid, u16 did, struct rio_dev *from);
 extern struct rio_dev *rio_get_asm(u16 vid, u16 did, u16 asm_vid, u16 asm_did,
                                   struct rio_dev *from);
+extern int rio_init_mports(void);
 
 #endif                         /* LINUX_RIO_DRV_H */
index 5951e3f..2680677 100644 (file)
@@ -111,6 +111,9 @@ static inline struct page *sg_page(struct scatterlist *sg)
 static inline void sg_set_buf(struct scatterlist *sg, const void *buf,
                              unsigned int buflen)
 {
+#ifdef CONFIG_DEBUG_SG
+       BUG_ON(!virt_addr_valid(buf));
+#endif
        sg_set_page(sg, virt_to_page(buf), buflen, offset_in_page(buf));
 }
 
index caa8f4d..178a8d9 100644 (file)
@@ -593,6 +593,7 @@ struct signal_struct {
 #endif
 #ifdef CONFIG_AUDIT
        unsigned audit_tty;
+       unsigned audit_tty_log_passwd;
        struct tty_audit_buf *tty_audit_buf;
 #endif
 #ifdef CONFIG_CGROUPS
index 2e0ced1..9c676ea 100644 (file)
@@ -2852,6 +2852,21 @@ static inline int skb_tnl_header_len(const struct sk_buff *inner_skb)
                SKB_GSO_CB(inner_skb)->mac_offset;
 }
 
+static inline int gso_pskb_expand_head(struct sk_buff *skb, int extra)
+{
+       int new_headroom, headroom;
+       int ret;
+
+       headroom = skb_headroom(skb);
+       ret = pskb_expand_head(skb, extra, 0, GFP_ATOMIC);
+       if (ret)
+               return ret;
+
+       new_headroom = skb_headroom(skb);
+       SKB_GSO_CB(skb)->mac_offset += (new_headroom - headroom);
+       return 0;
+}
+
 static inline bool skb_is_gso(const struct sk_buff *skb)
 {
        return skb_shinfo(skb)->gso_size;
index 428c37a..b10ce4b 100644 (file)
@@ -305,7 +305,6 @@ struct ucred {
 
 extern void cred_to_ucred(struct pid *pid, const struct cred *cred, struct ucred *ucred);
 
-extern int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len);
 extern int memcpy_fromiovecend(unsigned char *kdata, const struct iovec *iov,
                               int offset, int len);
 extern int csum_partial_copy_fromiovecend(unsigned char *kdata, 
@@ -314,7 +313,6 @@ extern int csum_partial_copy_fromiovecend(unsigned char *kdata,
                                          unsigned int len, __wsum *csump);
 
 extern int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr_storage *address, int mode);
-extern int memcpy_toiovec(struct iovec *v, unsigned char *kdata, int len);
 extern int memcpy_toiovecend(const struct iovec *v, unsigned char *kdata,
                             int offset, int len);
 extern int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr_storage *kaddr);
@@ -322,6 +320,9 @@ extern int put_cmsg(struct msghdr*, int level, int type, int len, void *data);
 
 struct timespec;
 
+/* The __sys_...msg variants allow MSG_CMSG_COMPAT */
+extern long __sys_recvmsg(int fd, struct msghdr __user *msg, unsigned flags);
+extern long __sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags);
 extern int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
                          unsigned int flags, struct timespec *timeout);
 extern int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg,
index 733eb5e..6ff26c8 100644 (file)
@@ -57,7 +57,7 @@ extern struct bus_type spi_bus_type;
  * @modalias: Name of the driver to use with this device, or an alias
  *     for that name.  This appears in the sysfs "modalias" attribute
  *     for driver coldplugging, and in uevents used for hotplugging
- * @cs_gpio: gpio number of the chipselect line (optional, -EINVAL when
+ * @cs_gpio: gpio number of the chipselect line (optional, -ENOENT when
  *     when not using a GPIO line)
  *
  * A @spi_device is used to interchange data between an SPI slave
@@ -266,7 +266,7 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
  *     queue so the subsystem notifies the driver that it may relax the
  *     hardware by issuing this call
  * @cs_gpios: Array of GPIOs to use as chip select lines; one per CS
- *     number. Any individual value may be -EINVAL for CS lines that
+ *     number. Any individual value may be -ENOENT for CS lines that
  *     are not GPIOs (driven by the SPI controller itself).
  *
  * Each SPI master controller can communicate with one or more @spi_device
index 47ead51..c5fd30d 100644 (file)
@@ -137,6 +137,7 @@ static inline void make_migration_entry_read(swp_entry_t *entry)
 
 extern void migration_entry_wait(struct mm_struct *mm, pmd_t *pmd,
                                        unsigned long address);
+extern void migration_entry_wait_huge(struct mm_struct *mm, pte_t *pte);
 #else
 
 #define make_migration_entry(page, write) swp_entry(0, 0)
@@ -148,6 +149,8 @@ static inline int is_migration_entry(swp_entry_t swp)
 static inline void make_migration_entry_read(swp_entry_t *entryp) { }
 static inline void migration_entry_wait(struct mm_struct *mm, pmd_t *pmd,
                                         unsigned long address) { }
+static inline void migration_entry_wait_huge(struct mm_struct *mm,
+                                       pte_t *pte) { }
 static inline int is_write_migration_entry(swp_entry_t entry)
 {
        return 0;
index 3891139..98a3153 100644 (file)
@@ -44,8 +44,8 @@
 /* Return size of the log buffer */
 #define SYSLOG_ACTION_SIZE_BUFFER   10
 
-#define SYSLOG_FROM_CALL 0
-#define SYSLOG_FROM_FILE 1
+#define SYSLOG_FROM_READER           0
+#define SYSLOG_FROM_PROC             1
 
 int do_syslog(int type, char __user *buf, int count, bool from_file);
 
index 22d81b3..d5d229b 100644 (file)
@@ -117,14 +117,10 @@ static inline bool timespec_valid_strict(const struct timespec *ts)
 
 extern bool persistent_clock_exist;
 
-#ifdef ALWAYS_USE_PERSISTENT_CLOCK
-#define has_persistent_clock() true
-#else
 static inline bool has_persistent_clock(void)
 {
        return persistent_clock_exist;
 }
-#endif
 
 extern void read_persistent_clock(struct timespec *ts);
 extern void read_boot_clock(struct timespec *ts);
index 7e92bd8..8780bd2 100644 (file)
@@ -575,8 +575,7 @@ extern void tty_audit_exit(void);
 extern void tty_audit_fork(struct signal_struct *sig);
 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_task(struct task_struct *tsk,
-                              kuid_t loginuid, u32 sessionid);
+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)
@@ -594,8 +593,7 @@ static inline void tty_audit_fork(struct signal_struct *sig)
 static inline void tty_audit_push(struct tty_struct *tty)
 {
 }
-static inline int tty_audit_push_task(struct task_struct *tsk,
-                                     kuid_t loginuid, u32 sessionid)
+static inline int tty_audit_push_current(void)
 {
        return 0;
 }
index 629aaf5..c55ce24 100644 (file)
@@ -35,4 +35,7 @@ static inline size_t iov_length(const struct iovec *iov, unsigned long nr_segs)
 }
 
 unsigned long iov_shorten(struct iovec *iov, unsigned long nr_segs, size_t to);
+
+int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len);
+int memcpy_toiovec(struct iovec *iov, unsigned char *kdata, int len);
 #endif
index c454a88..f1b0dca 100644 (file)
@@ -563,9 +563,8 @@ static inline int gadget_is_dualspeed(struct usb_gadget *g)
 }
 
 /**
- * gadget_is_superspeed() - return true if the hardware handles
- * supperspeed
- * @g: controller that might support supper speed
+ * gadget_is_superspeed() - return true if the hardware handles superspeed
+ * @g: controller that might support superspeed
  */
 static inline int gadget_is_superspeed(struct usb_gadget *g)
 {
index b9b0f7b..302ddf5 100644 (file)
@@ -268,6 +268,8 @@ struct usb_serial_driver {
                        struct usb_serial_port *port, struct ktermios *old);
        void (*break_ctl)(struct tty_struct *tty, int break_state);
        int  (*chars_in_buffer)(struct tty_struct *tty);
+       void (*wait_until_sent)(struct tty_struct *tty, long timeout);
+       bool (*tx_empty)(struct usb_serial_port *port);
        void (*throttle)(struct tty_struct *tty);
        void (*unthrottle)(struct tty_struct *tty);
        int  (*tiocmget)(struct tty_struct *tty);
@@ -327,6 +329,8 @@ extern void usb_serial_generic_close(struct usb_serial_port *port);
 extern int usb_serial_generic_resume(struct usb_serial *serial);
 extern int usb_serial_generic_write_room(struct tty_struct *tty);
 extern int usb_serial_generic_chars_in_buffer(struct tty_struct *tty);
+extern void usb_serial_generic_wait_until_sent(struct tty_struct *tty,
+                                                               long timeout);
 extern void usb_serial_generic_read_bulk_callback(struct urb *urb);
 extern void usb_serial_generic_write_bulk_callback(struct urb *urb);
 extern void usb_serial_generic_throttle(struct tty_struct *tty);
index e8d6571..0d33fca 100644 (file)
@@ -36,7 +36,7 @@ extern int fg_console, last_console, want_console;
 int vc_allocate(unsigned int console);
 int vc_cons_allocated(unsigned int console);
 int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines);
-void vc_deallocate(unsigned int console);
+struct vc_data *vc_deallocate(unsigned int console);
 void reset_palette(struct vc_data *vc);
 void do_blank_screen(int entering_gfx);
 void do_unblank_screen(int leaving_gfx);
index ac38be2..1133695 100644 (file)
@@ -217,6 +217,8 @@ do {                                                                        \
                if (!ret)                                               \
                        break;                                          \
        }                                                               \
+       if (!ret && (condition))                                        \
+               ret = 1;                                                \
        finish_wait(&wq, &__wait);                                      \
 } while (0)
 
@@ -233,8 +235,9 @@ do {                                                                        \
  * wake_up() has to be called after changing any variable that could
  * change the result of the wait condition.
  *
- * The function returns 0 if the @timeout elapsed, and the remaining
- * jiffies if the condition evaluated to true before the timeout elapsed.
+ * The function returns 0 if the @timeout elapsed, or the remaining
+ * jiffies (at least 1) if the @condition evaluated to %true before
+ * the @timeout elapsed.
  */
 #define wait_event_timeout(wq, condition, timeout)                     \
 ({                                                                     \
@@ -302,6 +305,8 @@ do {                                                                        \
                ret = -ERESTARTSYS;                                     \
                break;                                                  \
        }                                                               \
+       if (!ret && (condition))                                        \
+               ret = 1;                                                \
        finish_wait(&wq, &__wait);                                      \
 } while (0)
 
@@ -318,9 +323,10 @@ do {                                                                       \
  * wake_up() has to be called after changing any variable that could
  * change the result of the wait condition.
  *
- * The function returns 0 if the @timeout elapsed, -ERESTARTSYS if it
- * was interrupted by a signal, and the remaining jiffies otherwise
- * if the condition evaluated to true before the timeout elapsed.
+ * Returns:
+ * 0 if the @timeout elapsed, -%ERESTARTSYS if it was interrupted by
+ * a signal, or the remaining jiffies (at least 1) if the @condition
+ * evaluated to %true before the @timeout elapsed.
  */
 #define wait_event_interruptible_timeout(wq, condition, timeout)       \
 ({                                                                     \
index 84a6440..21f7027 100644 (file)
@@ -65,7 +65,7 @@ extern int                    addrconf_set_dstaddr(struct net *net,
 
 extern int                     ipv6_chk_addr(struct net *net,
                                              const struct in6_addr *addr,
-                                             struct net_device *dev,
+                                             const struct net_device *dev,
                                              int strict);
 
 #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
index 35a57cd..7cb6d36 100644 (file)
@@ -1117,6 +1117,7 @@ void hci_sock_dev_event(struct hci_dev *hdev, int event);
 int mgmt_control(struct sock *sk, struct msghdr *msg, size_t len);
 int mgmt_index_added(struct hci_dev *hdev);
 int mgmt_index_removed(struct hci_dev *hdev);
+int mgmt_set_powered_failed(struct hci_dev *hdev, int err);
 int mgmt_powered(struct hci_dev *hdev, u8 powered);
 int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable);
 int mgmt_connectable(struct hci_dev *hdev, u8 connectable);
index 22980a7..9944c3e 100644 (file)
@@ -42,6 +42,7 @@
 #define MGMT_STATUS_NOT_POWERED                0x0f
 #define MGMT_STATUS_CANCELLED          0x10
 #define MGMT_STATUS_INVALID_INDEX      0x11
+#define MGMT_STATUS_RFKILLED           0x12
 
 struct mgmt_hdr {
        __le16  opcode;
index 04c2d46..885898a 100644 (file)
@@ -3043,7 +3043,8 @@ void ieee80211_napi_complete(struct ieee80211_hw *hw);
  * This function may not be called in IRQ context. Calls to this function
  * for a single hardware must be synchronized against each other. Calls to
  * this function, ieee80211_rx_ni() and ieee80211_rx_irqsafe() may not be
- * mixed for a single hardware.
+ * mixed for a single hardware. Must not run concurrently with
+ * ieee80211_tx_status() or ieee80211_tx_status_ni().
  *
  * In process context use instead ieee80211_rx_ni().
  *
@@ -3059,7 +3060,8 @@ void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb);
  * (internally defers to a tasklet.)
  *
  * Calls to this function, ieee80211_rx() or ieee80211_rx_ni() may not
- * be mixed for a single hardware.
+ * be mixed for a single hardware.Must not run concurrently with
+ * ieee80211_tx_status() or ieee80211_tx_status_ni().
  *
  * @hw: the hardware this frame came in on
  * @skb: the buffer to receive, owned by mac80211 after this call
@@ -3073,7 +3075,8 @@ void ieee80211_rx_irqsafe(struct ieee80211_hw *hw, struct sk_buff *skb);
  * (internally disables bottom halves).
  *
  * Calls to this function, ieee80211_rx() and ieee80211_rx_irqsafe() may
- * not be mixed for a single hardware.
+ * not be mixed for a single hardware. Must not run concurrently with
+ * ieee80211_tx_status() or ieee80211_tx_status_ni().
  *
  * @hw: the hardware this frame came in on
  * @skb: the buffer to receive, owned by mac80211 after this call
@@ -3196,7 +3199,8 @@ void ieee80211_get_tx_rates(struct ieee80211_vif *vif,
  * This function may not be called in IRQ context. Calls to this function
  * for a single hardware must be synchronized against each other. Calls
  * to this function, ieee80211_tx_status_ni() and ieee80211_tx_status_irqsafe()
- * may not be mixed for a single hardware.
+ * may not be mixed for a single hardware. Must not run concurrently with
+ * ieee80211_rx() or ieee80211_rx_ni().
  *
  * @hw: the hardware the frame was transmitted by
  * @skb: the frame that was transmitted, owned by mac80211 after this call
index 31f1fb9..99eac12 100644 (file)
@@ -30,7 +30,8 @@ struct nf_loginfo {
        } u;
 };
 
-typedef void nf_logfn(u_int8_t pf,
+typedef void nf_logfn(struct net *net,
+                     u_int8_t pf,
                      unsigned int hooknum,
                      const struct sk_buff *skb,
                      const struct net_device *in,
index e2dec42..5ca3f14 100644 (file)
@@ -2,7 +2,8 @@
 #define _KER_NFNETLINK_LOG_H
 
 void
-nfulnl_log_packet(u_int8_t pf,
+nfulnl_log_packet(struct net *net,
+                 u_int8_t pf,
                  unsigned int hooknum,
                  const struct sk_buff *skb,
                  const struct net_device *in,
index f10818f..e7f4e21 100644 (file)
@@ -679,22 +679,26 @@ static inline struct sk_buff *skb_act_clone(struct sk_buff *skb, gfp_t gfp_mask,
 #endif
 
 struct psched_ratecfg {
-       u64 rate_bps;
-       u32 mult;
-       u32 shift;
+       u64     rate_bps;
+       u32     mult;
+       u16     overhead;
+       u8      shift;
 };
 
 static inline u64 psched_l2t_ns(const struct psched_ratecfg *r,
                                unsigned int len)
 {
-       return ((u64)len * r->mult) >> r->shift;
+       return ((u64)(len + r->overhead) * r->mult) >> r->shift;
 }
 
-extern void psched_ratecfg_precompute(struct psched_ratecfg *r, u32 rate);
+extern void psched_ratecfg_precompute(struct psched_ratecfg *r, const struct tc_ratespec *conf);
 
-static inline u32 psched_ratecfg_getrate(const struct psched_ratecfg *r)
+static inline void psched_ratecfg_getrate(struct tc_ratespec *res,
+                                         const struct psched_ratecfg *r)
 {
-       return r->rate_bps >> 3;
+       memset(res, 0, sizeof(*res));
+       res->rate = r->rate_bps >> 3;
+       res->overhead = r->overhead;
 }
 
 #endif
index 5c97b0f..66772cf 100644 (file)
@@ -866,6 +866,18 @@ struct inet_hashinfo;
 struct raw_hashinfo;
 struct module;
 
+/*
+ * caches using SLAB_DESTROY_BY_RCU should let .next pointer from nulls nodes
+ * un-modified. Special care is taken when initializing object to zero.
+ */
+static inline void sk_prot_clear_nulls(struct sock *sk, int size)
+{
+       if (offsetof(struct sock, sk_node.next) != 0)
+               memset(sk, 0, offsetof(struct sock, sk_node.next));
+       memset(&sk->sk_node.pprev, 0,
+              size - offsetof(struct sock, sk_node.pprev));
+}
+
 /* Networking protocol blocks we attach to sockets.
  * socket layer -> transport layer interface
  * transport -> network interface is defined by struct inet_proto
index ae16531..94ce082 100644 (file)
@@ -1160,6 +1160,8 @@ static inline void xfrm_sk_free_policy(struct sock *sk)
        }
 }
 
+extern void xfrm_garbage_collect(struct net *net);
+
 #else
 
 static inline void xfrm_sk_free_policy(struct sock *sk) {}
@@ -1194,6 +1196,9 @@ static inline int xfrm6_policy_check_reverse(struct sock *sk, int dir,
 {
        return 1;
 }
+static inline void xfrm_garbage_collect(struct net *net)
+{
+}
 #endif
 
 static __inline__
index ef937b5..e2c1e66 100644 (file)
@@ -118,7 +118,7 @@ struct ex_phy {
 
        enum ex_phy_state phy_state;
 
-       enum sas_dev_type attached_dev_type;
+       enum sas_device_type attached_dev_type;
        enum sas_linkrate linkrate;
 
        u8   attached_sata_host:1;
@@ -195,7 +195,7 @@ enum {
 
 struct domain_device {
        spinlock_t done_lock;
-        enum sas_dev_type dev_type;
+       enum sas_device_type dev_type;
 
         enum sas_linkrate linkrate;
         enum sas_linkrate min_linkrate;
index a6026da..25ac628 100644 (file)
@@ -107,7 +107,7 @@ enum osd_attributes_mode {
  *             int exponent: 04;
  *     }
  */
-typedef __be32 __bitwise osd_cdb_offset;
+typedef __be32 osd_cdb_offset;
 
 enum {
        OSD_OFFSET_UNUSED = 0xFFFFFFFF,
index be3eb0b..0d2607d 100644 (file)
@@ -90,16 +90,18 @@ enum sas_oob_mode {
 };
 
 /* See sas_discover.c if you plan on changing these */
-enum sas_dev_type {
-       NO_DEVICE   = 0,          /* protocol */
-       SAS_END_DEV = 1,          /* protocol */
-       EDGE_DEV    = 2,          /* protocol */
-       FANOUT_DEV  = 3,          /* protocol */
-       SAS_HA      = 4,
-       SATA_DEV    = 5,
-       SATA_PM     = 7,
-       SATA_PM_PORT= 8,
-       SATA_PENDING  = 9,
+enum sas_device_type {
+       /* these are SAS protocol defined (attached device type field) */
+       SAS_PHY_UNUSED = 0,
+       SAS_END_DEVICE = 1,
+       SAS_EDGE_EXPANDER_DEVICE = 2,
+       SAS_FANOUT_EXPANDER_DEVICE = 3,
+       /* these are internal to libsas */
+       SAS_HA = 4,
+       SAS_SATA_DEV = 5,
+       SAS_SATA_PM = 7,
+       SAS_SATA_PM_PORT = 8,
+       SAS_SATA_PENDING = 9,
 };
 
 enum sas_protocol {
index ff71a56..00f41ae 100644 (file)
@@ -32,8 +32,8 @@
 
 static inline int dev_is_sata(struct domain_device *dev)
 {
-       return dev->dev_type == SATA_DEV || dev->dev_type == SATA_PM ||
-              dev->dev_type == SATA_PM_PORT || dev->dev_type == SATA_PENDING;
+       return dev->dev_type == SAS_SATA_DEV || dev->dev_type == SAS_SATA_PM ||
+              dev->dev_type == SAS_SATA_PM_PORT || dev->dev_type == SAS_SATA_PENDING;
 }
 
 int sas_get_ata_info(struct domain_device *dev, struct ex_phy *phy);
index a7f9cba..cc64587 100644 (file)
@@ -394,10 +394,18 @@ extern int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
                        int data_direction, void *buffer, unsigned bufflen,
                        unsigned char *sense, int timeout, int retries,
                        int flag, int *resid);
-extern int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd,
-                           int data_direction, void *buffer, unsigned bufflen,
-                           struct scsi_sense_hdr *, int timeout, int retries,
-                           int *resid);
+extern int scsi_execute_req_flags(struct scsi_device *sdev,
+       const unsigned char *cmd, int data_direction, void *buffer,
+       unsigned bufflen, struct scsi_sense_hdr *sshdr, int timeout,
+       int retries, int *resid, int flags);
+static inline int scsi_execute_req(struct scsi_device *sdev,
+       const unsigned char *cmd, int data_direction, void *buffer,
+       unsigned bufflen, struct scsi_sense_hdr *sshdr, int timeout,
+       int retries, int *resid)
+{
+       return scsi_execute_req_flags(sdev, cmd, data_direction, buffer,
+               bufflen, sshdr, timeout, retries, resid, 0);
+}
 extern void sdev_disable_disk_events(struct scsi_device *sdev);
 extern void sdev_enable_disk_events(struct scsi_device *sdev);
 
index 4a58cca..d0f1602 100644 (file)
@@ -471,14 +471,10 @@ iscsi_destroy_flashnode_sess(struct iscsi_bus_flash_session *fnode_sess);
 extern void iscsi_destroy_all_flashnode(struct Scsi_Host *shost);
 extern int iscsi_flashnode_bus_match(struct device *dev,
                                     struct device_driver *drv);
-extern int iscsi_is_flashnode_conn_dev(struct device *dev, void *data);
-
 extern struct device *
 iscsi_find_flashnode_sess(struct Scsi_Host *shost, void *data,
                          int (*fn)(struct device *dev, void *data));
-
 extern struct device *
-iscsi_find_flashnode_conn(struct iscsi_bus_flash_session *fnode_sess,
-                         void *data,
-                         int (*fn)(struct device *dev, void *data));
+iscsi_find_flashnode_conn(struct iscsi_bus_flash_session *fnode_sess);
+
 #endif
index 9b8e088..0bd71e2 100644 (file)
@@ -10,13 +10,6 @@ struct scsi_transport_template;
 struct sas_rphy;
 struct request;
 
-enum sas_device_type {
-       SAS_PHY_UNUSED = 0,
-       SAS_END_DEVICE = 1,
-       SAS_EDGE_EXPANDER_DEVICE = 2,
-       SAS_FANOUT_EXPANDER_DEVICE = 3,
-};
-
 static inline int sas_protocol_ata(enum sas_protocol proto)
 {
        return ((proto & SAS_PROTOCOL_SATA) ||
index c4af592..4ea4f98 100644 (file)
@@ -463,7 +463,6 @@ struct se_cmd {
 #define CMD_T_ABORTED          (1 << 0)
 #define CMD_T_ACTIVE           (1 << 1)
 #define CMD_T_COMPLETE         (1 << 2)
-#define CMD_T_QUEUED           (1 << 3)
 #define CMD_T_SENT             (1 << 4)
 #define CMD_T_STOP             (1 << 5)
 #define CMD_T_FAILED           (1 << 6)
@@ -544,6 +543,7 @@ struct se_session {
        struct list_head        sess_list;
        struct list_head        sess_acl_list;
        struct list_head        sess_cmd_list;
+       struct list_head        sess_wait_list;
        spinlock_t              sess_cmd_lock;
        struct kref             sess_kref;
 };
@@ -572,12 +572,8 @@ struct se_dev_entry {
        bool                    def_pr_registered;
        /* See transport_lunflags_table */
        u32                     lun_flags;
-       u32                     deve_cmds;
        u32                     mapped_lun;
-       u32                     average_bytes;
-       u32                     last_byte_count;
        u32                     total_cmds;
-       u32                     total_bytes;
        u64                     pr_res_key;
        u64                     creation_time;
        u32                     attach_count;
index ba3471b..1dcce9c 100644 (file)
@@ -114,7 +114,7 @@ sense_reason_t      transport_generic_new_cmd(struct se_cmd *);
 
 void   target_execute_cmd(struct se_cmd *cmd);
 
-void   transport_generic_free_cmd(struct se_cmd *, int);
+int    transport_generic_free_cmd(struct se_cmd *, int);
 
 bool   transport_wait_for_tasks(struct se_cmd *);
 int    transport_check_aborted_status(struct se_cmd *, int);
@@ -123,7 +123,7 @@ int transport_send_check_condition_and_sense(struct se_cmd *,
 int    target_get_sess_cmd(struct se_session *, struct se_cmd *, bool);
 int    target_put_sess_cmd(struct se_session *, struct se_cmd *);
 void   target_sess_cmd_list_set_waiting(struct se_session *);
-void   target_wait_for_sess_cmds(struct se_session *, int);
+void   target_wait_for_sess_cmds(struct se_session *);
 
 int    core_alua_check_nonop_delay(struct se_cmd *);
 
index d0e6864..8ee15b9 100644 (file)
@@ -2139,7 +2139,7 @@ TRACE_EVENT(ext4_es_remove_extent,
                  __entry->lblk, __entry->len)
 );
 
-TRACE_EVENT(ext4_es_find_delayed_extent_enter,
+TRACE_EVENT(ext4_es_find_delayed_extent_range_enter,
        TP_PROTO(struct inode *inode, ext4_lblk_t lblk),
 
        TP_ARGS(inode, lblk),
@@ -2161,7 +2161,7 @@ TRACE_EVENT(ext4_es_find_delayed_extent_enter,
                  (unsigned long) __entry->ino, __entry->lblk)
 );
 
-TRACE_EVENT(ext4_es_find_delayed_extent_exit,
+TRACE_EVENT(ext4_es_find_delayed_extent_range_exit,
        TP_PROTO(struct inode *inode, struct extent_status *es),
 
        TP_ARGS(inode, es),
index 9f096f1..75cef3f 100644 (file)
 #define AUDIT_OBJ_TYPE 21
 #define AUDIT_OBJ_LEV_LOW      22
 #define AUDIT_OBJ_LEV_HIGH     23
+#define AUDIT_LOGINUID_SET     24
 
                                /* These are ONLY useful when checking
                                 * at syscall exit time (AUDIT_AT_EXIT). */
@@ -369,7 +370,8 @@ struct audit_status {
 };
 
 struct audit_tty_status {
-       __u32           enabled; /* 1 = enabled, 0 = disabled */
+       __u32           enabled;        /* 1 = enabled, 0 = disabled */
+       __u32           log_passwd;     /* 1 = enabled, 0 = disabled */
 };
 
 /* audit_rule_data supports filter rules with both integer and string
index a5c86fc..d88c8ee 100644 (file)
@@ -783,6 +783,7 @@ struct kvm_dirty_tlb {
 #define KVM_REG_IA64           0x3000000000000000ULL
 #define KVM_REG_ARM            0x4000000000000000ULL
 #define KVM_REG_S390           0x5000000000000000ULL
+#define KVM_REG_MIPS           0x7000000000000000ULL
 
 #define KVM_REG_SIZE_SHIFT     52
 #define KVM_REG_SIZE_MASK      0x00f0000000000000ULL
index ee13ab6..c312f16 100644 (file)
@@ -39,7 +39,7 @@
 #define VIRTIO_CONSOLE_F_SIZE  0       /* Does host provide console size? */
 #define VIRTIO_CONSOLE_F_MULTIPORT 1   /* Does host provide multiple ports? */
 
-#define VIRTIO_CONSOLE_BAD_ID          (~(u32)0)
+#define VIRTIO_CONSOLE_BAD_ID          (~(__u32)0)
 
 struct virtio_console_config {
        /* colums of the screens */
index 62ca9a7..aeb4e9a 100644 (file)
@@ -748,6 +748,7 @@ struct omap_dss_driver {
 };
 
 enum omapdss_version omapdss_get_version(void);
+bool omapdss_is_initialized(void);
 
 int omap_dss_register_driver(struct omap_dss_driver *);
 void omap_dss_unregister_driver(struct omap_dss_driver *);
index 0a7515c..569c07f 100644 (file)
@@ -70,6 +70,7 @@ struct xenbus_device {
        struct device dev;
        enum xenbus_state state;
        struct completion down;
+       struct work_struct work;
 };
 
 static inline struct xenbus_device *to_xenbus_device(struct device *dev)
index a7e40ed..70480a3 100644 (file)
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -752,19 +752,29 @@ static void do_smart_update(struct sem_array *sma, struct sembuf *sops, int nsop
                        int otime, struct list_head *pt)
 {
        int i;
+       int progress;
 
-       if (sma->complex_count || sops == NULL) {
-               if (update_queue(sma, -1, pt))
+       progress = 1;
+retry_global:
+       if (sma->complex_count) {
+               if (update_queue(sma, -1, pt)) {
+                       progress = 1;
                        otime = 1;
+                       sops = NULL;
+               }
        }
+       if (!progress)
+               goto done;
 
        if (!sops) {
                /* No semops; something special is going on. */
                for (i = 0; i < sma->sem_nsems; i++) {
-                       if (update_queue(sma, i, pt))
+                       if (update_queue(sma, i, pt)) {
                                otime = 1;
+                               progress = 1;
+                       }
                }
-               goto done;
+               goto done_checkretry;
        }
 
        /* Check the semaphores that were modified. */
@@ -772,8 +782,15 @@ static void do_smart_update(struct sem_array *sma, struct sembuf *sops, int nsop
                if (sops[i].sem_op > 0 ||
                        (sops[i].sem_op < 0 &&
                                sma->sem_base[sops[i].sem_num].semval == 0))
-                       if (update_queue(sma, sops[i].sem_num, pt))
+                       if (update_queue(sma, sops[i].sem_num, pt)) {
                                otime = 1;
+                               progress = 1;
+                       }
+       }
+done_checkretry:
+       if (progress) {
+               progress = 0;
+               goto retry_global;
        }
 done:
        if (otime)
index 0b084fa..91e53d0 100644 (file)
@@ -49,6 +49,8 @@
 #include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/kthread.h>
+#include <linux/kernel.h>
+#include <linux/syscalls.h>
 
 #include <linux/audit.h>
 
@@ -265,7 +267,6 @@ void audit_log_lost(const char *message)
 }
 
 static int audit_log_config_change(char *function_name, int new, int old,
-                                  kuid_t loginuid, u32 sessionid, u32 sid,
                                   int allow_changes)
 {
        struct audit_buffer *ab;
@@ -274,29 +275,17 @@ static int audit_log_config_change(char *function_name, int new, int old,
        ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
        if (unlikely(!ab))
                return rc;
-       audit_log_format(ab, "%s=%d old=%d auid=%u ses=%u", function_name, new,
-                        old, from_kuid(&init_user_ns, loginuid), sessionid);
-       if (sid) {
-               char *ctx = NULL;
-               u32 len;
-
-               rc = security_secid_to_secctx(sid, &ctx, &len);
-               if (rc) {
-                       audit_log_format(ab, " sid=%u", sid);
-                       allow_changes = 0; /* Something weird, deny request */
-               } else {
-                       audit_log_format(ab, " subj=%s", ctx);
-                       security_release_secctx(ctx, len);
-               }
-       }
+       audit_log_format(ab, "%s=%d old=%d", function_name, new, old);
+       audit_log_session_info(ab);
+       rc = audit_log_task_context(ab);
+       if (rc)
+               allow_changes = 0; /* Something weird, deny request */
        audit_log_format(ab, " res=%d", allow_changes);
        audit_log_end(ab);
        return rc;
 }
 
-static int audit_do_config_change(char *function_name, int *to_change,
-                                 int new, kuid_t loginuid, u32 sessionid,
-                                 u32 sid)
+static int audit_do_config_change(char *function_name, int *to_change, int new)
 {
        int allow_changes, rc = 0, old = *to_change;
 
@@ -307,8 +296,7 @@ static int audit_do_config_change(char *function_name, int *to_change,
                allow_changes = 1;
 
        if (audit_enabled != AUDIT_OFF) {
-               rc = audit_log_config_change(function_name, new, old, loginuid,
-                                            sessionid, sid, allow_changes);
+               rc = audit_log_config_change(function_name, new, old, allow_changes);
                if (rc)
                        allow_changes = 0;
        }
@@ -322,44 +310,37 @@ static int audit_do_config_change(char *function_name, int *to_change,
        return rc;
 }
 
-static int audit_set_rate_limit(int limit, kuid_t loginuid, u32 sessionid,
-                               u32 sid)
+static int audit_set_rate_limit(int limit)
 {
-       return audit_do_config_change("audit_rate_limit", &audit_rate_limit,
-                                     limit, loginuid, sessionid, sid);
+       return audit_do_config_change("audit_rate_limit", &audit_rate_limit, limit);
 }
 
-static int audit_set_backlog_limit(int limit, kuid_t loginuid, u32 sessionid,
-                                  u32 sid)
+static int audit_set_backlog_limit(int limit)
 {
-       return audit_do_config_change("audit_backlog_limit", &audit_backlog_limit,
-                                     limit, loginuid, sessionid, sid);
+       return audit_do_config_change("audit_backlog_limit", &audit_backlog_limit, limit);
 }
 
-static int audit_set_enabled(int state, kuid_t loginuid, u32 sessionid, u32 sid)
+static int audit_set_enabled(int state)
 {
        int rc;
        if (state < AUDIT_OFF || state > AUDIT_LOCKED)
                return -EINVAL;
 
-       rc =  audit_do_config_change("audit_enabled", &audit_enabled, state,
-                                    loginuid, sessionid, sid);
-
+       rc =  audit_do_config_change("audit_enabled", &audit_enabled, state);
        if (!rc)
                audit_ever_enabled |= !!state;
 
        return rc;
 }
 
-static int audit_set_failure(int state, kuid_t loginuid, u32 sessionid, u32 sid)
+static int audit_set_failure(int state)
 {
        if (state != AUDIT_FAIL_SILENT
            && state != AUDIT_FAIL_PRINTK
            && state != AUDIT_FAIL_PANIC)
                return -EINVAL;
 
-       return audit_do_config_change("audit_failure", &audit_failure, state,
-                                     loginuid, sessionid, sid);
+       return audit_do_config_change("audit_failure", &audit_failure, state);
 }
 
 /*
@@ -417,34 +398,53 @@ static void kauditd_send_skb(struct sk_buff *skb)
                consume_skb(skb);
 }
 
-static int kauditd_thread(void *dummy)
+/*
+ * flush_hold_queue - empty the hold queue if auditd appears
+ *
+ * If auditd just started, drain the queue of messages already
+ * sent to syslog/printk.  Remember loss here is ok.  We already
+ * called audit_log_lost() if it didn't go out normally.  so the
+ * race between the skb_dequeue and the next check for audit_pid
+ * doesn't matter.
+ *
+ * If you ever find kauditd to be too slow we can get a perf win
+ * by doing our own locking and keeping better track if there
+ * are messages in this queue.  I don't see the need now, but
+ * in 5 years when I want to play with this again I'll see this
+ * note and still have no friggin idea what i'm thinking today.
+ */
+static void flush_hold_queue(void)
 {
        struct sk_buff *skb;
 
+       if (!audit_default || !audit_pid)
+               return;
+
+       skb = skb_dequeue(&audit_skb_hold_queue);
+       if (likely(!skb))
+               return;
+
+       while (skb && audit_pid) {
+               kauditd_send_skb(skb);
+               skb = skb_dequeue(&audit_skb_hold_queue);
+       }
+
+       /*
+        * if auditd just disappeared but we
+        * dequeued an skb we need to drop ref
+        */
+       if (skb)
+               consume_skb(skb);
+}
+
+static int kauditd_thread(void *dummy)
+{
        set_freezable();
        while (!kthread_should_stop()) {
-               /*
-                * if auditd just started drain the queue of messages already
-                * sent to syslog/printk.  remember loss here is ok.  we already
-                * called audit_log_lost() if it didn't go out normally.  so the
-                * race between the skb_dequeue and the next check for audit_pid
-                * doesn't matter.
-                *
-                * if you ever find kauditd to be too slow we can get a perf win
-                * by doing our own locking and keeping better track if there
-                * are messages in this queue.  I don't see the need now, but
-                * in 5 years when I want to play with this again I'll see this
-                * note and still have no friggin idea what i'm thinking today.
-                */
-               if (audit_default && audit_pid) {
-                       skb = skb_dequeue(&audit_skb_hold_queue);
-                       if (unlikely(skb)) {
-                               while (skb && audit_pid) {
-                                       kauditd_send_skb(skb);
-                                       skb = skb_dequeue(&audit_skb_hold_queue);
-                               }
-                       }
-               }
+               struct sk_buff *skb;
+               DECLARE_WAITQUEUE(wait, current);
+
+               flush_hold_queue();
 
                skb = skb_dequeue(&audit_skb_queue);
                wake_up(&audit_backlog_wait);
@@ -453,19 +453,18 @@ static int kauditd_thread(void *dummy)
                                kauditd_send_skb(skb);
                        else
                                audit_printk_skb(skb);
-               } else {
-                       DECLARE_WAITQUEUE(wait, current);
-                       set_current_state(TASK_INTERRUPTIBLE);
-                       add_wait_queue(&kauditd_wait, &wait);
-
-                       if (!skb_queue_len(&audit_skb_queue)) {
-                               try_to_freeze();
-                               schedule();
-                       }
+                       continue;
+               }
+               set_current_state(TASK_INTERRUPTIBLE);
+               add_wait_queue(&kauditd_wait, &wait);
 
-                       __set_current_state(TASK_RUNNING);
-                       remove_wait_queue(&kauditd_wait, &wait);
+               if (!skb_queue_len(&audit_skb_queue)) {
+                       try_to_freeze();
+                       schedule();
                }
+
+               __set_current_state(TASK_RUNNING);
+               remove_wait_queue(&kauditd_wait, &wait);
        }
        return 0;
 }
@@ -579,13 +578,14 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type)
                return -EPERM;
 
        switch (msg_type) {
-       case AUDIT_GET:
        case AUDIT_LIST:
-       case AUDIT_LIST_RULES:
-       case AUDIT_SET:
        case AUDIT_ADD:
-       case AUDIT_ADD_RULE:
        case AUDIT_DEL:
+               return -EOPNOTSUPP;
+       case AUDIT_GET:
+       case AUDIT_SET:
+       case AUDIT_LIST_RULES:
+       case AUDIT_ADD_RULE:
        case AUDIT_DEL_RULE:
        case AUDIT_SIGNAL_INFO:
        case AUDIT_TTY_GET:
@@ -608,12 +608,10 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type)
        return err;
 }
 
-static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type,
-                                    kuid_t auid, u32 ses, u32 sid)
+static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type)
 {
        int rc = 0;
-       char *ctx = NULL;
-       u32 len;
+       uid_t uid = from_kuid(&init_user_ns, current_uid());
 
        if (!audit_enabled) {
                *ab = NULL;
@@ -623,33 +621,21 @@ static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type,
        *ab = audit_log_start(NULL, GFP_KERNEL, msg_type);
        if (unlikely(!*ab))
                return rc;
-       audit_log_format(*ab, "pid=%d uid=%u auid=%u ses=%u",
-                        task_tgid_vnr(current),
-                        from_kuid(&init_user_ns, current_uid()),
-                        from_kuid(&init_user_ns, auid), ses);
-       if (sid) {
-               rc = security_secid_to_secctx(sid, &ctx, &len);
-               if (rc)
-                       audit_log_format(*ab, " ssid=%u", sid);
-               else {
-                       audit_log_format(*ab, " subj=%s", ctx);
-                       security_release_secctx(ctx, len);
-               }
-       }
+       audit_log_format(*ab, "pid=%d uid=%u", task_tgid_vnr(current), uid);
+       audit_log_session_info(*ab);
+       audit_log_task_context(*ab);
 
        return rc;
 }
 
 static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 {
-       u32                     seq, sid;
+       u32                     seq;
        void                    *data;
        struct audit_status     *status_get, status_set;
        int                     err;
        struct audit_buffer     *ab;
        u16                     msg_type = nlh->nlmsg_type;
-       kuid_t                  loginuid; /* loginuid of sender */
-       u32                     sessionid;
        struct audit_sig_info   *sig_data;
        char                    *ctx = NULL;
        u32                     len;
@@ -668,9 +654,6 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                        return err;
                }
        }
-       loginuid = audit_get_loginuid(current);
-       sessionid = audit_get_sessionid(current);
-       security_task_getsecid(current, &sid);
        seq  = nlh->nlmsg_seq;
        data = nlmsg_data(nlh);
 
@@ -691,14 +674,12 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                        return -EINVAL;
                status_get   = (struct audit_status *)data;
                if (status_get->mask & AUDIT_STATUS_ENABLED) {
-                       err = audit_set_enabled(status_get->enabled,
-                                               loginuid, sessionid, sid);
+                       err = audit_set_enabled(status_get->enabled);
                        if (err < 0)
                                return err;
                }
                if (status_get->mask & AUDIT_STATUS_FAILURE) {
-                       err = audit_set_failure(status_get->failure,
-                                               loginuid, sessionid, sid);
+                       err = audit_set_failure(status_get->failure);
                        if (err < 0)
                                return err;
                }
@@ -706,22 +687,17 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                        int new_pid = status_get->pid;
 
                        if (audit_enabled != AUDIT_OFF)
-                               audit_log_config_change("audit_pid", new_pid,
-                                                       audit_pid, loginuid,
-                                                       sessionid, sid, 1);
-
+                               audit_log_config_change("audit_pid", new_pid, audit_pid, 1);
                        audit_pid = new_pid;
                        audit_nlk_portid = NETLINK_CB(skb).portid;
                }
                if (status_get->mask & AUDIT_STATUS_RATE_LIMIT) {
-                       err = audit_set_rate_limit(status_get->rate_limit,
-                                                  loginuid, sessionid, sid);
+                       err = audit_set_rate_limit(status_get->rate_limit);
                        if (err < 0)
                                return err;
                }
                if (status_get->mask & AUDIT_STATUS_BACKLOG_LIMIT)
-                       err = audit_set_backlog_limit(status_get->backlog_limit,
-                                                     loginuid, sessionid, sid);
+                       err = audit_set_backlog_limit(status_get->backlog_limit);
                break;
        case AUDIT_USER:
        case AUDIT_FIRST_USER_MSG ... AUDIT_LAST_USER_MSG:
@@ -729,25 +705,22 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                if (!audit_enabled && msg_type != AUDIT_USER_AVC)
                        return 0;
 
-               err = audit_filter_user();
+               err = audit_filter_user(msg_type);
                if (err == 1) {
                        err = 0;
                        if (msg_type == AUDIT_USER_TTY) {
-                               err = tty_audit_push_task(current, loginuid,
-                                                            sessionid);
+                               err = tty_audit_push_current();
                                if (err)
                                        break;
                        }
-                       audit_log_common_recv_msg(&ab, msg_type,
-                                                 loginuid, sessionid, sid);
-
+                       audit_log_common_recv_msg(&ab, msg_type);
                        if (msg_type != AUDIT_USER_TTY)
                                audit_log_format(ab, " msg='%.1024s'",
                                                 (char *)data);
                        else {
                                int size;
 
-                               audit_log_format(ab, " msg=");
+                               audit_log_format(ab, " data=");
                                size = nlmsg_len(nlh);
                                if (size > 0 &&
                                    ((unsigned char *)data)[size - 1] == '\0')
@@ -758,50 +731,24 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                        audit_log_end(ab);
                }
                break;
-       case AUDIT_ADD:
-       case AUDIT_DEL:
-               if (nlmsg_len(nlh) < sizeof(struct audit_rule))
-                       return -EINVAL;
-               if (audit_enabled == AUDIT_LOCKED) {
-                       audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE,
-                                                 loginuid, sessionid, sid);
-
-                       audit_log_format(ab, " audit_enabled=%d res=0",
-                                        audit_enabled);
-                       audit_log_end(ab);
-                       return -EPERM;
-               }
-               /* fallthrough */
-       case AUDIT_LIST:
-               err = audit_receive_filter(msg_type, NETLINK_CB(skb).portid,
-                                          seq, data, nlmsg_len(nlh),
-                                          loginuid, sessionid, sid);
-               break;
        case AUDIT_ADD_RULE:
        case AUDIT_DEL_RULE:
                if (nlmsg_len(nlh) < sizeof(struct audit_rule_data))
                        return -EINVAL;
                if (audit_enabled == AUDIT_LOCKED) {
-                       audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE,
-                                                 loginuid, sessionid, sid);
-
-                       audit_log_format(ab, " audit_enabled=%d res=0",
-                                        audit_enabled);
+                       audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE);
+                       audit_log_format(ab, " audit_enabled=%d res=0", audit_enabled);
                        audit_log_end(ab);
                        return -EPERM;
                }
                /* fallthrough */
        case AUDIT_LIST_RULES:
                err = audit_receive_filter(msg_type, NETLINK_CB(skb).portid,
-                                          seq, data, nlmsg_len(nlh),
-                                          loginuid, sessionid, sid);
+                                          seq, data, nlmsg_len(nlh));
                break;
        case AUDIT_TRIM:
                audit_trim_trees();
-
-               audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE,
-                                         loginuid, sessionid, sid);
-
+               audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE);
                audit_log_format(ab, " op=trim res=1");
                audit_log_end(ab);
                break;
@@ -831,8 +778,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                /* OK, here comes... */
                err = audit_tag_tree(old, new);
 
-               audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE,
-                                         loginuid, sessionid, sid);
+               audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE);
 
                audit_log_format(ab, " op=make_equiv old=");
                audit_log_untrustedstring(ab, old);
@@ -871,27 +817,30 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                struct audit_tty_status s;
                struct task_struct *tsk = current;
 
-               spin_lock_irq(&tsk->sighand->siglock);
+               spin_lock(&tsk->sighand->siglock);
                s.enabled = tsk->signal->audit_tty != 0;
-               spin_unlock_irq(&tsk->sighand->siglock);
+               s.log_passwd = tsk->signal->audit_tty_log_passwd;
+               spin_unlock(&tsk->sighand->siglock);
 
                audit_send_reply(NETLINK_CB(skb).portid, seq,
                                 AUDIT_TTY_GET, 0, 0, &s, sizeof(s));
                break;
        }
        case AUDIT_TTY_SET: {
-               struct audit_tty_status *s;
+               struct audit_tty_status s;
                struct task_struct *tsk = current;
 
-               if (nlh->nlmsg_len < sizeof(struct audit_tty_status))
-                       return -EINVAL;
-               s = data;
-               if (s->enabled != 0 && s->enabled != 1)
+               memset(&s, 0, sizeof(s));
+               /* guard against past and future API changes */
+               memcpy(&s, data, min(sizeof(s), (size_t)nlh->nlmsg_len));
+               if ((s.enabled != 0 && s.enabled != 1) ||
+                   (s.log_passwd != 0 && s.log_passwd != 1))
                        return -EINVAL;
 
-               spin_lock_irq(&tsk->sighand->siglock);
-               tsk->signal->audit_tty = s->enabled != 0;
-               spin_unlock_irq(&tsk->sighand->siglock);
+               spin_lock(&tsk->sighand->siglock);
+               tsk->signal->audit_tty = s.enabled;
+               tsk->signal->audit_tty_log_passwd = s.log_passwd;
+               spin_unlock(&tsk->sighand->siglock);
                break;
        }
        default:
@@ -1107,7 +1056,7 @@ static inline void audit_get_stamp(struct audit_context *ctx,
 static void wait_for_auditd(unsigned long sleep_time)
 {
        DECLARE_WAITQUEUE(wait, current);
-       set_current_state(TASK_INTERRUPTIBLE);
+       set_current_state(TASK_UNINTERRUPTIBLE);
        add_wait_queue(&audit_backlog_wait, &wait);
 
        if (audit_backlog_limit &&
@@ -1434,6 +1383,14 @@ void audit_log_d_path(struct audit_buffer *ab, const char *prefix,
        kfree(pathname);
 }
 
+void audit_log_session_info(struct audit_buffer *ab)
+{
+       u32 sessionid = audit_get_sessionid(current);
+       uid_t auid = from_kuid(&init_user_ns, audit_get_loginuid(current));
+
+       audit_log_format(ab, " auid=%u ses=%u\n", auid, sessionid);
+}
+
 void audit_log_key(struct audit_buffer *ab, char *key)
 {
        audit_log_format(ab, " key=");
@@ -1443,6 +1400,224 @@ void audit_log_key(struct audit_buffer *ab, char *key)
                audit_log_format(ab, "(null)");
 }
 
+void audit_log_cap(struct audit_buffer *ab, char *prefix, kernel_cap_t *cap)
+{
+       int i;
+
+       audit_log_format(ab, " %s=", prefix);
+       CAP_FOR_EACH_U32(i) {
+               audit_log_format(ab, "%08x",
+                                cap->cap[(_KERNEL_CAPABILITY_U32S-1) - i]);
+       }
+}
+
+void audit_log_fcaps(struct audit_buffer *ab, struct audit_names *name)
+{
+       kernel_cap_t *perm = &name->fcap.permitted;
+       kernel_cap_t *inh = &name->fcap.inheritable;
+       int log = 0;
+
+       if (!cap_isclear(*perm)) {
+               audit_log_cap(ab, "cap_fp", perm);
+               log = 1;
+       }
+       if (!cap_isclear(*inh)) {
+               audit_log_cap(ab, "cap_fi", inh);
+               log = 1;
+       }
+
+       if (log)
+               audit_log_format(ab, " cap_fe=%d cap_fver=%x",
+                                name->fcap.fE, name->fcap_ver);
+}
+
+static inline int audit_copy_fcaps(struct audit_names *name,
+                                  const struct dentry *dentry)
+{
+       struct cpu_vfs_cap_data caps;
+       int rc;
+
+       if (!dentry)
+               return 0;
+
+       rc = get_vfs_caps_from_disk(dentry, &caps);
+       if (rc)
+               return rc;
+
+       name->fcap.permitted = caps.permitted;
+       name->fcap.inheritable = caps.inheritable;
+       name->fcap.fE = !!(caps.magic_etc & VFS_CAP_FLAGS_EFFECTIVE);
+       name->fcap_ver = (caps.magic_etc & VFS_CAP_REVISION_MASK) >>
+                               VFS_CAP_REVISION_SHIFT;
+
+       return 0;
+}
+
+/* Copy inode data into an audit_names. */
+void audit_copy_inode(struct audit_names *name, const struct dentry *dentry,
+                     const struct inode *inode)
+{
+       name->ino   = inode->i_ino;
+       name->dev   = inode->i_sb->s_dev;
+       name->mode  = inode->i_mode;
+       name->uid   = inode->i_uid;
+       name->gid   = inode->i_gid;
+       name->rdev  = inode->i_rdev;
+       security_inode_getsecid(inode, &name->osid);
+       audit_copy_fcaps(name, dentry);
+}
+
+/**
+ * audit_log_name - produce AUDIT_PATH record from struct audit_names
+ * @context: audit_context for the task
+ * @n: audit_names structure with reportable details
+ * @path: optional path to report instead of audit_names->name
+ * @record_num: record number to report when handling a list of names
+ * @call_panic: optional pointer to int that will be updated if secid fails
+ */
+void audit_log_name(struct audit_context *context, struct audit_names *n,
+                   struct path *path, int record_num, int *call_panic)
+{
+       struct audit_buffer *ab;
+       ab = audit_log_start(context, GFP_KERNEL, AUDIT_PATH);
+       if (!ab)
+               return;
+
+       audit_log_format(ab, "item=%d", record_num);
+
+       if (path)
+               audit_log_d_path(ab, " name=", path);
+       else if (n->name) {
+               switch (n->name_len) {
+               case AUDIT_NAME_FULL:
+                       /* log the full path */
+                       audit_log_format(ab, " name=");
+                       audit_log_untrustedstring(ab, n->name->name);
+                       break;
+               case 0:
+                       /* name was specified as a relative path and the
+                        * directory component is the cwd */
+                       audit_log_d_path(ab, " name=", &context->pwd);
+                       break;
+               default:
+                       /* log the name's directory component */
+                       audit_log_format(ab, " name=");
+                       audit_log_n_untrustedstring(ab, n->name->name,
+                                                   n->name_len);
+               }
+       } else
+               audit_log_format(ab, " name=(null)");
+
+       if (n->ino != (unsigned long)-1) {
+               audit_log_format(ab, " inode=%lu"
+                                " dev=%02x:%02x mode=%#ho"
+                                " ouid=%u ogid=%u rdev=%02x:%02x",
+                                n->ino,
+                                MAJOR(n->dev),
+                                MINOR(n->dev),
+                                n->mode,
+                                from_kuid(&init_user_ns, n->uid),
+                                from_kgid(&init_user_ns, n->gid),
+                                MAJOR(n->rdev),
+                                MINOR(n->rdev));
+       }
+       if (n->osid != 0) {
+               char *ctx = NULL;
+               u32 len;
+               if (security_secid_to_secctx(
+                       n->osid, &ctx, &len)) {
+                       audit_log_format(ab, " osid=%u", n->osid);
+                       if (call_panic)
+                               *call_panic = 2;
+               } else {
+                       audit_log_format(ab, " obj=%s", ctx);
+                       security_release_secctx(ctx, len);
+               }
+       }
+
+       audit_log_fcaps(ab, n);
+       audit_log_end(ab);
+}
+
+int audit_log_task_context(struct audit_buffer *ab)
+{
+       char *ctx = NULL;
+       unsigned len;
+       int error;
+       u32 sid;
+
+       security_task_getsecid(current, &sid);
+       if (!sid)
+               return 0;
+
+       error = security_secid_to_secctx(sid, &ctx, &len);
+       if (error) {
+               if (error != -EINVAL)
+                       goto error_path;
+               return 0;
+       }
+
+       audit_log_format(ab, " subj=%s", ctx);
+       security_release_secctx(ctx, len);
+       return 0;
+
+error_path:
+       audit_panic("error in audit_log_task_context");
+       return error;
+}
+EXPORT_SYMBOL(audit_log_task_context);
+
+void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk)
+{
+       const struct cred *cred;
+       char name[sizeof(tsk->comm)];
+       struct mm_struct *mm = tsk->mm;
+       char *tty;
+
+       if (!ab)
+               return;
+
+       /* tsk == current */
+       cred = current_cred();
+
+       spin_lock_irq(&tsk->sighand->siglock);
+       if (tsk->signal && tsk->signal->tty && tsk->signal->tty->name)
+               tty = tsk->signal->tty->name;
+       else
+               tty = "(none)";
+       spin_unlock_irq(&tsk->sighand->siglock);
+
+       audit_log_format(ab,
+                        " ppid=%ld pid=%d auid=%u uid=%u gid=%u"
+                        " euid=%u suid=%u fsuid=%u"
+                        " egid=%u sgid=%u fsgid=%u ses=%u tty=%s",
+                        sys_getppid(),
+                        tsk->pid,
+                        from_kuid(&init_user_ns, audit_get_loginuid(tsk)),
+                        from_kuid(&init_user_ns, cred->uid),
+                        from_kgid(&init_user_ns, cred->gid),
+                        from_kuid(&init_user_ns, cred->euid),
+                        from_kuid(&init_user_ns, cred->suid),
+                        from_kuid(&init_user_ns, cred->fsuid),
+                        from_kgid(&init_user_ns, cred->egid),
+                        from_kgid(&init_user_ns, cred->sgid),
+                        from_kgid(&init_user_ns, cred->fsgid),
+                        audit_get_sessionid(tsk), tty);
+
+       get_task_comm(name, tsk);
+       audit_log_format(ab, " comm=");
+       audit_log_untrustedstring(ab, name);
+
+       if (mm) {
+               down_read(&mm->mmap_sem);
+               if (mm->exe_file)
+                       audit_log_d_path(ab, " exe=", &mm->exe_file->f_path);
+               up_read(&mm->mmap_sem);
+       }
+       audit_log_task_context(ab);
+}
+EXPORT_SYMBOL(audit_log_task_info);
+
 /**
  * audit_log_link_denied - report a link restriction denial
  * @operation: specific link opreation
@@ -1451,19 +1626,28 @@ void audit_log_key(struct audit_buffer *ab, char *key)
 void audit_log_link_denied(const char *operation, struct path *link)
 {
        struct audit_buffer *ab;
+       struct audit_names *name;
+
+       name = kzalloc(sizeof(*name), GFP_NOFS);
+       if (!name)
+               return;
 
+       /* Generate AUDIT_ANOM_LINK with subject, operation, outcome. */
        ab = audit_log_start(current->audit_context, GFP_KERNEL,
                             AUDIT_ANOM_LINK);
        if (!ab)
-               return;
-       audit_log_format(ab, "op=%s action=denied", operation);
-       audit_log_format(ab, " pid=%d comm=", current->pid);
-       audit_log_untrustedstring(ab, current->comm);
-       audit_log_d_path(ab, " path=", link);
-       audit_log_format(ab, " dev=");
-       audit_log_untrustedstring(ab, link->dentry->d_inode->i_sb->s_id);
-       audit_log_format(ab, " ino=%lu", link->dentry->d_inode->i_ino);
+               goto out;
+       audit_log_format(ab, "op=%s", operation);
+       audit_log_task_info(ab, current);
+       audit_log_format(ab, " res=0");
        audit_log_end(ab);
+
+       /* Generate AUDIT_PATH record with object. */
+       name->type = AUDIT_TYPE_NORMAL;
+       audit_copy_inode(name, link->dentry, link->dentry->d_inode);
+       audit_log_name(current->audit_context, name, link, 0, NULL);
+out:
+       kfree(name);
 }
 
 /**
index 11468d9..1c95131 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/fs.h>
 #include <linux/audit.h>
 #include <linux/skbuff.h>
+#include <uapi/linux/mqueue.h>
 
 /* 0 = no checking
    1 = put_count checking
 */
 #define AUDIT_DEBUG 0
 
+/* AUDIT_NAMES is the number of slots we reserve in the audit_context
+ * for saving names from getname().  If we get more names we will allocate
+ * a name dynamically and also add those to the list anchored by names_list. */
+#define AUDIT_NAMES    5
+
 /* At task start time, the audit_state is set in the audit_context using
    a per-task filter.  At syscall entry, the audit_state is augmented by
    the syscall filter. */
@@ -59,8 +65,158 @@ struct audit_entry {
        struct audit_krule      rule;
 };
 
+struct audit_cap_data {
+       kernel_cap_t            permitted;
+       kernel_cap_t            inheritable;
+       union {
+               unsigned int    fE;             /* effective bit of file cap */
+               kernel_cap_t    effective;      /* effective set of process */
+       };
+};
+
+/* When fs/namei.c:getname() is called, we store the pointer in name and
+ * we don't let putname() free it (instead we free all of the saved
+ * pointers at syscall exit time).
+ *
+ * Further, in fs/namei.c:path_lookup() we store the inode and device.
+ */
+struct audit_names {
+       struct list_head        list;           /* audit_context->names_list */
+
+       struct filename         *name;
+       int                     name_len;       /* number of chars to log */
+       bool                    name_put;       /* call __putname()? */
+
+       unsigned long           ino;
+       dev_t                   dev;
+       umode_t                 mode;
+       kuid_t                  uid;
+       kgid_t                  gid;
+       dev_t                   rdev;
+       u32                     osid;
+       struct audit_cap_data   fcap;
+       unsigned int            fcap_ver;
+       unsigned char           type;           /* record type */
+       /*
+        * This was an allocated audit_names and not from the array of
+        * names allocated in the task audit context.  Thus this name
+        * should be freed on syscall exit.
+        */
+       bool                    should_free;
+};
+
+/* The per-task audit context. */
+struct audit_context {
+       int                 dummy;      /* must be the first element */
+       int                 in_syscall; /* 1 if task is in a syscall */
+       enum audit_state    state, current_state;
+       unsigned int        serial;     /* serial number for record */
+       int                 major;      /* syscall number */
+       struct timespec     ctime;      /* time of syscall entry */
+       unsigned long       argv[4];    /* syscall arguments */
+       long                return_code;/* syscall return code */
+       u64                 prio;
+       int                 return_valid; /* return code is valid */
+       /*
+        * The names_list is the list of all audit_names collected during this
+        * syscall.  The first AUDIT_NAMES entries in the names_list will
+        * actually be from the preallocated_names array for performance
+        * reasons.  Except during allocation they should never be referenced
+        * through the preallocated_names array and should only be found/used
+        * by running the names_list.
+        */
+       struct audit_names  preallocated_names[AUDIT_NAMES];
+       int                 name_count; /* total records in names_list */
+       struct list_head    names_list; /* struct audit_names->list anchor */
+       char                *filterkey; /* key for rule that triggered record */
+       struct path         pwd;
+       struct audit_aux_data *aux;
+       struct audit_aux_data *aux_pids;
+       struct sockaddr_storage *sockaddr;
+       size_t sockaddr_len;
+                               /* Save things to print about task_struct */
+       pid_t               pid, ppid;
+       kuid_t              uid, euid, suid, fsuid;
+       kgid_t              gid, egid, sgid, fsgid;
+       unsigned long       personality;
+       int                 arch;
+
+       pid_t               target_pid;
+       kuid_t              target_auid;
+       kuid_t              target_uid;
+       unsigned int        target_sessionid;
+       u32                 target_sid;
+       char                target_comm[TASK_COMM_LEN];
+
+       struct audit_tree_refs *trees, *first_trees;
+       struct list_head killed_trees;
+       int tree_count;
+
+       int type;
+       union {
+               struct {
+                       int nargs;
+                       long args[6];
+               } socketcall;
+               struct {
+                       kuid_t                  uid;
+                       kgid_t                  gid;
+                       umode_t                 mode;
+                       u32                     osid;
+                       int                     has_perm;
+                       uid_t                   perm_uid;
+                       gid_t                   perm_gid;
+                       umode_t                 perm_mode;
+                       unsigned long           qbytes;
+               } ipc;
+               struct {
+                       mqd_t                   mqdes;
+                       struct mq_attr          mqstat;
+               } mq_getsetattr;
+               struct {
+                       mqd_t                   mqdes;
+                       int                     sigev_signo;
+               } mq_notify;
+               struct {
+                       mqd_t                   mqdes;
+                       size_t                  msg_len;
+                       unsigned int            msg_prio;
+                       struct timespec         abs_timeout;
+               } mq_sendrecv;
+               struct {
+                       int                     oflag;
+                       umode_t                 mode;
+                       struct mq_attr          attr;
+               } mq_open;
+               struct {
+                       pid_t                   pid;
+                       struct audit_cap_data   cap;
+               } capset;
+               struct {
+                       int                     fd;
+                       int                     flags;
+               } mmap;
+       };
+       int fds[2];
+
+#if AUDIT_DEBUG
+       int                 put_count;
+       int                 ino_count;
+#endif
+};
+
 extern int audit_ever_enabled;
 
+extern void audit_copy_inode(struct audit_names *name,
+                            const struct dentry *dentry,
+                            const struct inode *inode);
+extern void audit_log_cap(struct audit_buffer *ab, char *prefix,
+                         kernel_cap_t *cap);
+extern void audit_log_fcaps(struct audit_buffer *ab, struct audit_names *name);
+extern void audit_log_name(struct audit_context *context,
+                          struct audit_names *n, struct path *path,
+                          int record_num, int *call_panic);
+
 extern int audit_pid;
 
 #define AUDIT_INODE_BUCKETS    32
index a291aa2..43c307d 100644 (file)
@@ -658,6 +658,7 @@ int audit_add_tree_rule(struct audit_krule *rule)
        struct vfsmount *mnt;
        int err;
 
+       rule->tree = NULL;
        list_for_each_entry(tree, &tree_list, list) {
                if (!strcmp(seed->pathname, tree->pathname)) {
                        put_tree(seed);
index 2674368..6bd4a90 100644 (file)
@@ -310,121 +310,83 @@ static u32 audit_to_op(u32 op)
        return n;
 }
 
-
-/* Translate struct audit_rule to kernel's rule respresentation.
- * Exists for backward compatibility with userspace. */
-static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule)
+/* check if an audit field is valid */
+static int audit_field_valid(struct audit_entry *entry, struct audit_field *f)
 {
-       struct audit_entry *entry;
-       int err = 0;
-       int i;
-
-       entry = audit_to_entry_common(rule);
-       if (IS_ERR(entry))
-               goto exit_nofree;
-
-       for (i = 0; i < rule->field_count; i++) {
-               struct audit_field *f = &entry->rule.fields[i];
-               u32 n;
-
-               n = rule->fields[i] & (AUDIT_NEGATE|AUDIT_OPERATORS);
-
-               /* Support for legacy operators where
-                * AUDIT_NEGATE bit signifies != and otherwise assumes == */
-               if (n & AUDIT_NEGATE)
-                       f->op = Audit_not_equal;
-               else if (!n)
-                       f->op = Audit_equal;
-               else
-                       f->op = audit_to_op(n);
-
-               entry->rule.vers_ops = (n & AUDIT_OPERATORS) ? 2 : 1;
-
-               f->type = rule->fields[i] & ~(AUDIT_NEGATE|AUDIT_OPERATORS);
-               f->val = rule->values[i];
-               f->uid = INVALID_UID;
-               f->gid = INVALID_GID;
-
-               err = -EINVAL;
-               if (f->op == Audit_bad)
-                       goto exit_free;
-
-               switch(f->type) {
-               default:
-                       goto exit_free;
-               case AUDIT_UID:
-               case AUDIT_EUID:
-               case AUDIT_SUID:
-               case AUDIT_FSUID:
-               case AUDIT_LOGINUID:
-                       /* bit ops not implemented for uid comparisons */
-                       if (f->op == Audit_bitmask || f->op == Audit_bittest)
-                               goto exit_free;
-
-                       f->uid = make_kuid(current_user_ns(), f->val);
-                       if (!uid_valid(f->uid))
-                               goto exit_free;
-                       break;
-               case AUDIT_GID:
-               case AUDIT_EGID:
-               case AUDIT_SGID:
-               case AUDIT_FSGID:
-                       /* bit ops not implemented for gid comparisons */
-                       if (f->op == Audit_bitmask || f->op == Audit_bittest)
-                               goto exit_free;
-
-                       f->gid = make_kgid(current_user_ns(), f->val);
-                       if (!gid_valid(f->gid))
-                               goto exit_free;
-                       break;
-               case AUDIT_PID:
-               case AUDIT_PERS:
-               case AUDIT_MSGTYPE:
-               case AUDIT_PPID:
-               case AUDIT_DEVMAJOR:
-               case AUDIT_DEVMINOR:
-               case AUDIT_EXIT:
-               case AUDIT_SUCCESS:
-                       /* bit ops are only useful on syscall args */
-                       if (f->op == Audit_bitmask || f->op == Audit_bittest)
-                               goto exit_free;
-                       break;
-               case AUDIT_ARG0:
-               case AUDIT_ARG1:
-               case AUDIT_ARG2:
-               case AUDIT_ARG3:
-                       break;
-               /* arch is only allowed to be = or != */
-               case AUDIT_ARCH:
-                       if (f->op != Audit_not_equal && f->op != Audit_equal)
-                               goto exit_free;
-                       entry->rule.arch_f = f;
-                       break;
-               case AUDIT_PERM:
-                       if (f->val & ~15)
-                               goto exit_free;
-                       break;
-               case AUDIT_FILETYPE:
-                       if (f->val & ~S_IFMT)
-                               goto exit_free;
-                       break;
-               case AUDIT_INODE:
-                       err = audit_to_inode(&entry->rule, f);
-                       if (err)
-                               goto exit_free;
-                       break;
-               }
-       }
-
-       if (entry->rule.inode_f && entry->rule.inode_f->op == Audit_not_equal)
-               entry->rule.inode_f = NULL;
-
-exit_nofree:
-       return entry;
+       switch(f->type) {
+       case AUDIT_MSGTYPE:
+               if (entry->rule.listnr != AUDIT_FILTER_TYPE &&
+                   entry->rule.listnr != AUDIT_FILTER_USER)
+                       return -EINVAL;
+               break;
+       };
 
-exit_free:
-       audit_free_rule(entry);
-       return ERR_PTR(err);
+       switch(f->type) {
+       default:
+               return -EINVAL;
+       case AUDIT_UID:
+       case AUDIT_EUID:
+       case AUDIT_SUID:
+       case AUDIT_FSUID:
+       case AUDIT_LOGINUID:
+       case AUDIT_OBJ_UID:
+       case AUDIT_GID:
+       case AUDIT_EGID:
+       case AUDIT_SGID:
+       case AUDIT_FSGID:
+       case AUDIT_OBJ_GID:
+       case AUDIT_PID:
+       case AUDIT_PERS:
+       case AUDIT_MSGTYPE:
+       case AUDIT_PPID:
+       case AUDIT_DEVMAJOR:
+       case AUDIT_DEVMINOR:
+       case AUDIT_EXIT:
+       case AUDIT_SUCCESS:
+               /* bit ops are only useful on syscall args */
+               if (f->op == Audit_bitmask || f->op == Audit_bittest)
+                       return -EINVAL;
+               break;
+       case AUDIT_ARG0:
+       case AUDIT_ARG1:
+       case AUDIT_ARG2:
+       case AUDIT_ARG3:
+       case AUDIT_SUBJ_USER:
+       case AUDIT_SUBJ_ROLE:
+       case AUDIT_SUBJ_TYPE:
+       case AUDIT_SUBJ_SEN:
+       case AUDIT_SUBJ_CLR:
+       case AUDIT_OBJ_USER:
+       case AUDIT_OBJ_ROLE:
+       case AUDIT_OBJ_TYPE:
+       case AUDIT_OBJ_LEV_LOW:
+       case AUDIT_OBJ_LEV_HIGH:
+       case AUDIT_WATCH:
+       case AUDIT_DIR:
+       case AUDIT_FILTERKEY:
+               break;
+       case AUDIT_LOGINUID_SET:
+               if ((f->val != 0) && (f->val != 1))
+                       return -EINVAL;
+       /* FALL THROUGH */
+       case AUDIT_ARCH:
+               if (f->op != Audit_not_equal && f->op != Audit_equal)
+                       return -EINVAL;
+               break;
+       case AUDIT_PERM:
+               if (f->val & ~15)
+                       return -EINVAL;
+               break;
+       case AUDIT_FILETYPE:
+               if (f->val & ~S_IFMT)
+                       return -EINVAL;
+               break;
+       case AUDIT_FIELD_COMPARE:
+               if (f->val > AUDIT_MAX_FIELD_COMPARE)
+                       return -EINVAL;
+               break;
+       };
+       return 0;
 }
 
 /* Translate struct audit_rule_data to kernel's rule respresentation. */
@@ -459,17 +421,25 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
                f->gid = INVALID_GID;
                f->lsm_str = NULL;
                f->lsm_rule = NULL;
-               switch(f->type) {
+
+               /* Support legacy tests for a valid loginuid */
+               if ((f->type == AUDIT_LOGINUID) && (f->val == 4294967295)) {
+                       f->type = AUDIT_LOGINUID_SET;
+                       f->val = 0;
+               }
+
+               err = audit_field_valid(entry, f);
+               if (err)
+                       goto exit_free;
+
+               err = -EINVAL;
+               switch (f->type) {
+               case AUDIT_LOGINUID:
                case AUDIT_UID:
                case AUDIT_EUID:
                case AUDIT_SUID:
                case AUDIT_FSUID:
-               case AUDIT_LOGINUID:
                case AUDIT_OBJ_UID:
-                       /* bit ops not implemented for uid comparisons */
-                       if (f->op == Audit_bitmask || f->op == Audit_bittest)
-                               goto exit_free;
-
                        f->uid = make_kuid(current_user_ns(), f->val);
                        if (!uid_valid(f->uid))
                                goto exit_free;
@@ -479,27 +449,10 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
                case AUDIT_SGID:
                case AUDIT_FSGID:
                case AUDIT_OBJ_GID:
-                       /* bit ops not implemented for gid comparisons */
-                       if (f->op == Audit_bitmask || f->op == Audit_bittest)
-                               goto exit_free;
-
                        f->gid = make_kgid(current_user_ns(), f->val);
                        if (!gid_valid(f->gid))
                                goto exit_free;
                        break;
-               case AUDIT_PID:
-               case AUDIT_PERS:
-               case AUDIT_MSGTYPE:
-               case AUDIT_PPID:
-               case AUDIT_DEVMAJOR:
-               case AUDIT_DEVMINOR:
-               case AUDIT_EXIT:
-               case AUDIT_SUCCESS:
-               case AUDIT_ARG0:
-               case AUDIT_ARG1:
-               case AUDIT_ARG2:
-               case AUDIT_ARG3:
-                       break;
                case AUDIT_ARCH:
                        entry->rule.arch_f = f;
                        break;
@@ -570,20 +523,6 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
                        entry->rule.buflen += f->val;
                        entry->rule.filterkey = str;
                        break;
-               case AUDIT_PERM:
-                       if (f->val & ~15)
-                               goto exit_free;
-                       break;
-               case AUDIT_FILETYPE:
-                       if (f->val & ~S_IFMT)
-                               goto exit_free;
-                       break;
-               case AUDIT_FIELD_COMPARE:
-                       if (f->val > AUDIT_MAX_FIELD_COMPARE)
-                               goto exit_free;
-                       break;
-               default:
-                       goto exit_free;
                }
        }
 
@@ -613,36 +552,6 @@ static inline size_t audit_pack_string(void **bufp, const char *str)
        return len;
 }
 
-/* Translate kernel rule respresentation to struct audit_rule.
- * Exists for backward compatibility with userspace. */
-static struct audit_rule *audit_krule_to_rule(struct audit_krule *krule)
-{
-       struct audit_rule *rule;
-       int i;
-
-       rule = kzalloc(sizeof(*rule), GFP_KERNEL);
-       if (unlikely(!rule))
-               return NULL;
-
-       rule->flags = krule->flags | krule->listnr;
-       rule->action = krule->action;
-       rule->field_count = krule->field_count;
-       for (i = 0; i < rule->field_count; i++) {
-               rule->values[i] = krule->fields[i].val;
-               rule->fields[i] = krule->fields[i].type;
-
-               if (krule->vers_ops == 1) {
-                       if (krule->fields[i].op == Audit_not_equal)
-                               rule->fields[i] |= AUDIT_NEGATE;
-               } else {
-                       rule->fields[i] |= audit_ops[krule->fields[i].op];
-               }
-       }
-       for (i = 0; i < AUDIT_BITMASK_SIZE; i++) rule->mask[i] = krule->mask[i];
-
-       return rule;
-}
-
 /* Translate kernel rule respresentation to struct audit_rule_data. */
 static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule)
 {
@@ -1055,35 +964,6 @@ out:
        return ret;
 }
 
-/* List rules using struct audit_rule.  Exists for backward
- * compatibility with userspace. */
-static void audit_list(int pid, int seq, struct sk_buff_head *q)
-{
-       struct sk_buff *skb;
-       struct audit_krule *r;
-       int i;
-
-       /* This is a blocking read, so use audit_filter_mutex instead of rcu
-        * iterator to sync with list writers. */
-       for (i=0; i<AUDIT_NR_FILTERS; i++) {
-               list_for_each_entry(r, &audit_rules_list[i], list) {
-                       struct audit_rule *rule;
-
-                       rule = audit_krule_to_rule(r);
-                       if (unlikely(!rule))
-                               break;
-                       skb = audit_make_reply(pid, seq, AUDIT_LIST, 0, 1,
-                                        rule, sizeof(*rule));
-                       if (skb)
-                               skb_queue_tail(q, skb);
-                       kfree(rule);
-               }
-       }
-       skb = audit_make_reply(pid, seq, AUDIT_LIST, 1, 1, NULL, 0);
-       if (skb)
-               skb_queue_tail(q, skb);
-}
-
 /* List rules using struct audit_rule_data. */
 static void audit_list_rules(int pid, int seq, struct sk_buff_head *q)
 {
@@ -1113,11 +993,11 @@ static void audit_list_rules(int pid, int seq, struct sk_buff_head *q)
 }
 
 /* Log rule additions and removals */
-static void audit_log_rule_change(kuid_t loginuid, u32 sessionid, u32 sid,
-                                 char *action, struct audit_krule *rule,
-                                 int res)
+static void audit_log_rule_change(char *action, struct audit_krule *rule, int res)
 {
        struct audit_buffer *ab;
+       uid_t loginuid = from_kuid(&init_user_ns, audit_get_loginuid(current));
+       u32 sessionid = audit_get_sessionid(current);
 
        if (!audit_enabled)
                return;
@@ -1125,18 +1005,8 @@ static void audit_log_rule_change(kuid_t loginuid, u32 sessionid, u32 sid,
        ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
        if (!ab)
                return;
-       audit_log_format(ab, "auid=%u ses=%u",
-                        from_kuid(&init_user_ns, loginuid), sessionid);
-       if (sid) {
-               char *ctx = NULL;
-               u32 len;
-               if (security_secid_to_secctx(sid, &ctx, &len))
-                       audit_log_format(ab, " ssid=%u", sid);
-               else {
-                       audit_log_format(ab, " subj=%s", ctx);
-                       security_release_secctx(ctx, len);
-               }
-       }
+       audit_log_format(ab, "auid=%u ses=%u" ,loginuid, sessionid);
+       audit_log_task_context(ab);
        audit_log_format(ab, " op=");
        audit_log_string(ab, action);
        audit_log_key(ab, rule->filterkey);
@@ -1151,12 +1021,8 @@ static void audit_log_rule_change(kuid_t loginuid, u32 sessionid, u32 sid,
  * @seq: netlink audit message sequence (serial) number
  * @data: payload data
  * @datasz: size of payload data
- * @loginuid: loginuid of sender
- * @sessionid: sessionid for netlink audit message
- * @sid: SE Linux Security ID of sender
  */
-int audit_receive_filter(int type, int pid, int seq, void *data,
-                        size_t datasz, kuid_t loginuid, u32 sessionid, u32 sid)
+int audit_receive_filter(int type, int pid, int seq, void *data, size_t datasz)
 {
        struct task_struct *tsk;
        struct audit_netlink_list *dest;
@@ -1164,7 +1030,6 @@ int audit_receive_filter(int type, int pid, int seq, void *data,
        struct audit_entry *entry;
 
        switch (type) {
-       case AUDIT_LIST:
        case AUDIT_LIST_RULES:
                /* We can't just spew out the rules here because we might fill
                 * the available socket buffer space and deadlock waiting for
@@ -1179,10 +1044,7 @@ int audit_receive_filter(int type, int pid, int seq, void *data,
                skb_queue_head_init(&dest->q);
 
                mutex_lock(&audit_filter_mutex);
-               if (type == AUDIT_LIST)
-                       audit_list(pid, seq, &dest->q);
-               else
-                       audit_list_rules(pid, seq, &dest->q);
+               audit_list_rules(pid, seq, &dest->q);
                mutex_unlock(&audit_filter_mutex);
 
                tsk = kthread_run(audit_send_list, dest, "audit_send_list");
@@ -1192,35 +1054,23 @@ int audit_receive_filter(int type, int pid, int seq, void *data,
                        err = PTR_ERR(tsk);
                }
                break;
-       case AUDIT_ADD:
        case AUDIT_ADD_RULE:
-               if (type == AUDIT_ADD)
-                       entry = audit_rule_to_entry(data);
-               else
-                       entry = audit_data_to_entry(data, datasz);
+               entry = audit_data_to_entry(data, datasz);
                if (IS_ERR(entry))
                        return PTR_ERR(entry);
 
                err = audit_add_rule(entry);
-               audit_log_rule_change(loginuid, sessionid, sid, "add rule",
-                                     &entry->rule, !err);
-
+               audit_log_rule_change("add rule", &entry->rule, !err);
                if (err)
                        audit_free_rule(entry);
                break;
-       case AUDIT_DEL:
        case AUDIT_DEL_RULE:
-               if (type == AUDIT_DEL)
-                       entry = audit_rule_to_entry(data);
-               else
-                       entry = audit_data_to_entry(data, datasz);
+               entry = audit_data_to_entry(data, datasz);
                if (IS_ERR(entry))
                        return PTR_ERR(entry);
 
                err = audit_del_rule(entry);
-               audit_log_rule_change(loginuid, sessionid, sid, "remove rule",
-                                     &entry->rule, !err);
-
+               audit_log_rule_change("remove rule", &entry->rule, !err);
                audit_free_rule(entry);
                break;
        default:
@@ -1358,7 +1208,7 @@ int audit_compare_dname_path(const char *dname, const char *path, int parentlen)
        return strncmp(p, dname, dlen);
 }
 
-static int audit_filter_user_rules(struct audit_krule *rule,
+static int audit_filter_user_rules(struct audit_krule *rule, int type,
                                   enum audit_state *state)
 {
        int i;
@@ -1382,6 +1232,13 @@ static int audit_filter_user_rules(struct audit_krule *rule,
                        result = audit_uid_comparator(audit_get_loginuid(current),
                                                  f->op, f->uid);
                        break;
+               case AUDIT_LOGINUID_SET:
+                       result = audit_comparator(audit_loginuid_set(current),
+                                                 f->op, f->val);
+                       break;
+               case AUDIT_MSGTYPE:
+                       result = audit_comparator(type, f->op, f->val);
+                       break;
                case AUDIT_SUBJ_USER:
                case AUDIT_SUBJ_ROLE:
                case AUDIT_SUBJ_TYPE:
@@ -1408,7 +1265,7 @@ static int audit_filter_user_rules(struct audit_krule *rule,
        return 1;
 }
 
-int audit_filter_user(void)
+int audit_filter_user(int type)
 {
        enum audit_state state = AUDIT_DISABLED;
        struct audit_entry *e;
@@ -1416,7 +1273,7 @@ int audit_filter_user(void)
 
        rcu_read_lock();
        list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_USER], list) {
-               if (audit_filter_user_rules(&e->rule, &state)) {
+               if (audit_filter_user_rules(&e->rule, type, &state)) {
                        if (state == AUDIT_DISABLED)
                                ret = 0;
                        break;
index c682294..3c8a601 100644 (file)
 #define AUDITSC_SUCCESS 1
 #define AUDITSC_FAILURE 2
 
-/* AUDIT_NAMES is the number of slots we reserve in the audit_context
- * for saving names from getname().  If we get more names we will allocate
- * a name dynamically and also add those to the list anchored by names_list. */
-#define AUDIT_NAMES    5
-
 /* no execve audit message should be longer than this (userspace limits) */
 #define MAX_EXECVE_AUDIT_LEN 7500
 
@@ -90,44 +85,6 @@ int audit_n_rules;
 /* determines whether we collect data for signals sent */
 int audit_signals;
 
-struct audit_cap_data {
-       kernel_cap_t            permitted;
-       kernel_cap_t            inheritable;
-       union {
-               unsigned int    fE;             /* effective bit of a file capability */
-               kernel_cap_t    effective;      /* effective set of a process */
-       };
-};
-
-/* When fs/namei.c:getname() is called, we store the pointer in name and
- * we don't let putname() free it (instead we free all of the saved
- * pointers at syscall exit time).
- *
- * Further, in fs/namei.c:path_lookup() we store the inode and device.
- */
-struct audit_names {
-       struct list_head        list;           /* audit_context->names_list */
-       struct filename *name;
-       unsigned long           ino;
-       dev_t                   dev;
-       umode_t                 mode;
-       kuid_t                  uid;
-       kgid_t                  gid;
-       dev_t                   rdev;
-       u32                     osid;
-       struct audit_cap_data    fcap;
-       unsigned int            fcap_ver;
-       int                     name_len;       /* number of name's characters to log */
-       unsigned char           type;           /* record type */
-       bool                    name_put;       /* call __putname() for this name */
-       /*
-        * This was an allocated audit_names and not from the array of
-        * names allocated in the task audit context.  Thus this name
-        * should be freed on syscall exit
-        */
-       bool                    should_free;
-};
-
 struct audit_aux_data {
        struct audit_aux_data   *next;
        int                     type;
@@ -175,106 +132,6 @@ struct audit_tree_refs {
        struct audit_chunk *c[31];
 };
 
-/* The per-task audit context. */
-struct audit_context {
-       int                 dummy;      /* must be the first element */
-       int                 in_syscall; /* 1 if task is in a syscall */
-       enum audit_state    state, current_state;
-       unsigned int        serial;     /* serial number for record */
-       int                 major;      /* syscall number */
-       struct timespec     ctime;      /* time of syscall entry */
-       unsigned long       argv[4];    /* syscall arguments */
-       long                return_code;/* syscall return code */
-       u64                 prio;
-       int                 return_valid; /* return code is valid */
-       /*
-        * The names_list is the list of all audit_names collected during this
-        * syscall.  The first AUDIT_NAMES entries in the names_list will
-        * actually be from the preallocated_names array for performance
-        * reasons.  Except during allocation they should never be referenced
-        * through the preallocated_names array and should only be found/used
-        * by running the names_list.
-        */
-       struct audit_names  preallocated_names[AUDIT_NAMES];
-       int                 name_count; /* total records in names_list */
-       struct list_head    names_list; /* anchor for struct audit_names->list */
-       char *              filterkey;  /* key for rule that triggered record */
-       struct path         pwd;
-       struct audit_aux_data *aux;
-       struct audit_aux_data *aux_pids;
-       struct sockaddr_storage *sockaddr;
-       size_t sockaddr_len;
-                               /* Save things to print about task_struct */
-       pid_t               pid, ppid;
-       kuid_t              uid, euid, suid, fsuid;
-       kgid_t              gid, egid, sgid, fsgid;
-       unsigned long       personality;
-       int                 arch;
-
-       pid_t               target_pid;
-       kuid_t              target_auid;
-       kuid_t              target_uid;
-       unsigned int        target_sessionid;
-       u32                 target_sid;
-       char                target_comm[TASK_COMM_LEN];
-
-       struct audit_tree_refs *trees, *first_trees;
-       struct list_head killed_trees;
-       int tree_count;
-
-       int type;
-       union {
-               struct {
-                       int nargs;
-                       long args[6];
-               } socketcall;
-               struct {
-                       kuid_t                  uid;
-                       kgid_t                  gid;
-                       umode_t                 mode;
-                       u32                     osid;
-                       int                     has_perm;
-                       uid_t                   perm_uid;
-                       gid_t                   perm_gid;
-                       umode_t                 perm_mode;
-                       unsigned long           qbytes;
-               } ipc;
-               struct {
-                       mqd_t                   mqdes;
-                       struct mq_attr          mqstat;
-               } mq_getsetattr;
-               struct {
-                       mqd_t                   mqdes;
-                       int                     sigev_signo;
-               } mq_notify;
-               struct {
-                       mqd_t                   mqdes;
-                       size_t                  msg_len;
-                       unsigned int            msg_prio;
-                       struct timespec         abs_timeout;
-               } mq_sendrecv;
-               struct {
-                       int                     oflag;
-                       umode_t                 mode;
-                       struct mq_attr          attr;
-               } mq_open;
-               struct {
-                       pid_t                   pid;
-                       struct audit_cap_data   cap;
-               } capset;
-               struct {
-                       int                     fd;
-                       int                     flags;
-               } mmap;
-       };
-       int fds[2];
-
-#if AUDIT_DEBUG
-       int                 put_count;
-       int                 ino_count;
-#endif
-};
-
 static inline int open_arg(int flags, int mask)
 {
        int n = ACC_MODE(flags);
@@ -633,9 +490,23 @@ static int audit_filter_rules(struct task_struct *tsk,
                        break;
                case AUDIT_GID:
                        result = audit_gid_comparator(cred->gid, f->op, f->gid);
+                       if (f->op == Audit_equal) {
+                               if (!result)
+                                       result = in_group_p(f->gid);
+                       } else if (f->op == Audit_not_equal) {
+                               if (result)
+                                       result = !in_group_p(f->gid);
+                       }
                        break;
                case AUDIT_EGID:
                        result = audit_gid_comparator(cred->egid, f->op, f->gid);
+                       if (f->op == Audit_equal) {
+                               if (!result)
+                                       result = in_egroup_p(f->gid);
+                       } else if (f->op == Audit_not_equal) {
+                               if (result)
+                                       result = !in_egroup_p(f->gid);
+                       }
                        break;
                case AUDIT_SGID:
                        result = audit_gid_comparator(cred->sgid, f->op, f->gid);
@@ -742,6 +613,9 @@ static int audit_filter_rules(struct task_struct *tsk,
                        if (ctx)
                                result = audit_uid_comparator(tsk->loginuid, f->op, f->uid);
                        break;
+               case AUDIT_LOGINUID_SET:
+                       result = audit_comparator(audit_loginuid_set(tsk), f->op, f->val);
+                       break;
                case AUDIT_SUBJ_USER:
                case AUDIT_SUBJ_ROLE:
                case AUDIT_SUBJ_TYPE:
@@ -987,6 +861,8 @@ static inline void audit_free_names(struct audit_context *context)
 
 #if AUDIT_DEBUG == 2
        if (context->put_count + context->ino_count != context->name_count) {
+               int i = 0;
+
                printk(KERN_ERR "%s:%d(:%d): major=%d in_syscall=%d"
                       " name_count=%d put_count=%d"
                       " ino_count=%d [NOT freeing]\n",
@@ -995,7 +871,7 @@ static inline void audit_free_names(struct audit_context *context)
                       context->name_count, context->put_count,
                       context->ino_count);
                list_for_each_entry(n, &context->names_list, list) {
-                       printk(KERN_ERR "names[%d] = %p = %s\n", i,
+                       printk(KERN_ERR "names[%d] = %p = %s\n", i++,
                               n->name, n->name->name ?: "(null)");
                }
                dump_stack();
@@ -1010,7 +886,7 @@ static inline void audit_free_names(struct audit_context *context)
        list_for_each_entry_safe(n, next, &context->names_list, list) {
                list_del(&n->list);
                if (n->name && n->name_put)
-                       __putname(n->name);
+                       final_putname(n->name);
                if (n->should_free)
                        kfree(n);
        }
@@ -1093,88 +969,6 @@ static inline void audit_free_context(struct audit_context *context)
        kfree(context);
 }
 
-void audit_log_task_context(struct audit_buffer *ab)
-{
-       char *ctx = NULL;
-       unsigned len;
-       int error;
-       u32 sid;
-
-       security_task_getsecid(current, &sid);
-       if (!sid)
-               return;
-
-       error = security_secid_to_secctx(sid, &ctx, &len);
-       if (error) {
-               if (error != -EINVAL)
-                       goto error_path;
-               return;
-       }
-
-       audit_log_format(ab, " subj=%s", ctx);
-       security_release_secctx(ctx, len);
-       return;
-
-error_path:
-       audit_panic("error in audit_log_task_context");
-       return;
-}
-
-EXPORT_SYMBOL(audit_log_task_context);
-
-void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk)
-{
-       const struct cred *cred;
-       char name[sizeof(tsk->comm)];
-       struct mm_struct *mm = tsk->mm;
-       char *tty;
-
-       if (!ab)
-               return;
-
-       /* tsk == current */
-       cred = current_cred();
-
-       spin_lock_irq(&tsk->sighand->siglock);
-       if (tsk->signal && tsk->signal->tty)
-               tty = tsk->signal->tty->name;
-       else
-               tty = "(none)";
-       spin_unlock_irq(&tsk->sighand->siglock);
-
-
-       audit_log_format(ab,
-                        " ppid=%ld pid=%d auid=%u uid=%u gid=%u"
-                        " euid=%u suid=%u fsuid=%u"
-                        " egid=%u sgid=%u fsgid=%u ses=%u tty=%s",
-                        sys_getppid(),
-                        tsk->pid,
-                        from_kuid(&init_user_ns, tsk->loginuid),
-                        from_kuid(&init_user_ns, cred->uid),
-                        from_kgid(&init_user_ns, cred->gid),
-                        from_kuid(&init_user_ns, cred->euid),
-                        from_kuid(&init_user_ns, cred->suid),
-                        from_kuid(&init_user_ns, cred->fsuid),
-                        from_kgid(&init_user_ns, cred->egid),
-                        from_kgid(&init_user_ns, cred->sgid),
-                        from_kgid(&init_user_ns, cred->fsgid),
-                        tsk->sessionid, tty);
-
-       get_task_comm(name, tsk);
-       audit_log_format(ab, " comm=");
-       audit_log_untrustedstring(ab, name);
-
-       if (mm) {
-               down_read(&mm->mmap_sem);
-               if (mm->exe_file)
-                       audit_log_d_path(ab, " exe=", &mm->exe_file->f_path);
-               up_read(&mm->mmap_sem);
-       }
-       audit_log_task_context(ab);
-}
-
-EXPORT_SYMBOL(audit_log_task_info);
-
 static int audit_log_pid_context(struct audit_context *context, pid_t pid,
                                 kuid_t auid, kuid_t uid, unsigned int sessionid,
                                 u32 sid, char *comm)
@@ -1191,12 +985,14 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid,
        audit_log_format(ab, "opid=%d oauid=%d ouid=%d oses=%d", pid,
                         from_kuid(&init_user_ns, auid),
                         from_kuid(&init_user_ns, uid), sessionid);
-       if (security_secid_to_secctx(sid, &ctx, &len)) {
-               audit_log_format(ab, " obj=(none)");
-               rc = 1;
-       } else {
-               audit_log_format(ab, " obj=%s", ctx);
-               security_release_secctx(ctx, len);
+       if (sid) {
+               if (security_secid_to_secctx(sid, &ctx, &len)) {
+                       audit_log_format(ab, " obj=(none)");
+                       rc = 1;
+               } else {
+                       audit_log_format(ab, " obj=%s", ctx);
+                       security_release_secctx(ctx, len);
+               }
        }
        audit_log_format(ab, " ocomm=");
        audit_log_untrustedstring(ab, comm);
@@ -1390,35 +1186,6 @@ static void audit_log_execve_info(struct audit_context *context,
        kfree(buf);
 }
 
-static void audit_log_cap(struct audit_buffer *ab, char *prefix, kernel_cap_t *cap)
-{
-       int i;
-
-       audit_log_format(ab, " %s=", prefix);
-       CAP_FOR_EACH_U32(i) {
-               audit_log_format(ab, "%08x", cap->cap[(_KERNEL_CAPABILITY_U32S-1) - i]);
-       }
-}
-
-static void audit_log_fcaps(struct audit_buffer *ab, struct audit_names *name)
-{
-       kernel_cap_t *perm = &name->fcap.permitted;
-       kernel_cap_t *inh = &name->fcap.inheritable;
-       int log = 0;
-
-       if (!cap_isclear(*perm)) {
-               audit_log_cap(ab, "cap_fp", perm);
-               log = 1;
-       }
-       if (!cap_isclear(*inh)) {
-               audit_log_cap(ab, "cap_fi", inh);
-               log = 1;
-       }
-
-       if (log)
-               audit_log_format(ab, " cap_fe=%d cap_fver=%x", name->fcap.fE, name->fcap_ver);
-}
-
 static void show_special(struct audit_context *context, int *call_panic)
 {
        struct audit_buffer *ab;
@@ -1516,68 +1283,6 @@ static void show_special(struct audit_context *context, int *call_panic)
        audit_log_end(ab);
 }
 
-static void audit_log_name(struct audit_context *context, struct audit_names *n,
-                          int record_num, int *call_panic)
-{
-       struct audit_buffer *ab;
-       ab = audit_log_start(context, GFP_KERNEL, AUDIT_PATH);
-       if (!ab)
-               return; /* audit_panic has been called */
-
-       audit_log_format(ab, "item=%d", record_num);
-
-       if (n->name) {
-               switch (n->name_len) {
-               case AUDIT_NAME_FULL:
-                       /* log the full path */
-                       audit_log_format(ab, " name=");
-                       audit_log_untrustedstring(ab, n->name->name);
-                       break;
-               case 0:
-                       /* name was specified as a relative path and the
-                        * directory component is the cwd */
-                       audit_log_d_path(ab, " name=", &context->pwd);
-                       break;
-               default:
-                       /* log the name's directory component */
-                       audit_log_format(ab, " name=");
-                       audit_log_n_untrustedstring(ab, n->name->name,
-                                                   n->name_len);
-               }
-       } else
-               audit_log_format(ab, " name=(null)");
-
-       if (n->ino != (unsigned long)-1) {
-               audit_log_format(ab, " inode=%lu"
-                                " dev=%02x:%02x mode=%#ho"
-                                " ouid=%u ogid=%u rdev=%02x:%02x",
-                                n->ino,
-                                MAJOR(n->dev),
-                                MINOR(n->dev),
-                                n->mode,
-                                from_kuid(&init_user_ns, n->uid),
-                                from_kgid(&init_user_ns, n->gid),
-                                MAJOR(n->rdev),
-                                MINOR(n->rdev));
-       }
-       if (n->osid != 0) {
-               char *ctx = NULL;
-               u32 len;
-               if (security_secid_to_secctx(
-                       n->osid, &ctx, &len)) {
-                       audit_log_format(ab, " osid=%u", n->osid);
-                       *call_panic = 2;
-               } else {
-                       audit_log_format(ab, " obj=%s", ctx);
-                       security_release_secctx(ctx, len);
-               }
-       }
-
-       audit_log_fcaps(ab, n);
-
-       audit_log_end(ab);
-}
-
 static void audit_log_exit(struct audit_context *context, struct task_struct *tsk)
 {
        int i, call_panic = 0;
@@ -1695,7 +1400,7 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
 
        i = 0;
        list_for_each_entry(n, &context->names_list, list)
-               audit_log_name(context, n, i++, &call_panic);
+               audit_log_name(context, n, NULL, i++, &call_panic);
 
        /* Send end of event record to help user space know we are finished */
        ab = audit_log_start(context, GFP_KERNEL, AUDIT_EOE);
@@ -2030,18 +1735,18 @@ void audit_putname(struct filename *name)
        BUG_ON(!context);
        if (!context->in_syscall) {
 #if AUDIT_DEBUG == 2
-               printk(KERN_ERR "%s:%d(:%d): __putname(%p)\n",
+               printk(KERN_ERR "%s:%d(:%d): final_putname(%p)\n",
                       __FILE__, __LINE__, context->serial, name);
                if (context->name_count) {
                        struct audit_names *n;
-                       int i;
+                       int i = 0;
 
                        list_for_each_entry(n, &context->names_list, list)
-                               printk(KERN_ERR "name[%d] = %p = %s\n", i,
+                               printk(KERN_ERR "name[%d] = %p = %s\n", i++,
                                       n->name, n->name->name ?: "(null)");
                        }
 #endif
-               __putname(name);
+               final_putname(name);
        }
 #if AUDIT_DEBUG
        else {
@@ -2060,41 +1765,6 @@ void audit_putname(struct filename *name)
 #endif
 }
 
-static inline int audit_copy_fcaps(struct audit_names *name, const struct dentry *dentry)
-{
-       struct cpu_vfs_cap_data caps;
-       int rc;
-
-       if (!dentry)
-               return 0;
-
-       rc = get_vfs_caps_from_disk(dentry, &caps);
-       if (rc)
-               return rc;
-
-       name->fcap.permitted = caps.permitted;
-       name->fcap.inheritable = caps.inheritable;
-       name->fcap.fE = !!(caps.magic_etc & VFS_CAP_FLAGS_EFFECTIVE);
-       name->fcap_ver = (caps.magic_etc & VFS_CAP_REVISION_MASK) >> VFS_CAP_REVISION_SHIFT;
-
-       return 0;
-}
-
-
-/* Copy inode data into an audit_names. */
-static void audit_copy_inode(struct audit_names *name, const struct dentry *dentry,
-                            const struct inode *inode)
-{
-       name->ino   = inode->i_ino;
-       name->dev   = inode->i_sb->s_dev;
-       name->mode  = inode->i_mode;
-       name->uid   = inode->i_uid;
-       name->gid   = inode->i_gid;
-       name->rdev  = inode->i_rdev;
-       security_inode_getsecid(inode, &name->osid);
-       audit_copy_fcaps(name, dentry);
-}
-
 /**
  * __audit_inode - store the inode and device from a lookup
  * @name: name being audited
@@ -2303,7 +1973,7 @@ int audit_set_loginuid(kuid_t loginuid)
        unsigned int sessionid;
 
 #ifdef CONFIG_AUDIT_LOGINUID_IMMUTABLE
-       if (uid_valid(task->loginuid))
+       if (audit_loginuid_set(task))
                return -EPERM;
 #else /* CONFIG_AUDIT_LOGINUID_IMMUTABLE */
        if (!capable(CAP_AUDIT_CONTROL))
@@ -2471,17 +2141,20 @@ int __audit_bprm(struct linux_binprm *bprm)
 
 /**
  * audit_socketcall - record audit data for sys_socketcall
- * @nargs: number of args
+ * @nargs: number of args, which should not be more than AUDITSC_ARGS.
  * @args: args array
  *
  */
-void __audit_socketcall(int nargs, unsigned long *args)
+int __audit_socketcall(int nargs, unsigned long *args)
 {
        struct audit_context *context = current->audit_context;
 
+       if (nargs <= 0 || nargs > AUDITSC_ARGS || !args)
+               return -EINVAL;
        context->type = AUDIT_SOCKETCALL;
        context->socketcall.nargs = nargs;
        memcpy(context->socketcall.args, args, nargs * sizeof(unsigned long));
+       return 0;
 }
 
 /**
index 2a99262..a7c9e6d 100644 (file)
@@ -1686,11 +1686,14 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
                 */
                cgroup_drop_root(opts.new_root);
 
-               if (((root->flags | opts.flags) & CGRP_ROOT_SANE_BEHAVIOR) &&
-                   root->flags != opts.flags) {
-                       pr_err("cgroup: sane_behavior: new mount options should match the existing superblock\n");
-                       ret = -EINVAL;
-                       goto drop_new_super;
+               if (root->flags != opts.flags) {
+                       if ((root->flags | opts.flags) & CGRP_ROOT_SANE_BEHAVIOR) {
+                               pr_err("cgroup: sane_behavior: new mount options should match the existing superblock\n");
+                               ret = -EINVAL;
+                               goto drop_new_super;
+                       } else {
+                               pr_warning("cgroup: new mount options do not match the existing superblock, will be ignored\n");
+                       }
                }
 
                /* no subsys rebinding, so refcounts don't change */
@@ -2699,13 +2702,14 @@ static int cgroup_add_file(struct cgroup *cgrp, struct cgroup_subsys *subsys,
                goto out;
        }
 
+       cfe->type = (void *)cft;
+       cfe->dentry = dentry;
+       dentry->d_fsdata = cfe;
+       simple_xattrs_init(&cfe->xattrs);
+
        mode = cgroup_file_mode(cft);
        error = cgroup_create_file(dentry, mode | S_IFREG, cgrp->root->sb);
        if (!error) {
-               cfe->type = (void *)cft;
-               cfe->dentry = dentry;
-               dentry->d_fsdata = cfe;
-               simple_xattrs_init(&cfe->xattrs);
                list_add_tail(&cfe->node, &parent->files);
                cfe = NULL;
        }
@@ -2953,11 +2957,8 @@ struct cgroup *cgroup_next_descendant_pre(struct cgroup *pos,
        WARN_ON_ONCE(!rcu_read_lock_held());
 
        /* if first iteration, pretend we just visited @cgroup */
-       if (!pos) {
-               if (list_empty(&cgroup->children))
-                       return NULL;
+       if (!pos)
                pos = cgroup;
-       }
 
        /* visit the first child if exists */
        next = list_first_or_null_rcu(&pos->children, struct cgroup, sibling);
@@ -2965,14 +2966,14 @@ struct cgroup *cgroup_next_descendant_pre(struct cgroup *pos,
                return next;
 
        /* no child, visit my or the closest ancestor's next sibling */
-       do {
+       while (pos != cgroup) {
                next = list_entry_rcu(pos->sibling.next, struct cgroup,
                                      sibling);
                if (&next->sibling != &pos->parent->children)
                        return next;
 
                pos = pos->parent;
-       } while (pos != cgroup);
+       }
 
        return NULL;
 }
index b5e4ab2..198a388 100644 (file)
@@ -133,6 +133,27 @@ static void cpu_hotplug_done(void)
        mutex_unlock(&cpu_hotplug.lock);
 }
 
+/*
+ * Wait for currently running CPU hotplug operations to complete (if any) and
+ * disable future CPU hotplug (from sysfs). The 'cpu_add_remove_lock' protects
+ * the 'cpu_hotplug_disabled' flag. The same lock is also acquired by the
+ * hotplug path before performing hotplug operations. So acquiring that lock
+ * guarantees mutual exclusion from any currently running hotplug operations.
+ */
+void cpu_hotplug_disable(void)
+{
+       cpu_maps_update_begin();
+       cpu_hotplug_disabled = 1;
+       cpu_maps_update_done();
+}
+
+void cpu_hotplug_enable(void)
+{
+       cpu_maps_update_begin();
+       cpu_hotplug_disabled = 0;
+       cpu_maps_update_done();
+}
+
 #else /* #if CONFIG_HOTPLUG_CPU */
 static void cpu_hotplug_begin(void) {}
 static void cpu_hotplug_done(void) {}
@@ -540,36 +561,6 @@ static int __init alloc_frozen_cpus(void)
 }
 core_initcall(alloc_frozen_cpus);
 
-/*
- * Prevent regular CPU hotplug from racing with the freezer, by disabling CPU
- * hotplug when tasks are about to be frozen. Also, don't allow the freezer
- * to continue until any currently running CPU hotplug operation gets
- * completed.
- * To modify the 'cpu_hotplug_disabled' flag, we need to acquire the
- * 'cpu_add_remove_lock'. And this same lock is also taken by the regular
- * CPU hotplug path and released only after it is complete. Thus, we
- * (and hence the freezer) will block here until any currently running CPU
- * hotplug operation gets completed.
- */
-void cpu_hotplug_disable_before_freeze(void)
-{
-       cpu_maps_update_begin();
-       cpu_hotplug_disabled = 1;
-       cpu_maps_update_done();
-}
-
-
-/*
- * When tasks have been thawed, re-enable regular CPU hotplug (which had been
- * disabled while beginning to freeze tasks).
- */
-void cpu_hotplug_enable_after_thaw(void)
-{
-       cpu_maps_update_begin();
-       cpu_hotplug_disabled = 0;
-       cpu_maps_update_done();
-}
-
 /*
  * When callbacks for CPU hotplug notifications are being executed, we must
  * ensure that the state of the system with respect to the tasks being frozen
@@ -589,12 +580,12 @@ cpu_hotplug_pm_callback(struct notifier_block *nb,
 
        case PM_SUSPEND_PREPARE:
        case PM_HIBERNATION_PREPARE:
-               cpu_hotplug_disable_before_freeze();
+               cpu_hotplug_disable();
                break;
 
        case PM_POST_SUSPEND:
        case PM_POST_HIBERNATION:
-               cpu_hotplug_enable_after_thaw();
+               cpu_hotplug_enable();
                break;
 
        default:
index 8b86c0c..d5585f5 100644 (file)
@@ -40,11 +40,13 @@ __setup("hlt", cpu_idle_nopoll_setup);
 
 static inline int cpu_idle_poll(void)
 {
+       rcu_idle_enter();
        trace_cpu_idle_rcuidle(0, smp_processor_id());
        local_irq_enable();
        while (!need_resched())
                cpu_relax();
        trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, smp_processor_id());
+       rcu_idle_exit();
        return 1;
 }
 
index 6b41c18..9dc297f 100644 (file)
@@ -4394,6 +4394,64 @@ perf_event_read_event(struct perf_event *event,
        perf_output_end(&handle);
 }
 
+typedef int  (perf_event_aux_match_cb)(struct perf_event *event, void *data);
+typedef void (perf_event_aux_output_cb)(struct perf_event *event, void *data);
+
+static void
+perf_event_aux_ctx(struct perf_event_context *ctx,
+                  perf_event_aux_match_cb match,
+                  perf_event_aux_output_cb output,
+                  void *data)
+{
+       struct perf_event *event;
+
+       list_for_each_entry_rcu(event, &ctx->event_list, event_entry) {
+               if (event->state < PERF_EVENT_STATE_INACTIVE)
+                       continue;
+               if (!event_filter_match(event))
+                       continue;
+               if (match(event, data))
+                       output(event, data);
+       }
+}
+
+static void
+perf_event_aux(perf_event_aux_match_cb match,
+              perf_event_aux_output_cb output,
+              void *data,
+              struct perf_event_context *task_ctx)
+{
+       struct perf_cpu_context *cpuctx;
+       struct perf_event_context *ctx;
+       struct pmu *pmu;
+       int ctxn;
+
+       rcu_read_lock();
+       list_for_each_entry_rcu(pmu, &pmus, entry) {
+               cpuctx = get_cpu_ptr(pmu->pmu_cpu_context);
+               if (cpuctx->unique_pmu != pmu)
+                       goto next;
+               perf_event_aux_ctx(&cpuctx->ctx, match, output, data);
+               if (task_ctx)
+                       goto next;
+               ctxn = pmu->task_ctx_nr;
+               if (ctxn < 0)
+                       goto next;
+               ctx = rcu_dereference(current->perf_event_ctxp[ctxn]);
+               if (ctx)
+                       perf_event_aux_ctx(ctx, match, output, data);
+next:
+               put_cpu_ptr(pmu->pmu_cpu_context);
+       }
+
+       if (task_ctx) {
+               preempt_disable();
+               perf_event_aux_ctx(task_ctx, match, output, data);
+               preempt_enable();
+       }
+       rcu_read_unlock();
+}
+
 /*
  * task tracking -- fork/exit
  *
@@ -4416,8 +4474,9 @@ struct perf_task_event {
 };
 
 static void perf_event_task_output(struct perf_event *event,
-                                    struct perf_task_event *task_event)
+                                  void *data)
 {
+       struct perf_task_event *task_event = data;
        struct perf_output_handle handle;
        struct perf_sample_data sample;
        struct task_struct *task = task_event->task;
@@ -4445,62 +4504,11 @@ out:
        task_event->event_id.header.size = size;
 }
 
-static int perf_event_task_match(struct perf_event *event)
-{
-       if (event->state < PERF_EVENT_STATE_INACTIVE)
-               return 0;
-
-       if (!event_filter_match(event))
-               return 0;
-
-       if (event->attr.comm || event->attr.mmap ||
-           event->attr.mmap_data || event->attr.task)
-               return 1;
-
-       return 0;
-}
-
-static void perf_event_task_ctx(struct perf_event_context *ctx,
-                                 struct perf_task_event *task_event)
+static int perf_event_task_match(struct perf_event *event,
+                                void *data __maybe_unused)
 {
-       struct perf_event *event;
-
-       list_for_each_entry_rcu(event, &ctx->event_list, event_entry) {
-               if (perf_event_task_match(event))
-                       perf_event_task_output(event, task_event);
-       }
-}
-
-static void perf_event_task_event(struct perf_task_event *task_event)
-{
-       struct perf_cpu_context *cpuctx;
-       struct perf_event_context *ctx;
-       struct pmu *pmu;
-       int ctxn;
-
-       rcu_read_lock();
-       list_for_each_entry_rcu(pmu, &pmus, entry) {
-               cpuctx = get_cpu_ptr(pmu->pmu_cpu_context);
-               if (cpuctx->unique_pmu != pmu)
-                       goto next;
-               perf_event_task_ctx(&cpuctx->ctx, task_event);
-
-               ctx = task_event->task_ctx;
-               if (!ctx) {
-                       ctxn = pmu->task_ctx_nr;
-                       if (ctxn < 0)
-                               goto next;
-                       ctx = rcu_dereference(current->perf_event_ctxp[ctxn]);
-                       if (ctx)
-                               perf_event_task_ctx(ctx, task_event);
-               }
-next:
-               put_cpu_ptr(pmu->pmu_cpu_context);
-       }
-       if (task_event->task_ctx)
-               perf_event_task_ctx(task_event->task_ctx, task_event);
-
-       rcu_read_unlock();
+       return event->attr.comm || event->attr.mmap ||
+              event->attr.mmap_data || event->attr.task;
 }
 
 static void perf_event_task(struct task_struct *task,
@@ -4531,7 +4539,10 @@ static void perf_event_task(struct task_struct *task,
                },
        };
 
-       perf_event_task_event(&task_event);
+       perf_event_aux(perf_event_task_match,
+                      perf_event_task_output,
+                      &task_event,
+                      task_ctx);
 }
 
 void perf_event_fork(struct task_struct *task)
@@ -4557,8 +4568,9 @@ struct perf_comm_event {
 };
 
 static void perf_event_comm_output(struct perf_event *event,
-                                    struct perf_comm_event *comm_event)
+                                  void *data)
 {
+       struct perf_comm_event *comm_event = data;
        struct perf_output_handle handle;
        struct perf_sample_data sample;
        int size = comm_event->event_id.header.size;
@@ -4585,39 +4597,16 @@ out:
        comm_event->event_id.header.size = size;
 }
 
-static int perf_event_comm_match(struct perf_event *event)
-{
-       if (event->state < PERF_EVENT_STATE_INACTIVE)
-               return 0;
-
-       if (!event_filter_match(event))
-               return 0;
-
-       if (event->attr.comm)
-               return 1;
-
-       return 0;
-}
-
-static void perf_event_comm_ctx(struct perf_event_context *ctx,
-                                 struct perf_comm_event *comm_event)
+static int perf_event_comm_match(struct perf_event *event,
+                                void *data __maybe_unused)
 {
-       struct perf_event *event;
-
-       list_for_each_entry_rcu(event, &ctx->event_list, event_entry) {
-               if (perf_event_comm_match(event))
-                       perf_event_comm_output(event, comm_event);
-       }
+       return event->attr.comm;
 }
 
 static void perf_event_comm_event(struct perf_comm_event *comm_event)
 {
-       struct perf_cpu_context *cpuctx;
-       struct perf_event_context *ctx;
        char comm[TASK_COMM_LEN];
        unsigned int size;
-       struct pmu *pmu;
-       int ctxn;
 
        memset(comm, 0, sizeof(comm));
        strlcpy(comm, comm_event->task->comm, sizeof(comm));
@@ -4627,24 +4616,11 @@ static void perf_event_comm_event(struct perf_comm_event *comm_event)
        comm_event->comm_size = size;
 
        comm_event->event_id.header.size = sizeof(comm_event->event_id) + size;
-       rcu_read_lock();
-       list_for_each_entry_rcu(pmu, &pmus, entry) {
-               cpuctx = get_cpu_ptr(pmu->pmu_cpu_context);
-               if (cpuctx->unique_pmu != pmu)
-                       goto next;
-               perf_event_comm_ctx(&cpuctx->ctx, comm_event);
 
-               ctxn = pmu->task_ctx_nr;
-               if (ctxn < 0)
-                       goto next;
-
-               ctx = rcu_dereference(current->perf_event_ctxp[ctxn]);
-               if (ctx)
-                       perf_event_comm_ctx(ctx, comm_event);
-next:
-               put_cpu_ptr(pmu->pmu_cpu_context);
-       }
-       rcu_read_unlock();
+       perf_event_aux(perf_event_comm_match,
+                      perf_event_comm_output,
+                      comm_event,
+                      NULL);
 }
 
 void perf_event_comm(struct task_struct *task)
@@ -4706,8 +4682,9 @@ struct perf_mmap_event {
 };
 
 static void perf_event_mmap_output(struct perf_event *event,
-                                    struct perf_mmap_event *mmap_event)
+                                  void *data)
 {
+       struct perf_mmap_event *mmap_event = data;
        struct perf_output_handle handle;
        struct perf_sample_data sample;
        int size = mmap_event->event_id.header.size;
@@ -4734,46 +4711,24 @@ out:
 }
 
 static int perf_event_mmap_match(struct perf_event *event,
-                                  struct perf_mmap_event *mmap_event,
-                                  int executable)
-{
-       if (event->state < PERF_EVENT_STATE_INACTIVE)
-               return 0;
-
-       if (!event_filter_match(event))
-               return 0;
-
-       if ((!executable && event->attr.mmap_data) ||
-           (executable && event->attr.mmap))
-               return 1;
-
-       return 0;
-}
-
-static void perf_event_mmap_ctx(struct perf_event_context *ctx,
-                                 struct perf_mmap_event *mmap_event,
-                                 int executable)
+                                void *data)
 {
-       struct perf_event *event;
+       struct perf_mmap_event *mmap_event = data;
+       struct vm_area_struct *vma = mmap_event->vma;
+       int executable = vma->vm_flags & VM_EXEC;
 
-       list_for_each_entry_rcu(event, &ctx->event_list, event_entry) {
-               if (perf_event_mmap_match(event, mmap_event, executable))
-                       perf_event_mmap_output(event, mmap_event);
-       }
+       return (!executable && event->attr.mmap_data) ||
+              (executable && event->attr.mmap);
 }
 
 static void perf_event_mmap_event(struct perf_mmap_event *mmap_event)
 {
-       struct perf_cpu_context *cpuctx;
-       struct perf_event_context *ctx;
        struct vm_area_struct *vma = mmap_event->vma;
        struct file *file = vma->vm_file;
        unsigned int size;
        char tmp[16];
        char *buf = NULL;
        const char *name;
-       struct pmu *pmu;
-       int ctxn;
 
        memset(tmp, 0, sizeof(tmp));
 
@@ -4829,27 +4784,10 @@ got_name:
 
        mmap_event->event_id.header.size = sizeof(mmap_event->event_id) + size;
 
-       rcu_read_lock();
-       list_for_each_entry_rcu(pmu, &pmus, entry) {
-               cpuctx = get_cpu_ptr(pmu->pmu_cpu_context);
-               if (cpuctx->unique_pmu != pmu)
-                       goto next;
-               perf_event_mmap_ctx(&cpuctx->ctx, mmap_event,
-                                       vma->vm_flags & VM_EXEC);
-
-               ctxn = pmu->task_ctx_nr;
-               if (ctxn < 0)
-                       goto next;
-
-               ctx = rcu_dereference(current->perf_event_ctxp[ctxn]);
-               if (ctx) {
-                       perf_event_mmap_ctx(ctx, mmap_event,
-                                       vma->vm_flags & VM_EXEC);
-               }
-next:
-               put_cpu_ptr(pmu->pmu_cpu_context);
-       }
-       rcu_read_unlock();
+       perf_event_aux(perf_event_mmap_match,
+                      perf_event_mmap_output,
+                      mmap_event,
+                      NULL);
 
        kfree(buf);
 }
index 5a83dde..54a4d52 100644 (file)
@@ -143,7 +143,10 @@ static unsigned int irq_domain_legacy_revmap(struct irq_domain *domain,
  * irq_domain_add_simple() - Allocate and register a simple irq_domain.
  * @of_node: pointer to interrupt controller's device tree node.
  * @size: total number of irqs in mapping
- * @first_irq: first number of irq block assigned to the domain
+ * @first_irq: first number of irq block assigned to the domain,
+ *     pass zero to assign irqs on-the-fly. This will result in a
+ *     linear IRQ domain so it is important to use irq_create_mapping()
+ *     for each used IRQ, especially when SPARSE_IRQ is enabled.
  * @ops: map/unmap domain callbacks
  * @host_data: Controller private data pointer
  *
@@ -191,6 +194,7 @@ struct irq_domain *irq_domain_add_simple(struct device_node *of_node,
        /* A linear domain is the default */
        return irq_domain_add_linear(of_node, size, ops, host_data);
 }
+EXPORT_SYMBOL_GPL(irq_domain_add_simple);
 
 /**
  * irq_domain_add_legacy() - Allocate and register a legacy revmap irq_domain.
@@ -397,11 +401,12 @@ static void irq_domain_disassociate_many(struct irq_domain *domain,
        while (count--) {
                int irq = irq_base + count;
                struct irq_data *irq_data = irq_get_irq_data(irq);
-               irq_hw_number_t hwirq = irq_data->hwirq;
+               irq_hw_number_t hwirq;
 
                if (WARN_ON(!irq_data || irq_data->domain != domain))
                        continue;
 
+               hwirq = irq_data->hwirq;
                irq_set_status_flags(irq, IRQ_NOREQUEST);
 
                /* remove chip and handler */
index 1296e72..8241906 100644 (file)
@@ -569,6 +569,11 @@ int call_usermodehelper_exec(struct subprocess_info *sub_info, int wait)
        int retval = 0;
 
        helper_lock();
+       if (!sub_info->path) {
+               retval = -EINVAL;
+               goto out;
+       }
+
        if (sub_info->path[0] == '\0')
                goto out;
 
index b049939..cab4bce 100644 (file)
@@ -2431,10 +2431,10 @@ static void kmemleak_load_module(const struct module *mod,
        kmemleak_scan_area(mod, sizeof(struct module), GFP_KERNEL);
 
        for (i = 1; i < info->hdr->e_shnum; i++) {
-               const char *name = info->secstrings + info->sechdrs[i].sh_name;
-               if (!(info->sechdrs[i].sh_flags & SHF_ALLOC))
-                       continue;
-               if (!strstarts(name, ".data") && !strstarts(name, ".bss"))
+               /* Scan all writable sections that's not executable */
+               if (!(info->sechdrs[i].sh_flags & SHF_ALLOC) ||
+                   !(info->sechdrs[i].sh_flags & SHF_WRITE) ||
+                   (info->sechdrs[i].sh_flags & SHF_EXECINSTR))
                        continue;
 
                kmemleak_scan_area((void *)info->sechdrs[i].sh_addr,
@@ -2769,24 +2769,11 @@ static void find_module_sections(struct module *mod, struct load_info *info)
        mod->trace_events = section_objs(info, "_ftrace_events",
                                         sizeof(*mod->trace_events),
                                         &mod->num_trace_events);
-       /*
-        * This section contains pointers to allocated objects in the trace
-        * code and not scanning it leads to false positives.
-        */
-       kmemleak_scan_area(mod->trace_events, sizeof(*mod->trace_events) *
-                          mod->num_trace_events, GFP_KERNEL);
 #endif
 #ifdef CONFIG_TRACING
        mod->trace_bprintk_fmt_start = section_objs(info, "__trace_printk_fmt",
                                         sizeof(*mod->trace_bprintk_fmt_start),
                                         &mod->num_trace_bprintk_fmt);
-       /*
-        * This section contains pointers to allocated objects in the trace
-        * code and not scanning it leads to false positives.
-        */
-       kmemleak_scan_area(mod->trace_bprintk_fmt_start,
-                          sizeof(*mod->trace_bprintk_fmt_start) *
-                          mod->num_trace_bprintk_fmt, GFP_KERNEL);
 #endif
 #ifdef CONFIG_FTRACE_MCOUNT_RECORD
        /* sechdrs[0].sh_size is always zero */
index ed35345..53b958f 100644 (file)
@@ -613,10 +613,13 @@ static __modinit int add_sysfs_param(struct module_kobject *mk,
                       sizeof(*mk->mp) + sizeof(mk->mp->attrs[0]) * (num+1),
                       GFP_KERNEL);
        if (!new) {
-               kfree(mk->mp);
+               kfree(attrs);
                err = -ENOMEM;
                goto fail;
        }
+       /* Despite looking like the typical realloc() bug, this is safe.
+        * We *want* the old 'attrs' to be freed either way, and we'll store
+        * the new one in the success case. */
        attrs = krealloc(attrs, sizeof(new->grp.attrs[0])*(num+2), GFP_KERNEL);
        if (!attrs) {
                err = -ENOMEM;
index fa36e14..8212c1a 100644 (file)
@@ -363,6 +363,53 @@ static void log_store(int facility, int level,
        log_next_seq++;
 }
 
+#ifdef CONFIG_SECURITY_DMESG_RESTRICT
+int dmesg_restrict = 1;
+#else
+int dmesg_restrict;
+#endif
+
+static int syslog_action_restricted(int type)
+{
+       if (dmesg_restrict)
+               return 1;
+       /*
+        * Unless restricted, we allow "read all" and "get buffer size"
+        * for everybody.
+        */
+       return type != SYSLOG_ACTION_READ_ALL &&
+              type != SYSLOG_ACTION_SIZE_BUFFER;
+}
+
+static int check_syslog_permissions(int type, bool from_file)
+{
+       /*
+        * If this is from /proc/kmsg and we've already opened it, then we've
+        * already done the capabilities checks at open time.
+        */
+       if (from_file && type != SYSLOG_ACTION_OPEN)
+               return 0;
+
+       if (syslog_action_restricted(type)) {
+               if (capable(CAP_SYSLOG))
+                       return 0;
+               /*
+                * For historical reasons, accept CAP_SYS_ADMIN too, with
+                * a warning.
+                */
+               if (capable(CAP_SYS_ADMIN)) {
+                       pr_warn_once("%s (%d): Attempt to access syslog with "
+                                    "CAP_SYS_ADMIN but no CAP_SYSLOG "
+                                    "(deprecated).\n",
+                                current->comm, task_pid_nr(current));
+                       return 0;
+               }
+               return -EPERM;
+       }
+       return security_syslog(type);
+}
+
+
 /* /dev/kmsg - userspace message inject/listen interface */
 struct devkmsg_user {
        u64 seq;
@@ -620,7 +667,8 @@ static int devkmsg_open(struct inode *inode, struct file *file)
        if ((file->f_flags & O_ACCMODE) == O_WRONLY)
                return 0;
 
-       err = security_syslog(SYSLOG_ACTION_READ_ALL);
+       err = check_syslog_permissions(SYSLOG_ACTION_READ_ALL,
+                                      SYSLOG_FROM_READER);
        if (err)
                return err;
 
@@ -813,45 +861,6 @@ static inline void boot_delay_msec(int level)
 }
 #endif
 
-#ifdef CONFIG_SECURITY_DMESG_RESTRICT
-int dmesg_restrict = 1;
-#else
-int dmesg_restrict;
-#endif
-
-static int syslog_action_restricted(int type)
-{
-       if (dmesg_restrict)
-               return 1;
-       /* Unless restricted, we allow "read all" and "get buffer size" for everybody */
-       return type != SYSLOG_ACTION_READ_ALL && type != SYSLOG_ACTION_SIZE_BUFFER;
-}
-
-static int check_syslog_permissions(int type, bool from_file)
-{
-       /*
-        * If this is from /proc/kmsg and we've already opened it, then we've
-        * already done the capabilities checks at open time.
-        */
-       if (from_file && type != SYSLOG_ACTION_OPEN)
-               return 0;
-
-       if (syslog_action_restricted(type)) {
-               if (capable(CAP_SYSLOG))
-                       return 0;
-               /* For historical reasons, accept CAP_SYS_ADMIN too, with a warning */
-               if (capable(CAP_SYS_ADMIN)) {
-                       printk_once(KERN_WARNING "%s (%d): "
-                                "Attempt to access syslog with CAP_SYS_ADMIN "
-                                "but no CAP_SYSLOG (deprecated).\n",
-                                current->comm, task_pid_nr(current));
-                       return 0;
-               }
-               return -EPERM;
-       }
-       return 0;
-}
-
 #if defined(CONFIG_PRINTK_TIME)
 static bool printk_time = 1;
 #else
@@ -1249,7 +1258,7 @@ out:
 
 SYSCALL_DEFINE3(syslog, int, type, char __user *, buf, int, len)
 {
-       return do_syslog(type, buf, len, SYSLOG_FROM_CALL);
+       return do_syslog(type, buf, len, SYSLOG_FROM_READER);
 }
 
 /*
index 071b0ab..eb911db 100644 (file)
@@ -48,9 +48,11 @@ int add_range_with_merge(struct range *range, int az, int nr_range,
                final_start = min(range[i].start, start);
                final_end = max(range[i].end, end);
 
-               range[i].start = final_start;
-               range[i].end =  final_end;
-               return nr_range;
+               /* clear it and add it back for further merge */
+               range[i].start = 0;
+               range[i].end =  0;
+               return add_range_with_merge(range, az, nr_range,
+                       final_start, final_end);
        }
 
        /* Need to add it: */
index 170814d..3db5a37 100644 (file)
@@ -88,7 +88,7 @@ static void __init rcu_bootup_announce_oddness(void)
 #ifdef CONFIG_RCU_NOCB_CPU
 #ifndef CONFIG_RCU_NOCB_CPU_NONE
        if (!have_rcu_nocb_mask) {
-               alloc_bootmem_cpumask_var(&rcu_nocb_mask);
+               zalloc_cpumask_var(&rcu_nocb_mask, GFP_KERNEL);
                have_rcu_nocb_mask = true;
        }
 #ifdef CONFIG_RCU_NOCB_CPU_ZERO
@@ -1667,7 +1667,7 @@ int rcu_needs_cpu(int cpu, unsigned long *dj)
        rdtp->last_accelerate = jiffies;
 
        /* Request timer delay depending on laziness, and round. */
-       if (rdtp->all_lazy) {
+       if (!rdtp->all_lazy) {
                *dj = round_up(rcu_idle_gp_delay + jiffies,
                               rcu_idle_gp_delay) - jiffies;
        } else {
index b5197dc..3d6833f 100644 (file)
@@ -195,8 +195,12 @@ void local_bh_enable_ip(unsigned long ip)
 EXPORT_SYMBOL(local_bh_enable_ip);
 
 /*
- * We restart softirq processing for at most 2 ms,
- * and if need_resched() is not set.
+ * We restart softirq processing for at most MAX_SOFTIRQ_RESTART times,
+ * but break the loop if need_resched() is set or after 2 ms.
+ * The MAX_SOFTIRQ_TIME provides a nice upper bound in most cases, but in
+ * certain cases, such as stop_machine(), jiffies may cease to
+ * increment and so we need the MAX_SOFTIRQ_RESTART limit as
+ * well to make sure we eventually return from this method.
  *
  * These limits have been established via experimentation.
  * The two things to balance is latency against fairness -
@@ -204,6 +208,7 @@ EXPORT_SYMBOL(local_bh_enable_ip);
  * should not be able to lock up the box.
  */
 #define MAX_SOFTIRQ_TIME  msecs_to_jiffies(2)
+#define MAX_SOFTIRQ_RESTART 10
 
 asmlinkage void __do_softirq(void)
 {
@@ -212,6 +217,7 @@ asmlinkage void __do_softirq(void)
        unsigned long end = jiffies + MAX_SOFTIRQ_TIME;
        int cpu;
        unsigned long old_flags = current->flags;
+       int max_restart = MAX_SOFTIRQ_RESTART;
 
        /*
         * Mask out PF_MEMALLOC s current task context is borrowed for the
@@ -265,7 +271,8 @@ restart:
 
        pending = local_softirq_pending();
        if (pending) {
-               if (time_before(jiffies, end) && !need_resched())
+               if (time_before(jiffies, end) && !need_resched() &&
+                   --max_restart)
                        goto restart;
 
                wakeup_softirqd();
index b95d3c7..2bbd9a7 100644 (file)
@@ -362,6 +362,29 @@ int unregister_reboot_notifier(struct notifier_block *nb)
 }
 EXPORT_SYMBOL(unregister_reboot_notifier);
 
+/* Add backwards compatibility for stable trees. */
+#ifndef PF_NO_SETAFFINITY
+#define PF_NO_SETAFFINITY              PF_THREAD_BOUND
+#endif
+
+static void migrate_to_reboot_cpu(void)
+{
+       /* The boot cpu is always logical cpu 0 */
+       int cpu = 0;
+
+       cpu_hotplug_disable();
+
+       /* Make certain the cpu I'm about to reboot on is online */
+       if (!cpu_online(cpu))
+               cpu = cpumask_first(cpu_online_mask);
+
+       /* Prevent races with other tasks migrating this task */
+       current->flags |= PF_NO_SETAFFINITY;
+
+       /* Make certain I only run on the appropriate processor */
+       set_cpus_allowed_ptr(current, cpumask_of(cpu));
+}
+
 /**
  *     kernel_restart - reboot the system
  *     @cmd: pointer to buffer containing command to execute for restart
@@ -373,7 +396,7 @@ EXPORT_SYMBOL(unregister_reboot_notifier);
 void kernel_restart(char *cmd)
 {
        kernel_restart_prepare(cmd);
-       disable_nonboot_cpus();
+       migrate_to_reboot_cpu();
        syscore_shutdown();
        if (!cmd)
                printk(KERN_EMERG "Restarting system.\n");
@@ -400,7 +423,7 @@ static void kernel_shutdown_prepare(enum system_states state)
 void kernel_halt(void)
 {
        kernel_shutdown_prepare(SYSTEM_HALT);
-       disable_nonboot_cpus();
+       migrate_to_reboot_cpu();
        syscore_shutdown();
        printk(KERN_EMERG "System halted.\n");
        kmsg_dump(KMSG_DUMP_HALT);
@@ -419,7 +442,7 @@ void kernel_power_off(void)
        kernel_shutdown_prepare(SYSTEM_POWER_OFF);
        if (pm_power_off_prepare)
                pm_power_off_prepare();
-       disable_nonboot_cpus();
+       migrate_to_reboot_cpu();
        syscore_shutdown();
        printk(KERN_EMERG "Power down.\n");
        kmsg_dump(KMSG_DUMP_POWEROFF);
index bfd6787..7078052 100644 (file)
@@ -200,6 +200,7 @@ cond_syscall(sys_perf_event_open);
 /* fanotify! */
 cond_syscall(sys_fanotify_init);
 cond_syscall(sys_fanotify_mark);
+cond_syscall(compat_sys_fanotify_mark);
 
 /* open by handle */
 cond_syscall(sys_name_to_handle_at);
index ebf7235..aea4a9e 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/netdevice.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
+#include <linux/compat.h>
 
 #ifdef CONFIG_SYSCTL_SYSCALL
 
@@ -1447,7 +1448,6 @@ SYSCALL_DEFINE1(sysctl, struct __sysctl_args __user *, args)
 
 
 #ifdef CONFIG_COMPAT
-#include <asm/compat.h>
 
 struct compat_sysctl_args {
        compat_uptr_t   name;
@@ -1459,7 +1459,7 @@ struct compat_sysctl_args {
        compat_ulong_t  __unused[4];
 };
 
-asmlinkage long compat_sys_sysctl(struct compat_sysctl_args __user *args)
+COMPAT_SYSCALL_DEFINE1(sysctl, struct compat_sysctl_args __user *, args)
 {
        struct compat_sysctl_args tmp;
        compat_size_t __user *compat_oldlenp;
index e4c07b0..70f27e8 100644 (file)
@@ -12,11 +12,6 @@ config CLOCKSOURCE_WATCHDOG
 config ARCH_CLOCKSOURCE_DATA
        bool
 
-# Platforms has a persistent clock
-config ALWAYS_USE_PERSISTENT_CLOCK
-       bool
-       default n
-
 # Timekeeping vsyscall support
 config GENERIC_TIME_VSYSCALL
        bool
index 12ff13a..8f5b3b9 100644 (file)
@@ -874,7 +874,6 @@ static void hardpps_update_phase(long error)
 void __hardpps(const struct timespec *phase_ts, const struct timespec *raw_ts)
 {
        struct pps_normtime pts_norm, freq_norm;
-       unsigned long flags;
 
        pts_norm = pps_normalize_ts(*phase_ts);
 
index 206bbfb..0c73942 100644 (file)
@@ -511,6 +511,12 @@ again:
                }
        }
 
+       /*
+        * Remove the current cpu from the pending mask. The event is
+        * delivered immediately in tick_do_broadcast() !
+        */
+       cpumask_clear_cpu(smp_processor_id(), tick_broadcast_pending_mask);
+
        /* Take care of enforced broadcast requests */
        cpumask_or(tmpmask, tmpmask, tick_broadcast_force_mask);
        cpumask_clear(tick_broadcast_force_mask);
@@ -575,8 +581,8 @@ void tick_broadcast_oneshot_control(unsigned long reason)
 
        raw_spin_lock_irqsave(&tick_broadcast_lock, flags);
        if (reason == CLOCK_EVT_NOTIFY_BROADCAST_ENTER) {
-               WARN_ON_ONCE(cpumask_test_cpu(cpu, tick_broadcast_pending_mask));
                if (!cpumask_test_and_set_cpu(cpu, tick_broadcast_oneshot_mask)) {
+                       WARN_ON_ONCE(cpumask_test_cpu(cpu, tick_broadcast_pending_mask));
                        clockevents_set_mode(dev, CLOCK_EVT_MODE_SHUTDOWN);
                        /*
                         * We only reprogram the broadcast timer if we
@@ -786,11 +792,11 @@ bool tick_broadcast_oneshot_available(void)
 
 void __init tick_broadcast_init(void)
 {
-       alloc_cpumask_var(&tick_broadcast_mask, GFP_NOWAIT);
-       alloc_cpumask_var(&tmpmask, GFP_NOWAIT);
+       zalloc_cpumask_var(&tick_broadcast_mask, GFP_NOWAIT);
+       zalloc_cpumask_var(&tmpmask, GFP_NOWAIT);
 #ifdef CONFIG_TICK_ONESHOT
-       alloc_cpumask_var(&tick_broadcast_oneshot_mask, GFP_NOWAIT);
-       alloc_cpumask_var(&tick_broadcast_pending_mask, GFP_NOWAIT);
-       alloc_cpumask_var(&tick_broadcast_force_mask, GFP_NOWAIT);
+       zalloc_cpumask_var(&tick_broadcast_oneshot_mask, GFP_NOWAIT);
+       zalloc_cpumask_var(&tick_broadcast_pending_mask, GFP_NOWAIT);
+       zalloc_cpumask_var(&tick_broadcast_force_mask, GFP_NOWAIT);
 #endif
 }
index bc67d42..f420813 100644 (file)
@@ -717,6 +717,7 @@ static bool can_stop_idle_tick(int cpu, struct tick_sched *ts)
        if (unlikely(!cpu_online(cpu))) {
                if (cpu == tick_do_timer_cpu)
                        tick_do_timer_cpu = TICK_DO_TIMER_NONE;
+               return false;
        }
 
        if (unlikely(ts->nohz_mode == NOHZ_MODE_INACTIVE))
@@ -1168,7 +1169,7 @@ void tick_cancel_sched_timer(int cpu)
                hrtimer_cancel(&ts->sched_timer);
 # endif
 
-       ts->nohz_mode = NOHZ_MODE_INACTIVE;
+       memset(ts, 0, sizeof(*ts));
 }
 #endif
 
index 98cd470..baeeb5c 100644 (file)
@@ -975,6 +975,14 @@ static int timekeeping_suspend(void)
 
        read_persistent_clock(&timekeeping_suspend_time);
 
+       /*
+        * On some systems the persistent_clock can not be detected at
+        * timekeeping_init by its return value, so if we see a valid
+        * value returned, update the persistent_clock_exists flag.
+        */
+       if (timekeeping_suspend_time.tv_sec || timekeeping_suspend_time.tv_nsec)
+               persistent_clock_exist = true;
+
        raw_spin_lock_irqsave(&timekeeper_lock, flags);
        write_seqcount_begin(&timekeeper_seq);
        timekeeping_forward_now(tk);
index a860bba..15ffdb3 100644 (file)
@@ -1539,12 +1539,12 @@ static int __cpuinit init_timers_cpu(int cpu)
                        boot_done = 1;
                        base = &boot_tvec_bases;
                }
+               spin_lock_init(&base->lock);
                tvec_base_done[cpu] = 1;
        } else {
                base = per_cpu(tvec_bases, cpu);
        }
 
-       spin_lock_init(&base->lock);
 
        for (j = 0; j < TVN_SIZE; j++) {
                INIT_LIST_HEAD(base->tv5.vec + j);
index 5e9efd4..015f85a 100644 (file)
@@ -71,6 +71,7 @@ config TRACE_CLOCK
 config RING_BUFFER
        bool
        select TRACE_CLOCK
+       select IRQ_WORK
 
 config FTRACE_NMI_ENTER
        bool
@@ -107,7 +108,6 @@ config TRACING
        select BINARY_PRINTF
        select EVENT_TRACING
        select TRACE_CLOCK
-       select IRQ_WORK
 
 config GENERIC_TRACER
        bool
index 8a5c017..6c508ff 100644 (file)
 
 #define FL_GLOBAL_CONTROL_MASK (FTRACE_OPS_FL_GLOBAL | FTRACE_OPS_FL_CONTROL)
 
+#ifdef CONFIG_DYNAMIC_FTRACE
+#define INIT_REGEX_LOCK(opsname)       \
+       .regex_lock     = __MUTEX_INITIALIZER(opsname.regex_lock),
+#else
+#define INIT_REGEX_LOCK(opsname)
+#endif
+
 static struct ftrace_ops ftrace_list_end __read_mostly = {
        .func           = ftrace_stub,
        .flags          = FTRACE_OPS_FL_RECURSION_SAFE | FTRACE_OPS_FL_STUB,
@@ -113,24 +120,34 @@ static void ftrace_ops_no_ops(unsigned long ip, unsigned long parent_ip);
 
 /*
  * Traverse the ftrace_global_list, invoking all entries.  The reason that we
- * can use rcu_dereference_raw() is that elements removed from this list
+ * can use rcu_dereference_raw_notrace() is that elements removed from this list
  * are simply leaked, so there is no need to interact with a grace-period
- * mechanism.  The rcu_dereference_raw() calls are needed to handle
+ * mechanism.  The rcu_dereference_raw_notrace() calls are needed to handle
  * concurrent insertions into the ftrace_global_list.
  *
  * Silly Alpha and silly pointer-speculation compiler optimizations!
  */
 #define do_for_each_ftrace_op(op, list)                        \
-       op = rcu_dereference_raw(list);                 \
+       op = rcu_dereference_raw_notrace(list);                 \
        do
 
 /*
  * Optimized for just a single item in the list (as that is the normal case).
  */
 #define while_for_each_ftrace_op(op)                           \
-       while (likely(op = rcu_dereference_raw((op)->next)) &&  \
+       while (likely(op = rcu_dereference_raw_notrace((op)->next)) &&  \
               unlikely((op) != &ftrace_list_end))
 
+static inline void ftrace_ops_init(struct ftrace_ops *ops)
+{
+#ifdef CONFIG_DYNAMIC_FTRACE
+       if (!(ops->flags & FTRACE_OPS_FL_INITIALIZED)) {
+               mutex_init(&ops->regex_lock);
+               ops->flags |= FTRACE_OPS_FL_INITIALIZED;
+       }
+#endif
+}
+
 /**
  * ftrace_nr_registered_ops - return number of ops registered
  *
@@ -762,7 +779,7 @@ ftrace_find_profiled_func(struct ftrace_profile_stat *stat, unsigned long ip)
        if (hlist_empty(hhd))
                return NULL;
 
-       hlist_for_each_entry_rcu(rec, hhd, node) {
+       hlist_for_each_entry_rcu_notrace(rec, hhd, node) {
                if (rec->ip == ip)
                        return rec;
        }
@@ -907,7 +924,8 @@ static void unregister_ftrace_profiler(void)
 #else
 static struct ftrace_ops ftrace_profile_ops __read_mostly = {
        .func           = function_profile_call,
-       .flags          = FTRACE_OPS_FL_RECURSION_SAFE,
+       .flags          = FTRACE_OPS_FL_RECURSION_SAFE | FTRACE_OPS_FL_INITIALIZED,
+       INIT_REGEX_LOCK(ftrace_profile_ops)
 };
 
 static int register_ftrace_profiler(void)
@@ -1103,11 +1121,10 @@ static struct ftrace_ops global_ops = {
        .func                   = ftrace_stub,
        .notrace_hash           = EMPTY_HASH,
        .filter_hash            = EMPTY_HASH,
-       .flags                  = FTRACE_OPS_FL_RECURSION_SAFE,
+       .flags                  = FTRACE_OPS_FL_RECURSION_SAFE | FTRACE_OPS_FL_INITIALIZED,
+       INIT_REGEX_LOCK(global_ops)
 };
 
-static DEFINE_MUTEX(ftrace_regex_lock);
-
 struct ftrace_page {
        struct ftrace_page      *next;
        struct dyn_ftrace       *records;
@@ -1148,7 +1165,7 @@ ftrace_lookup_ip(struct ftrace_hash *hash, unsigned long ip)
 
        hhd = &hash->buckets[key];
 
-       hlist_for_each_entry_rcu(entry, hhd, hlist) {
+       hlist_for_each_entry_rcu_notrace(entry, hhd, hlist) {
                if (entry->ip == ip)
                        return entry;
        }
@@ -1247,6 +1264,7 @@ static void free_ftrace_hash_rcu(struct ftrace_hash *hash)
 
 void ftrace_free_filter(struct ftrace_ops *ops)
 {
+       ftrace_ops_init(ops);
        free_ftrace_hash(ops->filter_hash);
        free_ftrace_hash(ops->notrace_hash);
 }
@@ -1404,8 +1422,8 @@ ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip)
        struct ftrace_hash *notrace_hash;
        int ret;
 
-       filter_hash = rcu_dereference_raw(ops->filter_hash);
-       notrace_hash = rcu_dereference_raw(ops->notrace_hash);
+       filter_hash = rcu_dereference_raw_notrace(ops->filter_hash);
+       notrace_hash = rcu_dereference_raw_notrace(ops->notrace_hash);
 
        if ((ftrace_hash_empty(filter_hash) ||
             ftrace_lookup_ip(filter_hash, ip)) &&
@@ -2441,7 +2459,7 @@ t_next(struct seq_file *m, void *v, loff_t *pos)
                     !ftrace_lookup_ip(ops->notrace_hash, rec->ip)) ||
 
                    ((iter->flags & FTRACE_ITER_ENABLED) &&
-                    !(rec->flags & ~FTRACE_FL_MASK))) {
+                    !(rec->flags & FTRACE_FL_ENABLED))) {
 
                        rec = NULL;
                        goto retry;
@@ -2624,6 +2642,8 @@ ftrace_regex_open(struct ftrace_ops *ops, int flag,
        struct ftrace_hash *hash;
        int ret = 0;
 
+       ftrace_ops_init(ops);
+
        if (unlikely(ftrace_disabled))
                return -ENODEV;
 
@@ -2636,28 +2656,26 @@ ftrace_regex_open(struct ftrace_ops *ops, int flag,
                return -ENOMEM;
        }
 
+       iter->ops = ops;
+       iter->flags = flag;
+
+       mutex_lock(&ops->regex_lock);
+
        if (flag & FTRACE_ITER_NOTRACE)
                hash = ops->notrace_hash;
        else
                hash = ops->filter_hash;
 
-       iter->ops = ops;
-       iter->flags = flag;
-
        if (file->f_mode & FMODE_WRITE) {
-               mutex_lock(&ftrace_lock);
                iter->hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, hash);
-               mutex_unlock(&ftrace_lock);
-
                if (!iter->hash) {
                        trace_parser_put(&iter->parser);
                        kfree(iter);
-                       return -ENOMEM;
+                       ret = -ENOMEM;
+                       goto out_unlock;
                }
        }
 
-       mutex_lock(&ftrace_regex_lock);
-
        if ((file->f_mode & FMODE_WRITE) &&
            (file->f_flags & O_TRUNC))
                ftrace_filter_reset(iter->hash);
@@ -2677,7 +2695,9 @@ ftrace_regex_open(struct ftrace_ops *ops, int flag,
                }
        } else
                file->private_data = iter;
-       mutex_unlock(&ftrace_regex_lock);
+
+ out_unlock:
+       mutex_unlock(&ops->regex_lock);
 
        return ret;
 }
@@ -2900,7 +2920,7 @@ static void function_trace_probe_call(unsigned long ip, unsigned long parent_ip,
         * on the hash. rcu_read_lock is too dangerous here.
         */
        preempt_disable_notrace();
-       hlist_for_each_entry_rcu(entry, hhd, node) {
+       hlist_for_each_entry_rcu_notrace(entry, hhd, node) {
                if (entry->ip == ip)
                        entry->ops->func(ip, parent_ip, &entry->data);
        }
@@ -2910,6 +2930,8 @@ static void function_trace_probe_call(unsigned long ip, unsigned long parent_ip,
 static struct ftrace_ops trace_probe_ops __read_mostly =
 {
        .func           = function_trace_probe_call,
+       .flags          = FTRACE_OPS_FL_INITIALIZED,
+       INIT_REGEX_LOCK(trace_probe_ops)
 };
 
 static int ftrace_probe_registered;
@@ -2919,8 +2941,12 @@ static void __enable_ftrace_function_probe(void)
        int ret;
        int i;
 
-       if (ftrace_probe_registered)
+       if (ftrace_probe_registered) {
+               /* still need to update the function call sites */
+               if (ftrace_enabled)
+                       ftrace_run_update_code(FTRACE_UPDATE_CALLS);
                return;
+       }
 
        for (i = 0; i < FTRACE_FUNC_HASHSIZE; i++) {
                struct hlist_head *hhd = &ftrace_func_hash[i];
@@ -2990,19 +3016,21 @@ register_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
        if (WARN_ON(not))
                return -EINVAL;
 
-       mutex_lock(&ftrace_lock);
+       mutex_lock(&trace_probe_ops.regex_lock);
 
        hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, *orig_hash);
        if (!hash) {
                count = -ENOMEM;
-               goto out_unlock;
+               goto out;
        }
 
        if (unlikely(ftrace_disabled)) {
                count = -ENODEV;
-               goto out_unlock;
+               goto out;
        }
 
+       mutex_lock(&ftrace_lock);
+
        do_for_each_ftrace_rec(pg, rec) {
 
                if (!ftrace_match_record(rec, NULL, search, len, type))
@@ -3056,6 +3084,8 @@ register_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
 
  out_unlock:
        mutex_unlock(&ftrace_lock);
+ out:
+       mutex_unlock(&trace_probe_ops.regex_lock);
        free_ftrace_hash(hash);
 
        return count;
@@ -3095,7 +3125,7 @@ __unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
                        return;
        }
 
-       mutex_lock(&ftrace_lock);
+       mutex_lock(&trace_probe_ops.regex_lock);
 
        hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, *orig_hash);
        if (!hash)
@@ -3133,6 +3163,7 @@ __unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
                        list_add(&entry->free_list, &free_list);
                }
        }
+       mutex_lock(&ftrace_lock);
        __disable_ftrace_function_probe();
        /*
         * Remove after the disable is called. Otherwise, if the last
@@ -3144,9 +3175,10 @@ __unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
                list_del(&entry->free_list);
                ftrace_free_entry(entry);
        }
+       mutex_unlock(&ftrace_lock);
                
  out_unlock:
-       mutex_unlock(&ftrace_lock);
+       mutex_unlock(&trace_probe_ops.regex_lock);
        free_ftrace_hash(hash);
 }
 
@@ -3256,18 +3288,17 @@ ftrace_regex_write(struct file *file, const char __user *ubuf,
        if (!cnt)
                return 0;
 
-       mutex_lock(&ftrace_regex_lock);
-
-       ret = -ENODEV;
-       if (unlikely(ftrace_disabled))
-               goto out_unlock;
-
        if (file->f_mode & FMODE_READ) {
                struct seq_file *m = file->private_data;
                iter = m->private;
        } else
                iter = file->private_data;
 
+       if (unlikely(ftrace_disabled))
+               return -ENODEV;
+
+       /* iter->hash is a local copy, so we don't need regex_lock */
+
        parser = &iter->parser;
        read = trace_get_user(parser, ubuf, cnt, ppos);
 
@@ -3276,14 +3307,12 @@ ftrace_regex_write(struct file *file, const char __user *ubuf,
                ret = ftrace_process_regex(iter->hash, parser->buffer,
                                           parser->idx, enable);
                trace_parser_clear(parser);
-               if (ret)
-                       goto out_unlock;
+               if (ret < 0)
+                       goto out;
        }
 
        ret = read;
-out_unlock:
-       mutex_unlock(&ftrace_regex_lock);
-
+ out:
        return ret;
 }
 
@@ -3335,16 +3364,19 @@ ftrace_set_hash(struct ftrace_ops *ops, unsigned char *buf, int len,
        if (unlikely(ftrace_disabled))
                return -ENODEV;
 
+       mutex_lock(&ops->regex_lock);
+
        if (enable)
                orig_hash = &ops->filter_hash;
        else
                orig_hash = &ops->notrace_hash;
 
        hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, *orig_hash);
-       if (!hash)
-               return -ENOMEM;
+       if (!hash) {
+               ret = -ENOMEM;
+               goto out_regex_unlock;
+       }
 
-       mutex_lock(&ftrace_regex_lock);
        if (reset)
                ftrace_filter_reset(hash);
        if (buf && !ftrace_match_records(hash, buf, len)) {
@@ -3366,7 +3398,7 @@ ftrace_set_hash(struct ftrace_ops *ops, unsigned char *buf, int len,
        mutex_unlock(&ftrace_lock);
 
  out_regex_unlock:
-       mutex_unlock(&ftrace_regex_lock);
+       mutex_unlock(&ops->regex_lock);
 
        free_ftrace_hash(hash);
        return ret;
@@ -3392,6 +3424,7 @@ ftrace_set_addr(struct ftrace_ops *ops, unsigned long ip, int remove,
 int ftrace_set_filter_ip(struct ftrace_ops *ops, unsigned long ip,
                         int remove, int reset)
 {
+       ftrace_ops_init(ops);
        return ftrace_set_addr(ops, ip, remove, reset, 1);
 }
 EXPORT_SYMBOL_GPL(ftrace_set_filter_ip);
@@ -3416,6 +3449,7 @@ ftrace_set_regex(struct ftrace_ops *ops, unsigned char *buf, int len,
 int ftrace_set_filter(struct ftrace_ops *ops, unsigned char *buf,
                       int len, int reset)
 {
+       ftrace_ops_init(ops);
        return ftrace_set_regex(ops, buf, len, reset, 1);
 }
 EXPORT_SYMBOL_GPL(ftrace_set_filter);
@@ -3434,6 +3468,7 @@ EXPORT_SYMBOL_GPL(ftrace_set_filter);
 int ftrace_set_notrace(struct ftrace_ops *ops, unsigned char *buf,
                        int len, int reset)
 {
+       ftrace_ops_init(ops);
        return ftrace_set_regex(ops, buf, len, reset, 0);
 }
 EXPORT_SYMBOL_GPL(ftrace_set_notrace);
@@ -3524,6 +3559,8 @@ ftrace_set_early_filter(struct ftrace_ops *ops, char *buf, int enable)
 {
        char *func;
 
+       ftrace_ops_init(ops);
+
        while (buf) {
                func = strsep(&buf, ",");
                ftrace_set_regex(ops, func, strlen(func), 0, enable);
@@ -3551,10 +3588,8 @@ int ftrace_regex_release(struct inode *inode, struct file *file)
        int filter_hash;
        int ret;
 
-       mutex_lock(&ftrace_regex_lock);
        if (file->f_mode & FMODE_READ) {
                iter = m->private;
-
                seq_release(inode, file);
        } else
                iter = file->private_data;
@@ -3567,6 +3602,8 @@ int ftrace_regex_release(struct inode *inode, struct file *file)
 
        trace_parser_put(parser);
 
+       mutex_lock(&iter->ops->regex_lock);
+
        if (file->f_mode & FMODE_WRITE) {
                filter_hash = !!(iter->flags & FTRACE_ITER_FILTER);
 
@@ -3584,10 +3621,11 @@ int ftrace_regex_release(struct inode *inode, struct file *file)
 
                mutex_unlock(&ftrace_lock);
        }
+
+       mutex_unlock(&iter->ops->regex_lock);
        free_ftrace_hash(iter->hash);
        kfree(iter);
 
-       mutex_unlock(&ftrace_regex_lock);
        return 0;
 }
 
@@ -4126,7 +4164,8 @@ void __init ftrace_init(void)
 
 static struct ftrace_ops global_ops = {
        .func                   = ftrace_stub,
-       .flags                  = FTRACE_OPS_FL_RECURSION_SAFE,
+       .flags                  = FTRACE_OPS_FL_RECURSION_SAFE | FTRACE_OPS_FL_INITIALIZED,
+       INIT_REGEX_LOCK(global_ops)
 };
 
 static int __init ftrace_nodyn_init(void)
@@ -4180,8 +4219,9 @@ ftrace_ops_control_func(unsigned long ip, unsigned long parent_ip,
 }
 
 static struct ftrace_ops control_ops = {
-       .func = ftrace_ops_control_func,
-       .flags = FTRACE_OPS_FL_RECURSION_SAFE,
+       .func   = ftrace_ops_control_func,
+       .flags  = FTRACE_OPS_FL_RECURSION_SAFE | FTRACE_OPS_FL_INITIALIZED,
+       INIT_REGEX_LOCK(control_ops)
 };
 
 static inline void
@@ -4539,6 +4579,8 @@ int register_ftrace_function(struct ftrace_ops *ops)
 {
        int ret = -1;
 
+       ftrace_ops_init(ops);
+
        mutex_lock(&ftrace_lock);
 
        ret = __register_ftrace_function(ops);
index b59aea2..e444ff8 100644 (file)
@@ -620,6 +620,9 @@ int ring_buffer_poll_wait(struct ring_buffer *buffer, int cpu,
        if (cpu == RING_BUFFER_ALL_CPUS)
                work = &buffer->irq_work;
        else {
+               if (!cpumask_test_cpu(cpu, buffer->cpumask))
+                       return -EINVAL;
+
                cpu_buffer = buffer->buffers[cpu];
                work = &cpu_buffer->irq_work;
        }
index ae6fa2d..e71a8be 100644 (file)
@@ -652,8 +652,6 @@ static struct {
        ARCH_TRACE_CLOCKS
 };
 
-int trace_clock_id;
-
 /*
  * trace_parser_get_init - gets the buffer for trace parser
  */
@@ -843,7 +841,15 @@ __update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu)
 
        memcpy(max_data->comm, tsk->comm, TASK_COMM_LEN);
        max_data->pid = tsk->pid;
-       max_data->uid = task_uid(tsk);
+       /*
+        * If tsk == current, then use current_uid(), as that does not use
+        * RCU. The irq tracer can be called out of RCU scope.
+        */
+       if (tsk == current)
+               max_data->uid = current_uid();
+       else
+               max_data->uid = task_uid(tsk);
+
        max_data->nice = tsk->static_prio - 20 - MAX_RT_PRIO;
        max_data->policy = tsk->policy;
        max_data->rt_priority = tsk->rt_priority;
@@ -2818,7 +2824,7 @@ __tracing_open(struct inode *inode, struct file *file, bool snapshot)
                iter->iter_flags |= TRACE_FILE_ANNOTATE;
 
        /* Output in nanoseconds only if we are using a clock in nanoseconds. */
-       if (trace_clocks[trace_clock_id].in_ns)
+       if (trace_clocks[tr->clock_id].in_ns)
                iter->iter_flags |= TRACE_FILE_TIME_IN_NS;
 
        /* stop the trace while dumping if we are not opening "snapshot" */
@@ -3817,7 +3823,7 @@ static int tracing_open_pipe(struct inode *inode, struct file *filp)
                iter->iter_flags |= TRACE_FILE_LAT_FMT;
 
        /* Output in nanoseconds only if we are using a clock in nanoseconds. */
-       if (trace_clocks[trace_clock_id].in_ns)
+       if (trace_clocks[tr->clock_id].in_ns)
                iter->iter_flags |= TRACE_FILE_TIME_IN_NS;
 
        iter->cpu_file = tc->cpu;
@@ -5087,7 +5093,7 @@ tracing_stats_read(struct file *filp, char __user *ubuf,
        cnt = ring_buffer_bytes_cpu(trace_buf->buffer, cpu);
        trace_seq_printf(s, "bytes: %ld\n", cnt);
 
-       if (trace_clocks[trace_clock_id].in_ns) {
+       if (trace_clocks[tr->clock_id].in_ns) {
                /* local or global for trace_clock */
                t = ns2usecs(ring_buffer_oldest_event_ts(trace_buf->buffer, cpu));
                usec_rem = do_div(t, USEC_PER_SEC);
@@ -6216,10 +6222,15 @@ __init static int tracer_alloc_buffers(void)
 
        trace_init_cmdlines();
 
-       register_tracer(&nop_trace);
-
+       /*
+        * register_tracer() might reference current_trace, so it
+        * needs to be set before we register anything. This is
+        * just a bootstrap of current_trace anyway.
+        */
        global_trace.current_trace = &nop_trace;
 
+       register_tracer(&nop_trace);
+
        /* All seems OK, enable tracing */
        tracing_disabled = 0;
 
index 711ca7d..20572ed 100644 (file)
@@ -700,8 +700,6 @@ enum print_line_t print_trace_line(struct trace_iterator *iter);
 
 extern unsigned long trace_flags;
 
-extern int trace_clock_id;
-
 /* Standard output formatting function used for function return traces */
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 
index 53582e9..27963e2 100644 (file)
@@ -251,7 +251,8 @@ static int __ftrace_event_enable_disable(struct ftrace_event_file *file,
        switch (enable) {
        case 0:
                /*
-                * When soft_disable is set and enable is cleared, we want
+                * When soft_disable is set and enable is cleared, the sm_ref
+                * reference counter is decremented. If it reaches 0, we want
                 * to clear the SOFT_DISABLED flag but leave the event in the
                 * state that it was. That is, if the event was enabled and
                 * SOFT_DISABLED isn't set, then do nothing. But if SOFT_DISABLED
@@ -263,6 +264,8 @@ static int __ftrace_event_enable_disable(struct ftrace_event_file *file,
                 * "soft enable"s (clearing the SOFT_DISABLED bit) wont work.
                 */
                if (soft_disable) {
+                       if (atomic_dec_return(&file->sm_ref) > 0)
+                               break;
                        disable = file->flags & FTRACE_EVENT_FL_SOFT_DISABLED;
                        clear_bit(FTRACE_EVENT_FL_SOFT_MODE_BIT, &file->flags);
                } else
@@ -291,8 +294,11 @@ static int __ftrace_event_enable_disable(struct ftrace_event_file *file,
                 */
                if (!soft_disable)
                        clear_bit(FTRACE_EVENT_FL_SOFT_DISABLED_BIT, &file->flags);
-               else
+               else {
+                       if (atomic_inc_return(&file->sm_ref) > 1)
+                               break;
                        set_bit(FTRACE_EVENT_FL_SOFT_MODE_BIT, &file->flags);
+               }
 
                if (!(file->flags & FTRACE_EVENT_FL_ENABLED)) {
 
@@ -623,6 +629,8 @@ event_enable_read(struct file *filp, char __user *ubuf, size_t cnt,
        if (file->flags & FTRACE_EVENT_FL_ENABLED) {
                if (file->flags & FTRACE_EVENT_FL_SOFT_DISABLED)
                        buf = "0*\n";
+               else if (file->flags & FTRACE_EVENT_FL_SOFT_MODE)
+                       buf = "1*\n";
                else
                        buf = "1\n";
        } else
@@ -1521,6 +1529,24 @@ __register_event(struct ftrace_event_call *call, struct module *mod)
        return 0;
 }
 
+static struct ftrace_event_file *
+trace_create_new_event(struct ftrace_event_call *call,
+                      struct trace_array *tr)
+{
+       struct ftrace_event_file *file;
+
+       file = kmem_cache_alloc(file_cachep, GFP_TRACE);
+       if (!file)
+               return NULL;
+
+       file->event_call = call;
+       file->tr = tr;
+       atomic_set(&file->sm_ref, 0);
+       list_add(&file->list, &tr->events);
+
+       return file;
+}
+
 /* Add an event to a trace directory */
 static int
 __trace_add_new_event(struct ftrace_event_call *call,
@@ -1532,14 +1558,10 @@ __trace_add_new_event(struct ftrace_event_call *call,
 {
        struct ftrace_event_file *file;
 
-       file = kmem_cache_alloc(file_cachep, GFP_TRACE);
+       file = trace_create_new_event(call, tr);
        if (!file)
                return -ENOMEM;
 
-       file->event_call = call;
-       file->tr = tr;
-       list_add(&file->list, &tr->events);
-
        return event_create_dir(tr->event_dir, file, id, enable, filter, format);
 }
 
@@ -1554,14 +1576,10 @@ __trace_early_add_new_event(struct ftrace_event_call *call,
 {
        struct ftrace_event_file *file;
 
-       file = kmem_cache_alloc(file_cachep, GFP_TRACE);
+       file = trace_create_new_event(call, tr);
        if (!file)
                return -ENOMEM;
 
-       file->event_call = call;
-       file->tr = tr;
-       list_add(&file->list, &tr->events);
-
        return 0;
 }
 
@@ -2054,15 +2072,27 @@ event_enable_func(struct ftrace_hash *hash,
  out_reg:
        /* Don't let event modules unload while probe registered */
        ret = try_module_get(file->event_call->mod);
-       if (!ret)
+       if (!ret) {
+               ret = -EBUSY;
                goto out_free;
+       }
 
        ret = __ftrace_event_enable_disable(file, 1, 1);
        if (ret < 0)
                goto out_put;
        ret = register_ftrace_function_probe(glob, ops, data);
-       if (!ret)
+       /*
+        * The above returns on success the # of functions enabled,
+        * but if it didn't find any functions it returns zero.
+        * Consider no functions a failure too.
+        */
+       if (!ret) {
+               ret = -ENOENT;
+               goto out_disable;
+       } else if (ret < 0)
                goto out_disable;
+       /* Just return zero, not the number of enabled functions */
+       ret = 0;
  out:
        mutex_unlock(&event_mutex);
        return ret;
index a636117..e1b653f 100644 (file)
@@ -750,7 +750,11 @@ static int filter_set_pred(struct event_filter *filter,
 
 static void __free_preds(struct event_filter *filter)
 {
+       int i;
+
        if (filter->preds) {
+               for (i = 0; i < filter->n_preds; i++)
+                       kfree(filter->preds[i].ops);
                kfree(filter->preds);
                filter->preds = NULL;
        }
index 1865d5f..9f46e98 100644 (file)
@@ -27,7 +27,6 @@
 /**
  * Kprobe event core functions
  */
-
 struct trace_probe {
        struct list_head        list;
        struct kretprobe        rp;     /* Use rp.kp for kprobe use */
@@ -36,6 +35,7 @@ struct trace_probe {
        const char              *symbol;        /* symbol name */
        struct ftrace_event_class       class;
        struct ftrace_event_call        call;
+       struct ftrace_event_file * __rcu *files;
        ssize_t                 size;           /* trace entry size */
        unsigned int            nr_args;
        struct probe_arg        args[];
@@ -46,7 +46,7 @@ struct trace_probe {
        (sizeof(struct probe_arg) * (n)))
 
 
-static __kprobes int trace_probe_is_return(struct trace_probe *tp)
+static __kprobes bool trace_probe_is_return(struct trace_probe *tp)
 {
        return tp->rp.handler != NULL;
 }
@@ -183,12 +183,63 @@ static struct trace_probe *find_trace_probe(const char *event,
        return NULL;
 }
 
-/* Enable trace_probe - @flag must be TP_FLAG_TRACE or TP_FLAG_PROFILE */
-static int enable_trace_probe(struct trace_probe *tp, int flag)
+static int trace_probe_nr_files(struct trace_probe *tp)
+{
+       struct ftrace_event_file **file;
+       int ret = 0;
+
+       /*
+        * Since all tp->files updater is protected by probe_enable_lock,
+        * we don't need to lock an rcu_read_lock.
+        */
+       file = rcu_dereference_raw(tp->files);
+       if (file)
+               while (*(file++))
+                       ret++;
+
+       return ret;
+}
+
+static DEFINE_MUTEX(probe_enable_lock);
+
+/*
+ * Enable trace_probe
+ * if the file is NULL, enable "perf" handler, or enable "trace" handler.
+ */
+static int
+enable_trace_probe(struct trace_probe *tp, struct ftrace_event_file *file)
 {
        int ret = 0;
 
-       tp->flags |= flag;
+       mutex_lock(&probe_enable_lock);
+
+       if (file) {
+               struct ftrace_event_file **new, **old;
+               int n = trace_probe_nr_files(tp);
+
+               old = rcu_dereference_raw(tp->files);
+               /* 1 is for new one and 1 is for stopper */
+               new = kzalloc((n + 2) * sizeof(struct ftrace_event_file *),
+                             GFP_KERNEL);
+               if (!new) {
+                       ret = -ENOMEM;
+                       goto out_unlock;
+               }
+               memcpy(new, old, n * sizeof(struct ftrace_event_file *));
+               new[n] = file;
+               /* The last one keeps a NULL */
+
+               rcu_assign_pointer(tp->files, new);
+               tp->flags |= TP_FLAG_TRACE;
+
+               if (old) {
+                       /* Make sure the probe is done with old files */
+                       synchronize_sched();
+                       kfree(old);
+               }
+       } else
+               tp->flags |= TP_FLAG_PROFILE;
+
        if (trace_probe_is_enabled(tp) && trace_probe_is_registered(tp) &&
            !trace_probe_has_gone(tp)) {
                if (trace_probe_is_return(tp))
@@ -197,19 +248,90 @@ static int enable_trace_probe(struct trace_probe *tp, int flag)
                        ret = enable_kprobe(&tp->rp.kp);
        }
 
+ out_unlock:
+       mutex_unlock(&probe_enable_lock);
+
        return ret;
 }
 
-/* Disable trace_probe - @flag must be TP_FLAG_TRACE or TP_FLAG_PROFILE */
-static void disable_trace_probe(struct trace_probe *tp, int flag)
+static int
+trace_probe_file_index(struct trace_probe *tp, struct ftrace_event_file *file)
+{
+       struct ftrace_event_file **files;
+       int i;
+
+       /*
+        * Since all tp->files updater is protected by probe_enable_lock,
+        * we don't need to lock an rcu_read_lock.
+        */
+       files = rcu_dereference_raw(tp->files);
+       if (files) {
+               for (i = 0; files[i]; i++)
+                       if (files[i] == file)
+                               return i;
+       }
+
+       return -1;
+}
+
+/*
+ * Disable trace_probe
+ * if the file is NULL, disable "perf" handler, or disable "trace" handler.
+ */
+static int
+disable_trace_probe(struct trace_probe *tp, struct ftrace_event_file *file)
 {
-       tp->flags &= ~flag;
+       int ret = 0;
+
+       mutex_lock(&probe_enable_lock);
+
+       if (file) {
+               struct ftrace_event_file **new, **old;
+               int n = trace_probe_nr_files(tp);
+               int i, j;
+
+               old = rcu_dereference_raw(tp->files);
+               if (n == 0 || trace_probe_file_index(tp, file) < 0) {
+                       ret = -EINVAL;
+                       goto out_unlock;
+               }
+
+               if (n == 1) {   /* Remove the last file */
+                       tp->flags &= ~TP_FLAG_TRACE;
+                       new = NULL;
+               } else {
+                       new = kzalloc(n * sizeof(struct ftrace_event_file *),
+                                     GFP_KERNEL);
+                       if (!new) {
+                               ret = -ENOMEM;
+                               goto out_unlock;
+                       }
+
+                       /* This copy & check loop copies the NULL stopper too */
+                       for (i = 0, j = 0; j < n && i < n + 1; i++)
+                               if (old[i] != file)
+                                       new[j++] = old[i];
+               }
+
+               rcu_assign_pointer(tp->files, new);
+
+               /* Make sure the probe is done with old files */
+               synchronize_sched();
+               kfree(old);
+       } else
+               tp->flags &= ~TP_FLAG_PROFILE;
+
        if (!trace_probe_is_enabled(tp) && trace_probe_is_registered(tp)) {
                if (trace_probe_is_return(tp))
                        disable_kretprobe(&tp->rp);
                else
                        disable_kprobe(&tp->rp.kp);
        }
+
+ out_unlock:
+       mutex_unlock(&probe_enable_lock);
+
+       return ret;
 }
 
 /* Internal register function - just handle k*probes and flags */
@@ -723,9 +845,10 @@ static __kprobes void store_trace_args(int ent_size, struct trace_probe *tp,
 }
 
 /* Kprobe handler */
-static __kprobes void kprobe_trace_func(struct kprobe *kp, struct pt_regs *regs)
+static __kprobes void
+__kprobe_trace_func(struct trace_probe *tp, struct pt_regs *regs,
+                   struct ftrace_event_file *ftrace_file)
 {
-       struct trace_probe *tp = container_of(kp, struct trace_probe, rp.kp);
        struct kprobe_trace_entry_head *entry;
        struct ring_buffer_event *event;
        struct ring_buffer *buffer;
@@ -733,7 +856,10 @@ static __kprobes void kprobe_trace_func(struct kprobe *kp, struct pt_regs *regs)
        unsigned long irq_flags;
        struct ftrace_event_call *call = &tp->call;
 
-       tp->nhit++;
+       WARN_ON(call != ftrace_file->event_call);
+
+       if (test_bit(FTRACE_EVENT_FL_SOFT_DISABLED_BIT, &ftrace_file->flags))
+               return;
 
        local_save_flags(irq_flags);
        pc = preempt_count();
@@ -741,13 +867,14 @@ static __kprobes void kprobe_trace_func(struct kprobe *kp, struct pt_regs *regs)
        dsize = __get_data_size(tp, regs);
        size = sizeof(*entry) + tp->size + dsize;
 
-       event = trace_current_buffer_lock_reserve(&buffer, call->event.type,
-                                                 size, irq_flags, pc);
+       event = trace_event_buffer_lock_reserve(&buffer, ftrace_file,
+                                               call->event.type,
+                                               size, irq_flags, pc);
        if (!event)
                return;
 
        entry = ring_buffer_event_data(event);
-       entry->ip = (unsigned long)kp->addr;
+       entry->ip = (unsigned long)tp->rp.kp.addr;
        store_trace_args(sizeof(*entry), tp, regs, (u8 *)&entry[1], dsize);
 
        if (!filter_current_check_discard(buffer, call, entry, event))
@@ -755,11 +882,31 @@ static __kprobes void kprobe_trace_func(struct kprobe *kp, struct pt_regs *regs)
                                                irq_flags, pc, regs);
 }
 
+static __kprobes void
+kprobe_trace_func(struct trace_probe *tp, struct pt_regs *regs)
+{
+       /*
+        * Note: preempt is already disabled around the kprobe handler.
+        * However, we still need an smp_read_barrier_depends() corresponding
+        * to smp_wmb() in rcu_assign_pointer() to access the pointer.
+        */
+       struct ftrace_event_file **file = rcu_dereference_raw(tp->files);
+
+       if (unlikely(!file))
+               return;
+
+       while (*file) {
+               __kprobe_trace_func(tp, regs, *file);
+               file++;
+       }
+}
+
 /* Kretprobe handler */
-static __kprobes void kretprobe_trace_func(struct kretprobe_instance *ri,
-                                         struct pt_regs *regs)
+static __kprobes void
+__kretprobe_trace_func(struct trace_probe *tp, struct kretprobe_instance *ri,
+                      struct pt_regs *regs,
+                      struct ftrace_event_file *ftrace_file)
 {
-       struct trace_probe *tp = container_of(ri->rp, struct trace_probe, rp);
        struct kretprobe_trace_entry_head *entry;
        struct ring_buffer_event *event;
        struct ring_buffer *buffer;
@@ -767,14 +914,20 @@ static __kprobes void kretprobe_trace_func(struct kretprobe_instance *ri,
        unsigned long irq_flags;
        struct ftrace_event_call *call = &tp->call;
 
+       WARN_ON(call != ftrace_file->event_call);
+
+       if (test_bit(FTRACE_EVENT_FL_SOFT_DISABLED_BIT, &ftrace_file->flags))
+               return;
+
        local_save_flags(irq_flags);
        pc = preempt_count();
 
        dsize = __get_data_size(tp, regs);
        size = sizeof(*entry) + tp->size + dsize;
 
-       event = trace_current_buffer_lock_reserve(&buffer, call->event.type,
-                                                 size, irq_flags, pc);
+       event = trace_event_buffer_lock_reserve(&buffer, ftrace_file,
+                                               call->event.type,
+                                               size, irq_flags, pc);
        if (!event)
                return;
 
@@ -788,8 +941,28 @@ static __kprobes void kretprobe_trace_func(struct kretprobe_instance *ri,
                                                irq_flags, pc, regs);
 }
 
+static __kprobes void
+kretprobe_trace_func(struct trace_probe *tp, struct kretprobe_instance *ri,
+                    struct pt_regs *regs)
+{
+       /*
+        * Note: preempt is already disabled around the kprobe handler.
+        * However, we still need an smp_read_barrier_depends() corresponding
+        * to smp_wmb() in rcu_assign_pointer() to access the pointer.
+        */
+       struct ftrace_event_file **file = rcu_dereference_raw(tp->files);
+
+       if (unlikely(!file))
+               return;
+
+       while (*file) {
+               __kretprobe_trace_func(tp, ri, regs, *file);
+               file++;
+       }
+}
+
 /* Event entry printers */
-enum print_line_t
+static enum print_line_t
 print_kprobe_event(struct trace_iterator *iter, int flags,
                   struct trace_event *event)
 {
@@ -825,7 +998,7 @@ partial:
        return TRACE_TYPE_PARTIAL_LINE;
 }
 
-enum print_line_t
+static enum print_line_t
 print_kretprobe_event(struct trace_iterator *iter, int flags,
                      struct trace_event *event)
 {
@@ -975,10 +1148,9 @@ static int set_print_fmt(struct trace_probe *tp)
 #ifdef CONFIG_PERF_EVENTS
 
 /* Kprobe profile handler */
-static __kprobes void kprobe_perf_func(struct kprobe *kp,
-                                        struct pt_regs *regs)
+static __kprobes void
+kprobe_perf_func(struct trace_probe *tp, struct pt_regs *regs)
 {
-       struct trace_probe *tp = container_of(kp, struct trace_probe, rp.kp);
        struct ftrace_event_call *call = &tp->call;
        struct kprobe_trace_entry_head *entry;
        struct hlist_head *head;
@@ -997,7 +1169,7 @@ static __kprobes void kprobe_perf_func(struct kprobe *kp,
        if (!entry)
                return;
 
-       entry->ip = (unsigned long)kp->addr;
+       entry->ip = (unsigned long)tp->rp.kp.addr;
        memset(&entry[1], 0, dsize);
        store_trace_args(sizeof(*entry), tp, regs, (u8 *)&entry[1], dsize);
 
@@ -1007,10 +1179,10 @@ static __kprobes void kprobe_perf_func(struct kprobe *kp,
 }
 
 /* Kretprobe profile handler */
-static __kprobes void kretprobe_perf_func(struct kretprobe_instance *ri,
-                                           struct pt_regs *regs)
+static __kprobes void
+kretprobe_perf_func(struct trace_probe *tp, struct kretprobe_instance *ri,
+                   struct pt_regs *regs)
 {
-       struct trace_probe *tp = container_of(ri->rp, struct trace_probe, rp);
        struct ftrace_event_call *call = &tp->call;
        struct kretprobe_trace_entry_head *entry;
        struct hlist_head *head;
@@ -1044,20 +1216,19 @@ int kprobe_register(struct ftrace_event_call *event,
                    enum trace_reg type, void *data)
 {
        struct trace_probe *tp = (struct trace_probe *)event->data;
+       struct ftrace_event_file *file = data;
 
        switch (type) {
        case TRACE_REG_REGISTER:
-               return enable_trace_probe(tp, TP_FLAG_TRACE);
+               return enable_trace_probe(tp, file);
        case TRACE_REG_UNREGISTER:
-               disable_trace_probe(tp, TP_FLAG_TRACE);
-               return 0;
+               return disable_trace_probe(tp, file);
 
 #ifdef CONFIG_PERF_EVENTS
        case TRACE_REG_PERF_REGISTER:
-               return enable_trace_probe(tp, TP_FLAG_PROFILE);
+               return enable_trace_probe(tp, NULL);
        case TRACE_REG_PERF_UNREGISTER:
-               disable_trace_probe(tp, TP_FLAG_PROFILE);
-               return 0;
+               return disable_trace_probe(tp, NULL);
        case TRACE_REG_PERF_OPEN:
        case TRACE_REG_PERF_CLOSE:
        case TRACE_REG_PERF_ADD:
@@ -1073,11 +1244,13 @@ int kprobe_dispatcher(struct kprobe *kp, struct pt_regs *regs)
 {
        struct trace_probe *tp = container_of(kp, struct trace_probe, rp.kp);
 
+       tp->nhit++;
+
        if (tp->flags & TP_FLAG_TRACE)
-               kprobe_trace_func(kp, regs);
+               kprobe_trace_func(tp, regs);
 #ifdef CONFIG_PERF_EVENTS
        if (tp->flags & TP_FLAG_PROFILE)
-               kprobe_perf_func(kp, regs);
+               kprobe_perf_func(tp, regs);
 #endif
        return 0;       /* We don't tweek kernel, so just return 0 */
 }
@@ -1087,11 +1260,13 @@ int kretprobe_dispatcher(struct kretprobe_instance *ri, struct pt_regs *regs)
 {
        struct trace_probe *tp = container_of(ri->rp, struct trace_probe, rp);
 
+       tp->nhit++;
+
        if (tp->flags & TP_FLAG_TRACE)
-               kretprobe_trace_func(ri, regs);
+               kretprobe_trace_func(tp, ri, regs);
 #ifdef CONFIG_PERF_EVENTS
        if (tp->flags & TP_FLAG_PROFILE)
-               kretprobe_perf_func(ri, regs);
+               kretprobe_perf_func(tp, ri, regs);
 #endif
        return 0;       /* We don't tweek kernel, so just return 0 */
 }
@@ -1189,11 +1364,24 @@ static __used int kprobe_trace_selftest_target(int a1, int a2, int a3,
        return a1 + a2 + a3 + a4 + a5 + a6;
 }
 
+static struct ftrace_event_file *
+find_trace_probe_file(struct trace_probe *tp, struct trace_array *tr)
+{
+       struct ftrace_event_file *file;
+
+       list_for_each_entry(file, &tr->events, list)
+               if (file->event_call == &tp->call)
+                       return file;
+
+       return NULL;
+}
+
 static __init int kprobe_trace_self_tests_init(void)
 {
        int ret, warn = 0;
        int (*target)(int, int, int, int, int, int);
        struct trace_probe *tp;
+       struct ftrace_event_file *file;
 
        target = kprobe_trace_selftest_target;
 
@@ -1203,31 +1391,43 @@ static __init int kprobe_trace_self_tests_init(void)
                                  "$stack $stack0 +0($stack)",
                                  create_trace_probe);
        if (WARN_ON_ONCE(ret)) {
-               pr_warning("error on probing function entry.\n");
+               pr_warn("error on probing function entry.\n");
                warn++;
        } else {
                /* Enable trace point */
                tp = find_trace_probe("testprobe", KPROBE_EVENT_SYSTEM);
                if (WARN_ON_ONCE(tp == NULL)) {
-                       pr_warning("error on getting new probe.\n");
+                       pr_warn("error on getting new probe.\n");
                        warn++;
-               } else
-                       enable_trace_probe(tp, TP_FLAG_TRACE);
+               } else {
+                       file = find_trace_probe_file(tp, top_trace_array());
+                       if (WARN_ON_ONCE(file == NULL)) {
+                               pr_warn("error on getting probe file.\n");
+                               warn++;
+                       } else
+                               enable_trace_probe(tp, file);
+               }
        }
 
        ret = traceprobe_command("r:testprobe2 kprobe_trace_selftest_target "
                                  "$retval", create_trace_probe);
        if (WARN_ON_ONCE(ret)) {
-               pr_warning("error on probing function return.\n");
+               pr_warn("error on probing function return.\n");
                warn++;
        } else {
                /* Enable trace point */
                tp = find_trace_probe("testprobe2", KPROBE_EVENT_SYSTEM);
                if (WARN_ON_ONCE(tp == NULL)) {
-                       pr_warning("error on getting new probe.\n");
+                       pr_warn("error on getting 2nd new probe.\n");
                        warn++;
-               } else
-                       enable_trace_probe(tp, TP_FLAG_TRACE);
+               } else {
+                       file = find_trace_probe_file(tp, top_trace_array());
+                       if (WARN_ON_ONCE(file == NULL)) {
+                               pr_warn("error on getting probe file.\n");
+                               warn++;
+                       } else
+                               enable_trace_probe(tp, file);
+               }
        }
 
        if (warn)
@@ -1238,27 +1438,39 @@ static __init int kprobe_trace_self_tests_init(void)
        /* Disable trace points before removing it */
        tp = find_trace_probe("testprobe", KPROBE_EVENT_SYSTEM);
        if (WARN_ON_ONCE(tp == NULL)) {
-               pr_warning("error on getting test probe.\n");
+               pr_warn("error on getting test probe.\n");
                warn++;
-       } else
-               disable_trace_probe(tp, TP_FLAG_TRACE);
+       } else {
+               file = find_trace_probe_file(tp, top_trace_array());
+               if (WARN_ON_ONCE(file == NULL)) {
+                       pr_warn("error on getting probe file.\n");
+                       warn++;
+               } else
+                       disable_trace_probe(tp, file);
+       }
 
        tp = find_trace_probe("testprobe2", KPROBE_EVENT_SYSTEM);
        if (WARN_ON_ONCE(tp == NULL)) {
-               pr_warning("error on getting 2nd test probe.\n");
+               pr_warn("error on getting 2nd test probe.\n");
                warn++;
-       } else
-               disable_trace_probe(tp, TP_FLAG_TRACE);
+       } else {
+               file = find_trace_probe_file(tp, top_trace_array());
+               if (WARN_ON_ONCE(file == NULL)) {
+                       pr_warn("error on getting probe file.\n");
+                       warn++;
+               } else
+                       disable_trace_probe(tp, file);
+       }
 
        ret = traceprobe_command("-:testprobe", create_trace_probe);
        if (WARN_ON_ONCE(ret)) {
-               pr_warning("error on deleting a probe.\n");
+               pr_warn("error on deleting a probe.\n");
                warn++;
        }
 
        ret = traceprobe_command("-:testprobe2", create_trace_probe);
        if (WARN_ON_ONCE(ret)) {
-               pr_warning("error on deleting a probe.\n");
+               pr_warn("error on deleting a probe.\n");
                warn++;
        }
 
index 55e2cf6..2901e3b 100644 (file)
@@ -1159,7 +1159,7 @@ trace_selftest_startup_branch(struct tracer *trace, struct trace_array *tr)
        /* stop the tracing. */
        tracing_stop();
        /* check the trace buffer */
-       ret = trace_test_buffer(tr, &count);
+       ret = trace_test_buffer(&tr->trace_buffer, &count);
        trace->reset(tr);
        tracing_start();
 
index 4aa9f5b..ee8e29a 100644 (file)
@@ -296,7 +296,7 @@ static DEFINE_HASHTABLE(unbound_pool_hash, UNBOUND_POOL_HASH_ORDER);
 static struct workqueue_attrs *unbound_std_wq_attrs[NR_STD_WORKER_POOLS];
 
 struct workqueue_struct *system_wq __read_mostly;
-EXPORT_SYMBOL_GPL(system_wq);
+EXPORT_SYMBOL(system_wq);
 struct workqueue_struct *system_highpri_wq __read_mostly;
 EXPORT_SYMBOL_GPL(system_highpri_wq);
 struct workqueue_struct *system_long_wq __read_mostly;
@@ -1411,7 +1411,7 @@ bool queue_work_on(int cpu, struct workqueue_struct *wq,
        local_irq_restore(flags);
        return ret;
 }
-EXPORT_SYMBOL_GPL(queue_work_on);
+EXPORT_SYMBOL(queue_work_on);
 
 void delayed_work_timer_fn(unsigned long __data)
 {
@@ -1485,7 +1485,7 @@ bool queue_delayed_work_on(int cpu, struct workqueue_struct *wq,
        local_irq_restore(flags);
        return ret;
 }
-EXPORT_SYMBOL_GPL(queue_delayed_work_on);
+EXPORT_SYMBOL(queue_delayed_work_on);
 
 /**
  * mod_delayed_work_on - modify delay of or queue a delayed work on specific CPU
@@ -2059,6 +2059,7 @@ static bool manage_workers(struct worker *worker)
        if (unlikely(!mutex_trylock(&pool->manager_mutex))) {
                spin_unlock_irq(&pool->lock);
                mutex_lock(&pool->manager_mutex);
+               spin_lock_irq(&pool->lock);
                ret = true;
        }
 
@@ -4311,6 +4312,12 @@ bool current_is_workqueue_rescuer(void)
  * no synchronization around this function and the test result is
  * unreliable and only useful as advisory hints or for debugging.
  *
+ * If @cpu is WORK_CPU_UNBOUND, the test is performed on the local CPU.
+ * Note that both per-cpu and unbound workqueues may be associated with
+ * multiple pool_workqueues which have separate congested states.  A
+ * workqueue being congested on one CPU doesn't mean the workqueue is also
+ * contested on other CPUs / NUMA nodes.
+ *
  * RETURNS:
  * %true if congested, %false otherwise.
  */
@@ -4321,6 +4328,9 @@ bool workqueue_congested(int cpu, struct workqueue_struct *wq)
 
        rcu_read_lock_sched();
 
+       if (cpu == WORK_CPU_UNBOUND)
+               cpu = smp_processor_id();
+
        if (!(wq->flags & WQ_UNBOUND))
                pwq = per_cpu_ptr(wq->cpu_pwqs, cpu);
        else
@@ -4895,7 +4905,8 @@ static void __init wq_numa_init(void)
        BUG_ON(!tbl);
 
        for_each_node(node)
-               BUG_ON(!alloc_cpumask_var_node(&tbl[node], GFP_KERNEL, node));
+               BUG_ON(!alloc_cpumask_var_node(&tbl[node], GFP_KERNEL,
+                               node_online(node) ? node : NUMA_NO_NODE));
 
        for_each_possible_cpu(cpu) {
                node = cpu_to_node(cpu);
index e9c52e1..c55a037 100644 (file)
@@ -23,7 +23,7 @@ lib-y += kobject.o klist.o
 
 obj-y += bcd.o div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \
         bust_spinlocks.o hexdump.o kasprintf.o bitmap.o scatterlist.o \
-        gcd.o lcm.o list_sort.o uuid.o flex_array.o \
+        gcd.o lcm.o list_sort.o uuid.o flex_array.o iovec.o \
         bsearch.o find_last_bit.o find_next_bit.o llist.o memweight.o kfifo.o
 obj-y += string_helpers.o
 obj-$(CONFIG_TEST_STRING_HELPERS) += test-string_helpers.o
diff --git a/lib/iovec.c b/lib/iovec.c
new file mode 100644 (file)
index 0000000..454baa8
--- /dev/null
@@ -0,0 +1,53 @@
+#include <linux/uaccess.h>
+#include <linux/export.h>
+#include <linux/uio.h>
+
+/*
+ *     Copy iovec to kernel. Returns -EFAULT on error.
+ *
+ *     Note: this modifies the original iovec.
+ */
+
+int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len)
+{
+       while (len > 0) {
+               if (iov->iov_len) {
+                       int copy = min_t(unsigned int, len, iov->iov_len);
+                       if (copy_from_user(kdata, iov->iov_base, copy))
+                               return -EFAULT;
+                       len -= copy;
+                       kdata += copy;
+                       iov->iov_base += copy;
+                       iov->iov_len -= copy;
+               }
+               iov++;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(memcpy_fromiovec);
+
+/*
+ *     Copy kernel to iovec. Returns -EFAULT on error.
+ *
+ *     Note: this modifies the original iovec.
+ */
+
+int memcpy_toiovec(struct iovec *iov, unsigned char *kdata, int len)
+{
+       while (len > 0) {
+               if (iov->iov_len) {
+                       int copy = min_t(unsigned int, iov->iov_len, len);
+                       if (copy_to_user(iov->iov_base, kdata, copy))
+                               return -EFAULT;
+                       kdata += copy;
+                       len -= copy;
+                       iov->iov_len -= copy;
+                       iov->iov_base += copy;
+               }
+               iov++;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(memcpy_toiovec);
index 0874e41..358a368 100644 (file)
@@ -193,10 +193,10 @@ static void klist_release(struct kref *kref)
                if (waiter->node != n)
                        continue;
 
+               list_del(&waiter->list);
                waiter->woken = 1;
                mb();
                wake_up_process(waiter->process);
-               list_del(&waiter->list);
        }
        spin_unlock(&klist_remove_lock);
        knode_set_klist(n, NULL);
index 095ab15..d411355 100644 (file)
@@ -318,7 +318,8 @@ extern UDItype __udiv_qrnnd();
             "rM" ((USItype)(bh)), \
             "rM" ((USItype)(al)), \
             "rM" ((USItype)(bl)))
-#if defined(_PA_RISC1_1)
+#if 0 && defined(_PA_RISC1_1)
+/* xmpyu uses floating point register which is not allowed in Linux kernel. */
 #define umul_ppmm(wh, wl, u, v) \
 do { \
        union {UDItype __ll; \
@@ -337,7 +338,7 @@ do { \
 #define UMUL_TIME 40
 #define UDIV_TIME 80
 #endif
-#ifndef LONGLONG_STANDALONE
+#if 0 /* #ifndef LONGLONG_STANDALONE */
 #define udiv_qrnnd(q, r, n1, n0, d) \
 do { USItype __r; \
        (q) = __udiv_qrnnd(&__r, (n1), (n0), (d)); \
index 5f9c44c..4cc6442 100644 (file)
@@ -37,7 +37,7 @@ MPI mpi_read_raw_data(const void *xbuffer, size_t nbytes)
        mpi_limb_t a;
        MPI val = NULL;
 
-       while (nbytes >= 0 && buffer[0] == 0) {
+       while (nbytes > 0 && buffer[0] == 0) {
                buffer++;
                nbytes--;
        }
index 538367e..1b24bdc 100644 (file)
@@ -319,7 +319,7 @@ void __frontswap_invalidate_area(unsigned type)
                        return;
                frontswap_ops->invalidate_area(type);
                atomic_set(&sis->frontswap_pages, 0);
-               memset(sis->frontswap_map, 0, sis->max / sizeof(long));
+               bitmap_zero(sis->frontswap_map, sis->max);
        }
        clear_bit(type, need_init);
 }
index 03a89a2..362c329 100644 (file)
@@ -2325,7 +2325,12 @@ static void collapse_huge_page(struct mm_struct *mm,
                pte_unmap(pte);
                spin_lock(&mm->page_table_lock);
                BUG_ON(!pmd_none(*pmd));
-               set_pmd_at(mm, address, pmd, _pmd);
+               /*
+                * We can only use set_pmd_at when establishing
+                * hugepmds and never for establishing regular pmds that
+                * points to regular pagetables. Use pmd_populate for that
+                */
+               pmd_populate(mm, pmd, pmd_pgtable(_pmd));
                spin_unlock(&mm->page_table_lock);
                anon_vma_unlock_write(vma->anon_vma);
                goto out;
index f8feeec..e2bfbf7 100644 (file)
@@ -2839,7 +2839,7 @@ int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
        if (ptep) {
                entry = huge_ptep_get(ptep);
                if (unlikely(is_hugetlb_entry_migration(entry))) {
-                       migration_entry_wait(mm, (pmd_t *)ptep, address);
+                       migration_entry_wait_huge(mm, ptep);
                        return 0;
                } else if (unlikely(is_hugetlb_entry_hwpoisoned(entry)))
                        return VM_FAULT_HWPOISON_LARGE |
index cb1c9de..1947218 100644 (file)
@@ -1199,7 +1199,6 @@ struct mem_cgroup *mem_cgroup_iter(struct mem_cgroup *root,
 
                        mz = mem_cgroup_zoneinfo(root, nid, zid);
                        iter = &mz->reclaim_iter[reclaim->priority];
-                       last_visited = iter->last_visited;
                        if (prev && reclaim->generation != iter->generation) {
                                iter->last_visited = NULL;
                                goto out_unlock;
@@ -1218,13 +1217,12 @@ struct mem_cgroup *mem_cgroup_iter(struct mem_cgroup *root,
                         * is alive.
                         */
                        dead_count = atomic_read(&root->dead_count);
-                       smp_rmb();
-                       last_visited = iter->last_visited;
-                       if (last_visited) {
-                               if ((dead_count != iter->last_dead_count) ||
-                                       !css_tryget(&last_visited->css)) {
+                       if (dead_count == iter->last_dead_count) {
+                               smp_rmb();
+                               last_visited = iter->last_visited;
+                               if (last_visited &&
+                                   !css_tryget(&last_visited->css))
                                        last_visited = NULL;
-                               }
                        }
                }
 
@@ -3141,8 +3139,6 @@ int memcg_update_cache_size(struct kmem_cache *s, int num_groups)
                        return -ENOMEM;
                }
 
-               INIT_WORK(&s->memcg_params->destroy,
-                               kmem_cache_destroy_work_func);
                s->memcg_params->is_root_cache = true;
 
                /*
@@ -4108,8 +4104,6 @@ __mem_cgroup_uncharge_common(struct page *page, enum charge_type ctype,
        if (mem_cgroup_disabled())
                return NULL;
 
-       VM_BUG_ON(PageSwapCache(page));
-
        if (PageTransHuge(page)) {
                nr_pages <<= compound_order(page);
                VM_BUG_ON(!PageTransHuge(page));
@@ -4205,6 +4199,18 @@ void mem_cgroup_uncharge_page(struct page *page)
        if (page_mapped(page))
                return;
        VM_BUG_ON(page->mapping && !PageAnon(page));
+       /*
+        * If the page is in swap cache, uncharge should be deferred
+        * to the swap path, which also properly accounts swap usage
+        * and handles memcg lifetime.
+        *
+        * Note that this check is not stable and reclaim may add the
+        * page to swap cache at any time after this.  However, if the
+        * page is not in swap cache by the time page->mapcount hits
+        * 0, there won't be any page table references to the swap
+        * slot, and reclaim will free it and not actually write the
+        * page to disk.
+        */
        if (PageSwapCache(page))
                return;
        __mem_cgroup_uncharge_common(page, MEM_CGROUP_CHARGE_TYPE_ANON, false);
index 6dc1882..61a262b 100644 (file)
@@ -220,7 +220,6 @@ void tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, bool fullmm)
        tlb->start      = -1UL;
        tlb->end        = 0;
        tlb->need_flush = 0;
-       tlb->fast_mode  = (num_possible_cpus() == 1);
        tlb->local.next = NULL;
        tlb->local.nr   = 0;
        tlb->local.max  = ARRAY_SIZE(tlb->__pages);
@@ -244,9 +243,6 @@ void tlb_flush_mmu(struct mmu_gather *tlb)
        tlb_table_flush(tlb);
 #endif
 
-       if (tlb_fast_mode(tlb))
-               return;
-
        for (batch = &tlb->local; batch; batch = batch->next) {
                free_pages_and_swap_cache(batch->pages, batch->nr);
                batch->nr = 0;
@@ -288,11 +284,6 @@ int __tlb_remove_page(struct mmu_gather *tlb, struct page *page)
 
        VM_BUG_ON(!tlb->need_flush);
 
-       if (tlb_fast_mode(tlb)) {
-               free_page_and_swap_cache(page);
-               return 1; /* avoid calling tlb_flush_mmu() */
-       }
-
        batch = tlb->active;
        batch->pages[batch->nr++] = page;
        if (batch->nr == batch->max) {
index a221fac..1ad92b4 100644 (file)
@@ -720,9 +720,12 @@ int __remove_pages(struct zone *zone, unsigned long phys_start_pfn,
        start = phys_start_pfn << PAGE_SHIFT;
        size = nr_pages * PAGE_SIZE;
        ret = release_mem_region_adjustable(&iomem_resource, start, size);
-       if (ret)
-               pr_warn("Unable to release resource <%016llx-%016llx> (%d)\n",
-                               start, start + size - 1, ret);
+       if (ret) {
+               resource_size_t endres = start + size - 1;
+
+               pr_warn("Unable to release resource <%pa-%pa> (%d)\n",
+                               &start, &endres, ret);
+       }
 
        sections_to_remove = nr_pages / PAGES_PER_SECTION;
        for (i = 0; i < sections_to_remove; i++) {
index 27ed225..6f0c244 100644 (file)
@@ -165,7 +165,7 @@ static int remove_migration_pte(struct page *new, struct vm_area_struct *vma,
                pte = arch_make_huge_pte(pte, vma, new, 0);
        }
 #endif
-       flush_cache_page(vma, addr, pte_pfn(pte));
+       flush_dcache_page(new);
        set_pte_at(mm, addr, ptep, pte);
 
        if (PageHuge(new)) {
@@ -200,15 +200,14 @@ static void remove_migration_ptes(struct page *old, struct page *new)
  * get to the page and wait until migration is finished.
  * When we return from this function the fault will be retried.
  */
-void migration_entry_wait(struct mm_struct *mm, pmd_t *pmd,
-                               unsigned long address)
+static void __migration_entry_wait(struct mm_struct *mm, pte_t *ptep,
+                               spinlock_t *ptl)
 {
-       pte_t *ptep, pte;
-       spinlock_t *ptl;
+       pte_t pte;
        swp_entry_t entry;
        struct page *page;
 
-       ptep = pte_offset_map_lock(mm, pmd, address, &ptl);
+       spin_lock(ptl);
        pte = *ptep;
        if (!is_swap_pte(pte))
                goto out;
@@ -236,6 +235,20 @@ out:
        pte_unmap_unlock(ptep, ptl);
 }
 
+void migration_entry_wait(struct mm_struct *mm, pmd_t *pmd,
+                               unsigned long address)
+{
+       spinlock_t *ptl = pte_lockptr(mm, pmd);
+       pte_t *ptep = pte_offset_map(pmd, address);
+       __migration_entry_wait(mm, ptep, ptl);
+}
+
+void migration_entry_wait_huge(struct mm_struct *mm, pte_t *pte)
+{
+       spinlock_t *ptl = &(mm)->page_table_lock;
+       __migration_entry_wait(mm, pte, ptl);
+}
+
 #ifdef CONFIG_BLOCK
 /* Returns true if all buffers are successfully locked */
 static bool buffer_migrate_lock_buffers(struct buffer_head *head,
index be04122..6725ff1 100644 (file)
@@ -40,48 +40,44 @@ void __mmu_notifier_release(struct mm_struct *mm)
        int id;
 
        /*
-        * srcu_read_lock() here will block synchronize_srcu() in
-        * mmu_notifier_unregister() until all registered
-        * ->release() callouts this function makes have
-        * returned.
+        * SRCU here will block mmu_notifier_unregister until
+        * ->release returns.
         */
        id = srcu_read_lock(&srcu);
+       hlist_for_each_entry_rcu(mn, &mm->mmu_notifier_mm->list, hlist)
+               /*
+                * If ->release runs before mmu_notifier_unregister it must be
+                * handled, as it's the only way for the driver to flush all
+                * existing sptes and stop the driver from establishing any more
+                * sptes before all the pages in the mm are freed.
+                */
+               if (mn->ops->release)
+                       mn->ops->release(mn, mm);
+       srcu_read_unlock(&srcu, id);
+
        spin_lock(&mm->mmu_notifier_mm->lock);
        while (unlikely(!hlist_empty(&mm->mmu_notifier_mm->list))) {
                mn = hlist_entry(mm->mmu_notifier_mm->list.first,
                                 struct mmu_notifier,
                                 hlist);
-
                /*
-                * Unlink.  This will prevent mmu_notifier_unregister()
-                * from also making the ->release() callout.
+                * We arrived before mmu_notifier_unregister so
+                * mmu_notifier_unregister will do nothing other than to wait
+                * for ->release to finish and for mmu_notifier_unregister to
+                * return.
                 */
                hlist_del_init_rcu(&mn->hlist);
-               spin_unlock(&mm->mmu_notifier_mm->lock);
-
-               /*
-                * Clear sptes. (see 'release' description in mmu_notifier.h)
-                */
-               if (mn->ops->release)
-                       mn->ops->release(mn, mm);
-
-               spin_lock(&mm->mmu_notifier_mm->lock);
        }
        spin_unlock(&mm->mmu_notifier_mm->lock);
 
        /*
-        * All callouts to ->release() which we have done are complete.
-        * Allow synchronize_srcu() in mmu_notifier_unregister() to complete
-        */
-       srcu_read_unlock(&srcu, id);
-
-       /*
-        * mmu_notifier_unregister() may have unlinked a notifier and may
-        * still be calling out to it.  Additionally, other notifiers
-        * may have been active via vmtruncate() et. al. Block here
-        * to ensure that all notifier callouts for this mm have been
-        * completed and the sptes are really cleaned up before returning
-        * to exit_mmap().
+        * synchronize_srcu here prevents mmu_notifier_release from returning to
+        * exit_mmap (which would proceed with freeing all pages in the mm)
+        * until the ->release method returns, if it was invoked by
+        * mmu_notifier_unregister.
+        *
+        * The mmu_notifier_mm can't go away from under us because one mm_count
+        * is held by exit_mmap.
         */
        synchronize_srcu(&srcu);
 }
@@ -292,31 +288,34 @@ void mmu_notifier_unregister(struct mmu_notifier *mn, struct mm_struct *mm)
 {
        BUG_ON(atomic_read(&mm->mm_count) <= 0);
 
-       spin_lock(&mm->mmu_notifier_mm->lock);
        if (!hlist_unhashed(&mn->hlist)) {
+               /*
+                * SRCU here will force exit_mmap to wait for ->release to
+                * finish before freeing the pages.
+                */
                int id;
 
+               id = srcu_read_lock(&srcu);
                /*
-                * Ensure we synchronize up with __mmu_notifier_release().
+                * exit_mmap will block in mmu_notifier_release to guarantee
+                * that ->release is called before freeing the pages.
                 */
-               id = srcu_read_lock(&srcu);
-
-               hlist_del_rcu(&mn->hlist);
-               spin_unlock(&mm->mmu_notifier_mm->lock);
-
                if (mn->ops->release)
                        mn->ops->release(mn, mm);
+               srcu_read_unlock(&srcu, id);
 
+               spin_lock(&mm->mmu_notifier_mm->lock);
                /*
-                * Allow __mmu_notifier_release() to complete.
+                * Can not use list_del_rcu() since __mmu_notifier_release
+                * can delete it before we hold the lock.
                 */
-               srcu_read_unlock(&srcu, id);
-       } else
+               hlist_del_init_rcu(&mn->hlist);
                spin_unlock(&mm->mmu_notifier_mm->lock);
+       }
 
        /*
-        * Wait for any running method to finish, including ->release() if it
-        * was run by __mmu_notifier_release() instead of us.
+        * Wait for any running method to finish, of course including
+        * ->release if it was run by mmu_notifier_relase instead of us.
         */
        synchronize_srcu(&srcu);
 
index 98cbdf6..c3edb62 100644 (file)
@@ -1628,6 +1628,7 @@ static bool __zone_watermark_ok(struct zone *z, int order, unsigned long mark,
        long min = mark;
        long lowmem_reserve = z->lowmem_reserve[classzone_idx];
        int o;
+       long free_cma = 0;
 
        free_pages -= (1 << order) - 1;
        if (alloc_flags & ALLOC_HIGH)
@@ -1637,9 +1638,10 @@ static bool __zone_watermark_ok(struct zone *z, int order, unsigned long mark,
 #ifdef CONFIG_CMA
        /* If allocation can't use CMA areas don't use free CMA pages */
        if (!(alloc_flags & ALLOC_CMA))
-               free_pages -= zone_page_state(z, NR_FREE_CMA_PAGES);
+               free_cma = zone_page_state(z, NR_FREE_CMA_PAGES);
 #endif
-       if (free_pages <= min + lowmem_reserve)
+
+       if (free_pages - free_cma <= min + lowmem_reserve)
                return false;
        for (o = 0; o < order; o++) {
                /* At the next order, this order's pages become unavailable */
@@ -5158,7 +5160,7 @@ unsigned long free_reserved_area(unsigned long start, unsigned long end,
        for (pages = 0; pos < end; pos += PAGE_SIZE, pages++) {
                if (poison)
                        memset((void *)pos, poison, PAGE_SIZE);
-               free_reserved_page(virt_to_page(pos));
+               free_reserved_page(virt_to_page((void *)pos));
        }
 
        if (pages && s)
index 35aa294..5da2cbc 100644 (file)
@@ -127,28 +127,7 @@ static int walk_hugetlb_range(struct vm_area_struct *vma,
        return 0;
 }
 
-static struct vm_area_struct* hugetlb_vma(unsigned long addr, struct mm_walk *walk)
-{
-       struct vm_area_struct *vma;
-
-       /* We don't need vma lookup at all. */
-       if (!walk->hugetlb_entry)
-               return NULL;
-
-       VM_BUG_ON(!rwsem_is_locked(&walk->mm->mmap_sem));
-       vma = find_vma(walk->mm, addr);
-       if (vma && vma->vm_start <= addr && is_vm_hugetlb_page(vma))
-               return vma;
-
-       return NULL;
-}
-
 #else /* CONFIG_HUGETLB_PAGE */
-static struct vm_area_struct* hugetlb_vma(unsigned long addr, struct mm_walk *walk)
-{
-       return NULL;
-}
-
 static int walk_hugetlb_range(struct vm_area_struct *vma,
                              unsigned long addr, unsigned long end,
                              struct mm_walk *walk)
@@ -198,30 +177,53 @@ int walk_page_range(unsigned long addr, unsigned long end,
        if (!walk->mm)
                return -EINVAL;
 
+       VM_BUG_ON(!rwsem_is_locked(&walk->mm->mmap_sem));
+
        pgd = pgd_offset(walk->mm, addr);
        do {
-               struct vm_area_struct *vma;
+               struct vm_area_struct *vma = NULL;
 
                next = pgd_addr_end(addr, end);
 
                /*
-                * handle hugetlb vma individually because pagetable walk for
-                * the hugetlb page is dependent on the architecture and
-                * we can't handled it in the same manner as non-huge pages.
+                * This function was not intended to be vma based.
+                * But there are vma special cases to be handled:
+                * - hugetlb vma's
+                * - VM_PFNMAP vma's
                 */
-               vma = hugetlb_vma(addr, walk);
+               vma = find_vma(walk->mm, addr);
                if (vma) {
-                       if (vma->vm_end < next)
+                       /*
+                        * There are no page structures backing a VM_PFNMAP
+                        * range, so do not allow split_huge_page_pmd().
+                        */
+                       if ((vma->vm_start <= addr) &&
+                           (vma->vm_flags & VM_PFNMAP)) {
                                next = vma->vm_end;
+                               pgd = pgd_offset(walk->mm, next);
+                               continue;
+                       }
                        /*
-                        * Hugepage is very tightly coupled with vma, so
-                        * walk through hugetlb entries within a given vma.
+                        * Handle hugetlb vma individually because pagetable
+                        * walk for the hugetlb page is dependent on the
+                        * architecture and we can't handled it in the same
+                        * manner as non-huge pages.
                         */
-                       err = walk_hugetlb_range(vma, addr, next, walk);
-                       if (err)
-                               break;
-                       pgd = pgd_offset(walk->mm, next);
-                       continue;
+                       if (walk->hugetlb_entry && (vma->vm_start <= addr) &&
+                           is_vm_hugetlb_page(vma)) {
+                               if (vma->vm_end < next)
+                                       next = vma->vm_end;
+                               /*
+                                * Hugepage is very tightly coupled with vma,
+                                * so walk through hugetlb entries within a
+                                * given vma.
+                                */
+                               err = walk_hugetlb_range(vma, addr, next, walk);
+                               if (err)
+                                       break;
+                               pgd = pgd_offset(walk->mm, next);
+                               continue;
+                       }
                }
 
                if (pgd_none_or_clear_bad(pgd)) {
index b3d40dc..f24ab0d 100644 (file)
@@ -336,8 +336,24 @@ struct page *read_swap_cache_async(swp_entry_t entry, gfp_t gfp_mask,
                 * Swap entry may have been freed since our caller observed it.
                 */
                err = swapcache_prepare(entry);
-               if (err == -EEXIST) {   /* seems racy */
+               if (err == -EEXIST) {
                        radix_tree_preload_end();
+                       /*
+                        * We might race against get_swap_page() and stumble
+                        * across a SWAP_HAS_CACHE swap_map entry whose page
+                        * has not been brought into the swapcache yet, while
+                        * the other end is scheduled away waiting on discard
+                        * I/O completion at scan_swap_map().
+                        *
+                        * In order to avoid turning this transitory state
+                        * into a permanent loop around this -EEXIST case
+                        * if !CONFIG_PREEMPT and the I/O completion happens
+                        * to be waiting on the CPU waitqueue where we are now
+                        * busy looping, we just conditionally invoke the
+                        * scheduler here, if there are some more important
+                        * tasks to run.
+                        */
+                       cond_resched();
                        continue;
                }
                if (err) {              /* swp entry is obsolete ? */
index 6c340d9..746af55 100644 (file)
@@ -2116,7 +2116,7 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
        }
        /* frontswap enabled? set up bit-per-page map for frontswap */
        if (frontswap_enabled)
-               frontswap_map = vzalloc(maxpages / sizeof(long));
+               frontswap_map = vzalloc(BITS_TO_LONGS(maxpages) * sizeof(long));
 
        if (p->bdev) {
                if (blk_queue_nonrot(bdev_get_queue(p->bdev))) {
index e085bcc..1eb05d8 100644 (file)
@@ -871,10 +871,10 @@ void mrp_uninit_applicant(struct net_device *dev, struct mrp_application *appl)
         */
        del_timer_sync(&app->join_timer);
 
-       spin_lock(&app->lock);
+       spin_lock_bh(&app->lock);
        mrp_mad_event(app, MRP_EVENT_TX);
        mrp_pdu_queue(app);
-       spin_unlock(&app->lock);
+       spin_unlock_bh(&app->lock);
 
        mrp_queue_xmit(app);
 
index 8eb7542..addc116 100644 (file)
@@ -562,36 +562,19 @@ static int p9_check_zc_errors(struct p9_client *c, struct p9_req_t *req,
 
        if (!p9_is_proto_dotl(c)) {
                /* Error is reported in string format */
-               uint16_t len;
-               /* 7 = header size for RERROR, 2 is the size of string len; */
-               int inline_len = in_hdrlen - (7 + 2);
+               int len;
+               /* 7 = header size for RERROR; */
+               int inline_len = in_hdrlen - 7;
 
-               /* Read the size of error string */
-               err = p9pdu_readf(req->rc, c->proto_version, "w", &len);
-               if (err)
-                       goto out_err;
-
-               ename = kmalloc(len + 1, GFP_NOFS);
-               if (!ename) {
-                       err = -ENOMEM;
+               len =  req->rc->size - req->rc->offset;
+               if (len > (P9_ZC_HDR_SZ - 7)) {
+                       err = -EFAULT;
                        goto out_err;
                }
-               if (len <= inline_len) {
-                       /* We have error in protocol buffer itself */
-                       if (pdu_read(req->rc, ename, len)) {
-                               err = -EFAULT;
-                               goto out_free;
 
-                       }
-               } else {
-                       /*
-                        *  Part of the data is in user space buffer.
-                        */
-                       if (pdu_read(req->rc, ename, inline_len)) {
-                               err = -EFAULT;
-                               goto out_free;
-
-                       }
+               ename = &req->rc->sdata[req->rc->offset];
+               if (len > inline_len) {
+                       /* We have error in external buffer */
                        if (kern_buf) {
                                memcpy(ename + inline_len, uidata,
                                       len - inline_len);
@@ -600,19 +583,19 @@ static int p9_check_zc_errors(struct p9_client *c, struct p9_req_t *req,
                                                     uidata, len - inline_len);
                                if (err) {
                                        err = -EFAULT;
-                                       goto out_free;
+                                       goto out_err;
                                }
                        }
                }
-               ename[len] = 0;
-               if (p9_is_proto_dotu(c)) {
-                       /* For dotu we also have error code */
-                       err = p9pdu_readf(req->rc,
-                                         c->proto_version, "d", &ecode);
-                       if (err)
-                               goto out_free;
+               ename = NULL;
+               err = p9pdu_readf(req->rc, c->proto_version, "s?d",
+                                 &ename, &ecode);
+               if (err)
+                       goto out_err;
+
+               if (p9_is_proto_dotu(c))
                        err = -ecode;
-               }
+
                if (!err || !IS_ERR_VALUE(err)) {
                        err = p9_errstr2errno(ename, strlen(ename));
 
@@ -628,8 +611,6 @@ static int p9_check_zc_errors(struct p9_client *c, struct p9_req_t *req,
        }
        return err;
 
-out_free:
-       kfree(ename);
 out_err:
        p9_debug(P9_DEBUG_ERROR, "couldn't parse error%d\n", err);
        return err;
index 8e15d96..2399920 100644 (file)
@@ -837,6 +837,19 @@ bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
 
        dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_dst);
        if (dat_entry) {
+               /* If the ARP request is destined for a local client the local
+                * client will answer itself. DAT would only generate a
+                * duplicate packet.
+                *
+                * Moreover, if the soft-interface is enslaved into a bridge, an
+                * additional DAT answer may trigger kernel warnings about
+                * a packet coming from the wrong port.
+                */
+               if (batadv_is_my_client(bat_priv, dat_entry->mac_addr)) {
+                       ret = true;
+                       goto out;
+               }
+
                skb_new = arp_create(ARPOP_REPLY, ETH_P_ARP, ip_src,
                                     bat_priv->soft_iface, ip_dst, hw_src,
                                     dat_entry->mac_addr, hw_src);
index 3e30a0f..51aafd6 100644 (file)
@@ -163,16 +163,25 @@ void batadv_mesh_free(struct net_device *soft_iface)
        batadv_vis_quit(bat_priv);
 
        batadv_gw_node_purge(bat_priv);
-       batadv_originator_free(bat_priv);
        batadv_nc_free(bat_priv);
+       batadv_dat_free(bat_priv);
+       batadv_bla_free(bat_priv);
 
+       /* Free the TT and the originator tables only after having terminated
+        * all the other depending components which may use these structures for
+        * their purposes.
+        */
        batadv_tt_free(bat_priv);
 
-       batadv_bla_free(bat_priv);
-
-       batadv_dat_free(bat_priv);
+       /* Since the originator table clean up routine is accessing the TT
+        * tables as well, it has to be invoked after the TT tables have been
+        * freed and marked as empty. This ensures that no cleanup RCU callbacks
+        * accessing the TT data are scheduled for later execution.
+        */
+       batadv_originator_free(bat_priv);
 
        free_percpu(bat_priv->bat_counters);
+       bat_priv->bat_counters = NULL;
 
        atomic_set(&bat_priv->mesh_state, BATADV_MESH_INACTIVE);
 }
@@ -475,7 +484,7 @@ static int batadv_param_set_ra(const char *val, const struct kernel_param *kp)
        char *algo_name = (char *)val;
        size_t name_len = strlen(algo_name);
 
-       if (algo_name[name_len - 1] == '\n')
+       if (name_len > 0 && algo_name[name_len - 1] == '\n')
                algo_name[name_len - 1] = '\0';
 
        bat_algo_ops = batadv_algo_get(algo_name);
index f7c5430..e84629e 100644 (file)
@@ -1514,6 +1514,7 @@ batadv_nc_skb_decode_packet(struct batadv_priv *bat_priv, struct sk_buff *skb,
        struct ethhdr *ethhdr, ethhdr_tmp;
        uint8_t *orig_dest, ttl, ttvn;
        unsigned int coding_len;
+       int err;
 
        /* Save headers temporarily */
        memcpy(&coded_packet_tmp, skb->data, sizeof(coded_packet_tmp));
@@ -1568,8 +1569,11 @@ batadv_nc_skb_decode_packet(struct batadv_priv *bat_priv, struct sk_buff *skb,
                         coding_len);
 
        /* Resize decoded skb if decoded with larger packet */
-       if (nc_packet->skb->len > coding_len + h_size)
-               pskb_trim_rcsum(skb, coding_len + h_size);
+       if (nc_packet->skb->len > coding_len + h_size) {
+               err = pskb_trim_rcsum(skb, coding_len + h_size);
+               if (err)
+                       return NULL;
+       }
 
        /* Create decoded unicast packet */
        unicast_packet = (struct batadv_unicast_packet *)skb->data;
index 2f34525..fad1a20 100644 (file)
@@ -156,12 +156,28 @@ static void batadv_orig_node_free_rcu(struct rcu_head *rcu)
        kfree(orig_node);
 }
 
+/**
+ * batadv_orig_node_free_ref - decrement the orig node refcounter and possibly
+ * schedule an rcu callback for freeing it
+ * @orig_node: the orig node to free
+ */
 void batadv_orig_node_free_ref(struct batadv_orig_node *orig_node)
 {
        if (atomic_dec_and_test(&orig_node->refcount))
                call_rcu(&orig_node->rcu, batadv_orig_node_free_rcu);
 }
 
+/**
+ * batadv_orig_node_free_ref_now - decrement the orig node refcounter and
+ * possibly free it (without rcu callback)
+ * @orig_node: the orig node to free
+ */
+void batadv_orig_node_free_ref_now(struct batadv_orig_node *orig_node)
+{
+       if (atomic_dec_and_test(&orig_node->refcount))
+               batadv_orig_node_free_rcu(&orig_node->rcu);
+}
+
 void batadv_originator_free(struct batadv_priv *bat_priv)
 {
        struct batadv_hashtable *hash = bat_priv->orig_hash;
index 7df48fa..734e5a3 100644 (file)
@@ -26,6 +26,7 @@ int batadv_originator_init(struct batadv_priv *bat_priv);
 void batadv_originator_free(struct batadv_priv *bat_priv);
 void batadv_purge_orig_ref(struct batadv_priv *bat_priv);
 void batadv_orig_node_free_ref(struct batadv_orig_node *orig_node);
+void batadv_orig_node_free_ref_now(struct batadv_orig_node *orig_node);
 struct batadv_orig_node *batadv_get_orig_node(struct batadv_priv *bat_priv,
                                              const uint8_t *addr);
 struct batadv_neigh_node *
index 6f20d33..819dfb0 100644 (file)
@@ -505,6 +505,7 @@ unreg_debugfs:
        batadv_debugfs_del_meshif(dev);
 free_bat_counters:
        free_percpu(bat_priv->bat_counters);
+       bat_priv->bat_counters = NULL;
 
        return ret;
 }
index 5e89dee..9e87485 100644 (file)
@@ -144,7 +144,12 @@ static void batadv_tt_orig_list_entry_free_rcu(struct rcu_head *rcu)
        struct batadv_tt_orig_list_entry *orig_entry;
 
        orig_entry = container_of(rcu, struct batadv_tt_orig_list_entry, rcu);
-       batadv_orig_node_free_ref(orig_entry->orig_node);
+
+       /* We are in an rcu callback here, therefore we cannot use
+        * batadv_orig_node_free_ref() and its call_rcu():
+        * An rcu_barrier() wouldn't wait for that to finish
+        */
+       batadv_orig_node_free_ref_now(orig_entry->orig_node);
        kfree(orig_entry);
 }
 
index 33843c5..d817c93 100644 (file)
@@ -1555,11 +1555,15 @@ static const struct rfkill_ops hci_rfkill_ops = {
 static void hci_power_on(struct work_struct *work)
 {
        struct hci_dev *hdev = container_of(work, struct hci_dev, power_on);
+       int err;
 
        BT_DBG("%s", hdev->name);
 
-       if (hci_dev_open(hdev->id) < 0)
+       err = hci_dev_open(hdev->id);
+       if (err < 0) {
+               mgmt_set_powered_failed(hdev, err);
                return;
+       }
 
        if (test_bit(HCI_AUTO_OFF, &hdev->dev_flags))
                queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
index 940f5ac..46c6a14 100644 (file)
@@ -850,6 +850,29 @@ static void hidp_session_dev_del(struct hidp_session *session)
                input_unregister_device(session->input);
 }
 
+/*
+ * Asynchronous device registration
+ * HID device drivers might want to perform I/O during initialization to
+ * detect device types. Therefore, call device registration in a separate
+ * worker so the HIDP thread can schedule I/O operations.
+ * Note that this must be called after the worker thread was initialized
+ * successfully. This will then add the devices and increase session state
+ * on success, otherwise it will terminate the session thread.
+ */
+static void hidp_session_dev_work(struct work_struct *work)
+{
+       struct hidp_session *session = container_of(work,
+                                                   struct hidp_session,
+                                                   dev_init);
+       int ret;
+
+       ret = hidp_session_dev_add(session);
+       if (!ret)
+               atomic_inc(&session->state);
+       else
+               hidp_session_terminate(session);
+}
+
 /*
  * Create new session object
  * Allocate session object, initialize static fields, copy input data into the
@@ -897,6 +920,7 @@ static int hidp_session_new(struct hidp_session **out, const bdaddr_t *bdaddr,
        session->idle_to = req->idle_to;
 
        /* device management */
+       INIT_WORK(&session->dev_init, hidp_session_dev_work);
        setup_timer(&session->timer, hidp_idle_timeout,
                    (unsigned long)session);
 
@@ -1035,8 +1059,8 @@ static void hidp_session_terminate(struct hidp_session *session)
  * Probe HIDP session
  * This is called from the l2cap_conn core when our l2cap_user object is bound
  * to the hci-connection. We get the session via the \user object and can now
- * start the session thread, register the HID/input devices and link it into
- * the global session list.
+ * start the session thread, link it into the global session list and
+ * schedule HID/input device registration.
  * The global session-list owns its own reference to the session object so you
  * can drop your own reference after registering the l2cap_user object.
  */
@@ -1058,21 +1082,30 @@ static int hidp_session_probe(struct l2cap_conn *conn,
                goto out_unlock;
        }
 
+       if (session->input) {
+               ret = hidp_session_dev_add(session);
+               if (ret)
+                       goto out_unlock;
+       }
+
        ret = hidp_session_start_sync(session);
        if (ret)
-               goto out_unlock;
+               goto out_del;
 
-       ret = hidp_session_dev_add(session);
-       if (ret)
-               goto out_stop;
+       /* HID device registration is async to allow I/O during probe */
+       if (session->input)
+               atomic_inc(&session->state);
+       else
+               schedule_work(&session->dev_init);
 
        hidp_session_get(session);
        list_add(&session->list, &hidp_session_list);
        ret = 0;
        goto out_unlock;
 
-out_stop:
-       hidp_session_terminate(session);
+out_del:
+       if (session->input)
+               hidp_session_dev_del(session);
 out_unlock:
        up_write(&hidp_session_sem);
        return ret;
@@ -1102,7 +1135,12 @@ static void hidp_session_remove(struct l2cap_conn *conn,
        down_write(&hidp_session_sem);
 
        hidp_session_terminate(session);
-       hidp_session_dev_del(session);
+
+       cancel_work_sync(&session->dev_init);
+       if (session->input ||
+           atomic_read(&session->state) > HIDP_SESSION_PREPARING)
+               hidp_session_dev_del(session);
+
        list_del(&session->list);
 
        up_write(&hidp_session_sem);
index 6162ce8..9e6cc35 100644 (file)
@@ -128,6 +128,7 @@ int hidp_get_conninfo(struct hidp_conninfo *ci);
 
 enum hidp_session_state {
        HIDP_SESSION_IDLING,
+       HIDP_SESSION_PREPARING,
        HIDP_SESSION_RUNNING,
 };
 
@@ -156,6 +157,7 @@ struct hidp_session {
        unsigned long idle_to;
 
        /* device management */
+       struct work_struct dev_init;
        struct input_dev *input;
        struct hid_device *hid;
        struct timer_list timer;
index a76d1ac..24bee07 100644 (file)
@@ -3677,10 +3677,14 @@ static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
 }
 
 static inline int l2cap_command_rej(struct l2cap_conn *conn,
-                                   struct l2cap_cmd_hdr *cmd, u8 *data)
+                                   struct l2cap_cmd_hdr *cmd, u16 cmd_len,
+                                   u8 *data)
 {
        struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
 
+       if (cmd_len < sizeof(*rej))
+               return -EPROTO;
+
        if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
                return 0;
 
@@ -3829,11 +3833,14 @@ sendresp:
 }
 
 static int l2cap_connect_req(struct l2cap_conn *conn,
-                            struct l2cap_cmd_hdr *cmd, u8 *data)
+                            struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
 {
        struct hci_dev *hdev = conn->hcon->hdev;
        struct hci_conn *hcon = conn->hcon;
 
+       if (cmd_len < sizeof(struct l2cap_conn_req))
+               return -EPROTO;
+
        hci_dev_lock(hdev);
        if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
            !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &hcon->flags))
@@ -3847,7 +3854,8 @@ static int l2cap_connect_req(struct l2cap_conn *conn,
 }
 
 static int l2cap_connect_create_rsp(struct l2cap_conn *conn,
-                                   struct l2cap_cmd_hdr *cmd, u8 *data)
+                                   struct l2cap_cmd_hdr *cmd, u16 cmd_len,
+                                   u8 *data)
 {
        struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
        u16 scid, dcid, result, status;
@@ -3855,6 +3863,9 @@ static int l2cap_connect_create_rsp(struct l2cap_conn *conn,
        u8 req[128];
        int err;
 
+       if (cmd_len < sizeof(*rsp))
+               return -EPROTO;
+
        scid   = __le16_to_cpu(rsp->scid);
        dcid   = __le16_to_cpu(rsp->dcid);
        result = __le16_to_cpu(rsp->result);
@@ -3952,6 +3963,9 @@ static inline int l2cap_config_req(struct l2cap_conn *conn,
        struct l2cap_chan *chan;
        int len, err = 0;
 
+       if (cmd_len < sizeof(*req))
+               return -EPROTO;
+
        dcid  = __le16_to_cpu(req->dcid);
        flags = __le16_to_cpu(req->flags);
 
@@ -3975,7 +3989,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn,
 
        /* Reject if config buffer is too small. */
        len = cmd_len - sizeof(*req);
-       if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) {
+       if (chan->conf_len + len > sizeof(chan->conf_req)) {
                l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
                               l2cap_build_conf_rsp(chan, rsp,
                               L2CAP_CONF_REJECT, flags), rsp);
@@ -4053,14 +4067,18 @@ unlock:
 }
 
 static inline int l2cap_config_rsp(struct l2cap_conn *conn,
-                                  struct l2cap_cmd_hdr *cmd, u8 *data)
+                                  struct l2cap_cmd_hdr *cmd, u16 cmd_len,
+                                  u8 *data)
 {
        struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
        u16 scid, flags, result;
        struct l2cap_chan *chan;
-       int len = le16_to_cpu(cmd->len) - sizeof(*rsp);
+       int len = cmd_len - sizeof(*rsp);
        int err = 0;
 
+       if (cmd_len < sizeof(*rsp))
+               return -EPROTO;
+
        scid   = __le16_to_cpu(rsp->scid);
        flags  = __le16_to_cpu(rsp->flags);
        result = __le16_to_cpu(rsp->result);
@@ -4161,7 +4179,8 @@ done:
 }
 
 static inline int l2cap_disconnect_req(struct l2cap_conn *conn,
-                                      struct l2cap_cmd_hdr *cmd, u8 *data)
+                                      struct l2cap_cmd_hdr *cmd, u16 cmd_len,
+                                      u8 *data)
 {
        struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
        struct l2cap_disconn_rsp rsp;
@@ -4169,6 +4188,9 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn,
        struct l2cap_chan *chan;
        struct sock *sk;
 
+       if (cmd_len != sizeof(*req))
+               return -EPROTO;
+
        scid = __le16_to_cpu(req->scid);
        dcid = __le16_to_cpu(req->dcid);
 
@@ -4208,12 +4230,16 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn,
 }
 
 static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn,
-                                      struct l2cap_cmd_hdr *cmd, u8 *data)
+                                      struct l2cap_cmd_hdr *cmd, u16 cmd_len,
+                                      u8 *data)
 {
        struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
        u16 dcid, scid;
        struct l2cap_chan *chan;
 
+       if (cmd_len != sizeof(*rsp))
+               return -EPROTO;
+
        scid = __le16_to_cpu(rsp->scid);
        dcid = __le16_to_cpu(rsp->dcid);
 
@@ -4243,11 +4269,15 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn,
 }
 
 static inline int l2cap_information_req(struct l2cap_conn *conn,
-                                       struct l2cap_cmd_hdr *cmd, u8 *data)
+                                       struct l2cap_cmd_hdr *cmd, u16 cmd_len,
+                                       u8 *data)
 {
        struct l2cap_info_req *req = (struct l2cap_info_req *) data;
        u16 type;
 
+       if (cmd_len != sizeof(*req))
+               return -EPROTO;
+
        type = __le16_to_cpu(req->type);
 
        BT_DBG("type 0x%4.4x", type);
@@ -4294,11 +4324,15 @@ static inline int l2cap_information_req(struct l2cap_conn *conn,
 }
 
 static inline int l2cap_information_rsp(struct l2cap_conn *conn,
-                                       struct l2cap_cmd_hdr *cmd, u8 *data)
+                                       struct l2cap_cmd_hdr *cmd, u16 cmd_len,
+                                       u8 *data)
 {
        struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
        u16 type, result;
 
+       if (cmd_len != sizeof(*rsp))
+               return -EPROTO;
+
        type   = __le16_to_cpu(rsp->type);
        result = __le16_to_cpu(rsp->result);
 
@@ -5164,16 +5198,16 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
 
        switch (cmd->code) {
        case L2CAP_COMMAND_REJ:
-               l2cap_command_rej(conn, cmd, data);
+               l2cap_command_rej(conn, cmd, cmd_len, data);
                break;
 
        case L2CAP_CONN_REQ:
-               err = l2cap_connect_req(conn, cmd, data);
+               err = l2cap_connect_req(conn, cmd, cmd_len, data);
                break;
 
        case L2CAP_CONN_RSP:
        case L2CAP_CREATE_CHAN_RSP:
-               err = l2cap_connect_create_rsp(conn, cmd, data);
+               err = l2cap_connect_create_rsp(conn, cmd, cmd_len, data);
                break;
 
        case L2CAP_CONF_REQ:
@@ -5181,15 +5215,15 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
                break;
 
        case L2CAP_CONF_RSP:
-               err = l2cap_config_rsp(conn, cmd, data);
+               err = l2cap_config_rsp(conn, cmd, cmd_len, data);
                break;
 
        case L2CAP_DISCONN_REQ:
-               err = l2cap_disconnect_req(conn, cmd, data);
+               err = l2cap_disconnect_req(conn, cmd, cmd_len, data);
                break;
 
        case L2CAP_DISCONN_RSP:
-               err = l2cap_disconnect_rsp(conn, cmd, data);
+               err = l2cap_disconnect_rsp(conn, cmd, cmd_len, data);
                break;
 
        case L2CAP_ECHO_REQ:
@@ -5200,11 +5234,11 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
                break;
 
        case L2CAP_INFO_REQ:
-               err = l2cap_information_req(conn, cmd, data);
+               err = l2cap_information_req(conn, cmd, cmd_len, data);
                break;
 
        case L2CAP_INFO_RSP:
-               err = l2cap_information_rsp(conn, cmd, data);
+               err = l2cap_information_rsp(conn, cmd, cmd_len, data);
                break;
 
        case L2CAP_CREATE_CHAN_REQ:
index 35fef22..f8ecbc7 100644 (file)
@@ -2700,7 +2700,7 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
                break;
 
        case DISCOV_TYPE_LE:
-               if (!lmp_host_le_capable(hdev)) {
+               if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
                        err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
                                         MGMT_STATUS_NOT_SUPPORTED);
                        mgmt_pending_remove(cmd);
@@ -3418,6 +3418,27 @@ new_settings:
        return err;
 }
 
+int mgmt_set_powered_failed(struct hci_dev *hdev, int err)
+{
+       struct pending_cmd *cmd;
+       u8 status;
+
+       cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
+       if (!cmd)
+               return -ENOENT;
+
+       if (err == -ERFKILL)
+               status = MGMT_STATUS_RFKILLED;
+       else
+               status = MGMT_STATUS_FAILED;
+
+       err = cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
+
+       mgmt_pending_remove(cmd);
+
+       return err;
+}
+
 int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable)
 {
        struct cmd_lookup match = { NULL, hdev };
index b2296d3..b5562ab 100644 (file)
@@ -770,7 +770,7 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
 
        BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
 
-       if (!lmp_host_le_capable(hcon->hdev))
+       if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags))
                return 1;
 
        if (sec_level == BT_SECURITY_LOW)
@@ -851,7 +851,7 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
        __u8 reason;
        int err = 0;
 
-       if (!lmp_host_le_capable(conn->hcon->hdev)) {
+       if (!test_bit(HCI_LE_ENABLED, &conn->hcon->hdev->dev_flags)) {
                err = -ENOTSUPP;
                reason = SMP_PAIRING_NOTSUPP;
                goto done;
index 9878eb8..19c37a4 100644 (file)
@@ -72,13 +72,12 @@ print_ports(const struct sk_buff *skb, uint8_t protocol, int offset)
 }
 
 static void
-ebt_log_packet(u_int8_t pf, unsigned int hooknum,
-   const struct sk_buff *skb, const struct net_device *in,
-   const struct net_device *out, const struct nf_loginfo *loginfo,
-   const char *prefix)
+ebt_log_packet(struct net *net, u_int8_t pf, unsigned int hooknum,
+              const struct sk_buff *skb, const struct net_device *in,
+              const struct net_device *out, const struct nf_loginfo *loginfo,
+              const char *prefix)
 {
        unsigned int bitmask;
-       struct net *net = dev_net(in ? in : out);
 
        /* FIXME: Disabled from containers until syslog ns is supported */
        if (!net_eq(net, &init_net))
@@ -191,7 +190,7 @@ ebt_log_tg(struct sk_buff *skb, const struct xt_action_param *par)
                nf_log_packet(net, NFPROTO_BRIDGE, par->hooknum, skb,
                              par->in, par->out, &li, "%s", info->prefix);
        else
-               ebt_log_packet(NFPROTO_BRIDGE, par->hooknum, skb, par->in,
+               ebt_log_packet(net, NFPROTO_BRIDGE, par->hooknum, skb, par->in,
                               par->out, &li, info->prefix);
        return EBT_CONTINUE;
 }
index fc1905c..df0364a 100644 (file)
@@ -131,14 +131,16 @@ static struct sk_buff *ulog_alloc_skb(unsigned int size)
        return skb;
 }
 
-static void ebt_ulog_packet(unsigned int hooknr, const struct sk_buff *skb,
-   const struct net_device *in, const struct net_device *out,
-   const struct ebt_ulog_info *uloginfo, const char *prefix)
+static void ebt_ulog_packet(struct net *net, unsigned int hooknr,
+                           const struct sk_buff *skb,
+                           const struct net_device *in,
+                           const struct net_device *out,
+                           const struct ebt_ulog_info *uloginfo,
+                           const char *prefix)
 {
        ebt_ulog_packet_msg_t *pm;
        size_t size, copy_len;
        struct nlmsghdr *nlh;
-       struct net *net = dev_net(in ? in : out);
        struct ebt_ulog_net *ebt = ebt_ulog_pernet(net);
        unsigned int group = uloginfo->nlgroup;
        ebt_ulog_buff_t *ub = &ebt->ulog_buffers[group];
@@ -233,7 +235,7 @@ unlock:
 }
 
 /* this function is registered with the netfilter core */
-static void ebt_log_packet(u_int8_t pf, unsigned int hooknum,
+static void ebt_log_packet(struct net *net, u_int8_t pf, unsigned int hooknum,
    const struct sk_buff *skb, const struct net_device *in,
    const struct net_device *out, const struct nf_loginfo *li,
    const char *prefix)
@@ -252,13 +254,15 @@ static void ebt_log_packet(u_int8_t pf, unsigned int hooknum,
                strlcpy(loginfo.prefix, prefix, sizeof(loginfo.prefix));
        }
 
-       ebt_ulog_packet(hooknum, skb, in, out, &loginfo, prefix);
+       ebt_ulog_packet(net, hooknum, skb, in, out, &loginfo, prefix);
 }
 
 static unsigned int
 ebt_ulog_tg(struct sk_buff *skb, const struct xt_action_param *par)
 {
-       ebt_ulog_packet(par->hooknum, skb, par->in, par->out,
+       struct net *net = dev_net(par->in ? par->in : par->out);
+
+       ebt_ulog_packet(net, par->hooknum, skb, par->in, par->out,
                        par->targinfo, NULL);
        return EBT_CONTINUE;
 }
index a3395fd..3a246a6 100644 (file)
@@ -1204,6 +1204,7 @@ void ceph_osdc_unregister_linger_request(struct ceph_osd_client *osdc,
        mutex_lock(&osdc->request_mutex);
        if (req->r_linger) {
                __unregister_linger_request(osdc, req);
+               req->r_linger = 0;
                ceph_osdc_put_request(req);
        }
        mutex_unlock(&osdc->request_mutex);
@@ -1674,13 +1675,13 @@ static void kick_requests(struct ceph_osd_client *osdc, int force_resend)
                __register_request(osdc, req);
                __unregister_linger_request(osdc, req);
        }
+       reset_changed_osds(osdc);
        mutex_unlock(&osdc->request_mutex);
 
        if (needmap) {
                dout("%d requests for down osds, need new map\n", needmap);
                ceph_monc_request_next_osdmap(&osdc->client->monc);
        }
-       reset_changed_osds(osdc);
 }
 
 
@@ -2120,7 +2121,9 @@ int ceph_osdc_start_request(struct ceph_osd_client *osdc,
        down_read(&osdc->map_sem);
        mutex_lock(&osdc->request_mutex);
        __register_request(osdc, req);
-       WARN_ON(req->r_sent);
+       req->r_sent = 0;
+       req->r_got_reply = 0;
+       req->r_completed = 0;
        rc = __map_request(osdc, req, 0);
        if (rc < 0) {
                if (nofail) {
index 79ae884..f0a1ba6 100644 (file)
@@ -734,19 +734,25 @@ static unsigned char nas[21] = {
 
 asmlinkage long compat_sys_sendmsg(int fd, struct compat_msghdr __user *msg, unsigned int flags)
 {
-       return sys_sendmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT);
+       if (flags & MSG_CMSG_COMPAT)
+               return -EINVAL;
+       return __sys_sendmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT);
 }
 
 asmlinkage long compat_sys_sendmmsg(int fd, struct compat_mmsghdr __user *mmsg,
                                    unsigned int vlen, unsigned int flags)
 {
+       if (flags & MSG_CMSG_COMPAT)
+               return -EINVAL;
        return __sys_sendmmsg(fd, (struct mmsghdr __user *)mmsg, vlen,
                              flags | MSG_CMSG_COMPAT);
 }
 
 asmlinkage long compat_sys_recvmsg(int fd, struct compat_msghdr __user *msg, unsigned int flags)
 {
-       return sys_recvmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT);
+       if (flags & MSG_CMSG_COMPAT)
+               return -EINVAL;
+       return __sys_recvmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT);
 }
 
 asmlinkage long compat_sys_recv(int fd, void __user *buf, size_t len, unsigned int flags)
@@ -768,6 +774,9 @@ asmlinkage long compat_sys_recvmmsg(int fd, struct compat_mmsghdr __user *mmsg,
        int datagrams;
        struct timespec ktspec;
 
+       if (flags & MSG_CMSG_COMPAT)
+               return -EINVAL;
+
        if (COMPAT_USE_64BIT_TIME)
                return __sys_recvmmsg(fd, (struct mmsghdr __user *)mmsg, vlen,
                                      flags | MSG_CMSG_COMPAT,
index c013f38..6cda4e2 100644 (file)
@@ -39,6 +39,7 @@ static int __hw_addr_create_ex(struct netdev_hw_addr_list *list,
        ha->refcount = 1;
        ha->global_use = global;
        ha->synced = sync;
+       ha->sync_cnt = 0;
        list_add_tail_rcu(&ha->list, &list->list);
        list->count++;
 
@@ -66,7 +67,7 @@ static int __hw_addr_add_ex(struct netdev_hw_addr_list *list,
                        }
                        if (sync) {
                                if (ha->synced)
-                                       return 0;
+                                       return -EEXIST;
                                else
                                        ha->synced = true;
                        }
@@ -139,10 +140,13 @@ static int __hw_addr_sync_one(struct netdev_hw_addr_list *to_list,
 
        err = __hw_addr_add_ex(to_list, ha->addr, addr_len, ha->type,
                               false, true);
-       if (err)
+       if (err && err != -EEXIST)
                return err;
-       ha->sync_cnt++;
-       ha->refcount++;
+
+       if (!err) {
+               ha->sync_cnt++;
+               ha->refcount++;
+       }
 
        return 0;
 }
@@ -159,7 +163,8 @@ static void __hw_addr_unsync_one(struct netdev_hw_addr_list *to_list,
        if (err)
                return;
        ha->sync_cnt--;
-       __hw_addr_del_entry(from_list, ha, false, true);
+       /* address on from list is not marked synced */
+       __hw_addr_del_entry(from_list, ha, false, false);
 }
 
 static int __hw_addr_sync_multiple(struct netdev_hw_addr_list *to_list,
@@ -796,7 +801,7 @@ int dev_mc_sync_multiple(struct net_device *to, struct net_device *from)
                return -EINVAL;
 
        netif_addr_lock_nested(to);
-       err = __hw_addr_sync(&to->mc, &from->mc, to->addr_len);
+       err = __hw_addr_sync_multiple(&to->mc, &from->mc, to->addr_len);
        if (!err)
                __dev_set_rx_mode(to);
        netif_addr_unlock(to);
index dad2a17..6438f29 100644 (file)
@@ -778,7 +778,7 @@ int sk_detach_filter(struct sock *sk)
 }
 EXPORT_SYMBOL_GPL(sk_detach_filter);
 
-static void sk_decode_filter(struct sock_filter *filt, struct sock_filter *to)
+void sk_decode_filter(struct sock_filter *filt, struct sock_filter *to)
 {
        static const u16 decodes[] = {
                [BPF_S_ALU_ADD_K]       = BPF_ALU|BPF_ADD|BPF_K,
index 7e7aeb0..de178e4 100644 (file)
@@ -73,31 +73,6 @@ int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr_storage *a
        return err;
 }
 
-/*
- *     Copy kernel to iovec. Returns -EFAULT on error.
- *
- *     Note: this modifies the original iovec.
- */
-
-int memcpy_toiovec(struct iovec *iov, unsigned char *kdata, int len)
-{
-       while (len > 0) {
-               if (iov->iov_len) {
-                       int copy = min_t(unsigned int, iov->iov_len, len);
-                       if (copy_to_user(iov->iov_base, kdata, copy))
-                               return -EFAULT;
-                       kdata += copy;
-                       len -= copy;
-                       iov->iov_len -= copy;
-                       iov->iov_base += copy;
-               }
-               iov++;
-       }
-
-       return 0;
-}
-EXPORT_SYMBOL(memcpy_toiovec);
-
 /*
  *     Copy kernel to iovec. Returns -EFAULT on error.
  */
@@ -124,31 +99,6 @@ int memcpy_toiovecend(const struct iovec *iov, unsigned char *kdata,
 }
 EXPORT_SYMBOL(memcpy_toiovecend);
 
-/*
- *     Copy iovec to kernel. Returns -EFAULT on error.
- *
- *     Note: this modifies the original iovec.
- */
-
-int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len)
-{
-       while (len > 0) {
-               if (iov->iov_len) {
-                       int copy = min_t(unsigned int, len, iov->iov_len);
-                       if (copy_from_user(kdata, iov->iov_base, copy))
-                               return -EFAULT;
-                       len -= copy;
-                       kdata += copy;
-                       iov->iov_base += copy;
-                       iov->iov_len -= copy;
-               }
-               iov++;
-       }
-
-       return 0;
-}
-EXPORT_SYMBOL(memcpy_fromiovec);
-
 /*
  *     Copy iovec from kernel. Returns -EFAULT on error.
  */
index af9185d..cfd777b 100644 (file)
@@ -195,7 +195,7 @@ struct sk_buff *__alloc_skb_head(gfp_t gfp_mask, int node)
         * the tail pointer in struct sk_buff!
         */
        memset(skb, 0, offsetof(struct sk_buff, tail));
-       skb->data = NULL;
+       skb->head = NULL;
        skb->truesize = sizeof(struct sk_buff);
        atomic_set(&skb->users, 1);
 
@@ -611,7 +611,7 @@ static void skb_release_head_state(struct sk_buff *skb)
 static void skb_release_all(struct sk_buff *skb)
 {
        skb_release_head_state(skb);
-       if (likely(skb->data))
+       if (likely(skb->head))
                skb_release_data(skb);
 }
 
index d4f4cea..88868a9 100644 (file)
@@ -210,7 +210,7 @@ static const char *const af_family_key_strings[AF_MAX+1] = {
   "sk_lock-AF_TIPC"  , "sk_lock-AF_BLUETOOTH", "sk_lock-IUCV"        ,
   "sk_lock-AF_RXRPC" , "sk_lock-AF_ISDN"     , "sk_lock-AF_PHONET"   ,
   "sk_lock-AF_IEEE802154", "sk_lock-AF_CAIF" , "sk_lock-AF_ALG"      ,
-  "sk_lock-AF_NFC"   , "sk_lock-AF_MAX"
+  "sk_lock-AF_NFC"   , "sk_lock-AF_VSOCK"    , "sk_lock-AF_MAX"
 };
 static const char *const af_family_slock_key_strings[AF_MAX+1] = {
   "slock-AF_UNSPEC", "slock-AF_UNIX"     , "slock-AF_INET"     ,
@@ -226,7 +226,7 @@ static const char *const af_family_slock_key_strings[AF_MAX+1] = {
   "slock-AF_TIPC"  , "slock-AF_BLUETOOTH", "slock-AF_IUCV"     ,
   "slock-AF_RXRPC" , "slock-AF_ISDN"     , "slock-AF_PHONET"   ,
   "slock-AF_IEEE802154", "slock-AF_CAIF" , "slock-AF_ALG"      ,
-  "slock-AF_NFC"   , "slock-AF_MAX"
+  "slock-AF_NFC"   , "slock-AF_VSOCK"    ,"slock-AF_MAX"
 };
 static const char *const af_family_clock_key_strings[AF_MAX+1] = {
   "clock-AF_UNSPEC", "clock-AF_UNIX"     , "clock-AF_INET"     ,
@@ -242,7 +242,7 @@ static const char *const af_family_clock_key_strings[AF_MAX+1] = {
   "clock-AF_TIPC"  , "clock-AF_BLUETOOTH", "clock-AF_IUCV"     ,
   "clock-AF_RXRPC" , "clock-AF_ISDN"     , "clock-AF_PHONET"   ,
   "clock-AF_IEEE802154", "clock-AF_CAIF" , "clock-AF_ALG"      ,
-  "clock-AF_NFC"   , "clock-AF_MAX"
+  "clock-AF_NFC"   , "clock-AF_VSOCK"    , "clock-AF_MAX"
 };
 
 /*
@@ -1217,18 +1217,6 @@ static void sock_copy(struct sock *nsk, const struct sock *osk)
 #endif
 }
 
-/*
- * caches using SLAB_DESTROY_BY_RCU should let .next pointer from nulls nodes
- * un-modified. Special care is taken when initializing object to zero.
- */
-static inline void sk_prot_clear_nulls(struct sock *sk, int size)
-{
-       if (offsetof(struct sock, sk_node.next) != 0)
-               memset(sk, 0, offsetof(struct sock, sk_node.next));
-       memset(&sk->sk_node.pprev, 0,
-              size - offsetof(struct sock, sk_node.pprev));
-}
-
 void sk_prot_clear_portaddr_nulls(struct sock *sk, int size)
 {
        unsigned long nulls1, nulls2;
index d5bef0b..a0e9cf6 100644 (file)
@@ -73,8 +73,13 @@ int sock_diag_put_filterinfo(struct user_namespace *user_ns, struct sock *sk,
                goto out;
        }
 
-       if (filter)
-               memcpy(nla_data(attr), filter->insns, len);
+       if (filter) {
+               struct sock_filter *fb = (struct sock_filter *)nla_data(attr);
+               int i;
+
+               for (i = 0; i < filter->len; i++, fb++)
+                       sk_decode_filter(&filter->insns[i], fb);
+       }
 
 out:
        rcu_read_unlock();
index c625e4d..2a83591 100644 (file)
@@ -235,7 +235,7 @@ static void ipgre_err(struct sk_buff *skb, u32 info)
           */
        struct net *net = dev_net(skb->dev);
        struct ip_tunnel_net *itn;
-       const struct iphdr *iph = (const struct iphdr *)skb->data;
+       const struct iphdr *iph;
        const int type = icmp_hdr(skb)->type;
        const int code = icmp_hdr(skb)->code;
        struct ip_tunnel *t;
@@ -281,6 +281,7 @@ static void ipgre_err(struct sk_buff *skb, u32 info)
        else
                itn = net_generic(net, ipgre_net_id);
 
+       iph = (const struct iphdr *)skb->data;
        t = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi.flags,
                             iph->daddr, iph->saddr, tpi.key);
 
index 147abf5..4bcabf3 100644 (file)
@@ -84,7 +84,7 @@ int sysctl_ip_default_ttl __read_mostly = IPDEFTTL;
 EXPORT_SYMBOL(sysctl_ip_default_ttl);
 
 /* Generate a checksum for an outgoing IP datagram. */
-__inline__ void ip_send_check(struct iphdr *iph)
+void ip_send_check(struct iphdr *iph)
 {
        iph->check = 0;
        iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
index e4147ec..be2f8da 100644 (file)
@@ -503,6 +503,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
 
        inner_iph = (const struct iphdr *)skb_inner_network_header(skb);
 
+       memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
        dst = tnl_params->daddr;
        if (dst == 0) {
                /* NBMA tunnel */
@@ -658,7 +659,6 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
 
        skb_dst_drop(skb);
        skb_dst_set(skb, &rt->dst);
-       memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
 
        /* Push down and install the IP header. */
        skb_push(skb, sizeof(struct iphdr));
index f8a222c..ff4b781 100644 (file)
@@ -162,7 +162,8 @@ static struct sk_buff *ulog_alloc_skb(unsigned int size)
        return skb;
 }
 
-static void ipt_ulog_packet(unsigned int hooknum,
+static void ipt_ulog_packet(struct net *net,
+                           unsigned int hooknum,
                            const struct sk_buff *skb,
                            const struct net_device *in,
                            const struct net_device *out,
@@ -174,7 +175,6 @@ static void ipt_ulog_packet(unsigned int hooknum,
        size_t size, copy_len;
        struct nlmsghdr *nlh;
        struct timeval tv;
-       struct net *net = dev_net(in ? in : out);
        struct ulog_net *ulog = ulog_pernet(net);
 
        /* ffs == find first bit set, necessary because userspace
@@ -231,8 +231,10 @@ static void ipt_ulog_packet(unsigned int hooknum,
        put_unaligned(tv.tv_usec, &pm->timestamp_usec);
        put_unaligned(skb->mark, &pm->mark);
        pm->hook = hooknum;
-       if (prefix != NULL)
-               strncpy(pm->prefix, prefix, sizeof(pm->prefix));
+       if (prefix != NULL) {
+               strncpy(pm->prefix, prefix, sizeof(pm->prefix) - 1);
+               pm->prefix[sizeof(pm->prefix) - 1] = '\0';
+       }
        else if (loginfo->prefix[0] != '\0')
                strncpy(pm->prefix, loginfo->prefix, sizeof(pm->prefix));
        else
@@ -291,12 +293,15 @@ alloc_failure:
 static unsigned int
 ulog_tg(struct sk_buff *skb, const struct xt_action_param *par)
 {
-       ipt_ulog_packet(par->hooknum, skb, par->in, par->out,
+       struct net *net = dev_net(par->in ? par->in : par->out);
+
+       ipt_ulog_packet(net, par->hooknum, skb, par->in, par->out,
                        par->targinfo, NULL);
        return XT_CONTINUE;
 }
 
-static void ipt_logfn(u_int8_t pf,
+static void ipt_logfn(struct net *net,
+                     u_int8_t pf,
                      unsigned int hooknum,
                      const struct sk_buff *skb,
                      const struct net_device *in,
@@ -318,7 +323,7 @@ static void ipt_logfn(u_int8_t pf,
                strlcpy(loginfo.prefix, prefix, sizeof(loginfo.prefix));
        }
 
-       ipt_ulog_packet(hooknum, skb, in, out, &loginfo, prefix);
+       ipt_ulog_packet(net, hooknum, skb, in, out, &loginfo, prefix);
 }
 
 static int ulog_tg_check(const struct xt_tgchk_param *par)
index 550781a..d35bbf0 100644 (file)
@@ -737,10 +737,15 @@ static void ip_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_buf
 {
        struct rtable *rt;
        struct flowi4 fl4;
+       const struct iphdr *iph = (const struct iphdr *) skb->data;
+       int oif = skb->dev->ifindex;
+       u8 tos = RT_TOS(iph->tos);
+       u8 prot = iph->protocol;
+       u32 mark = skb->mark;
 
        rt = (struct rtable *) dst;
 
-       ip_rt_build_flow_key(&fl4, sk, skb);
+       __build_flow_key(&fl4, sk, iph, oif, tos, prot, mark, 0);
        __ip_do_redirect(rt, skb, &fl4, true);
 }
 
index dcb116d..ab450c0 100644 (file)
@@ -2887,6 +2887,7 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb,
        unsigned int mss;
        struct sk_buff *gso_skb = skb;
        __sum16 newcheck;
+       bool ooo_okay, copy_destructor;
 
        if (!pskb_may_pull(skb, sizeof(*th)))
                goto out;
@@ -2927,10 +2928,18 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb,
                goto out;
        }
 
+       copy_destructor = gso_skb->destructor == tcp_wfree;
+       ooo_okay = gso_skb->ooo_okay;
+       /* All segments but the first should have ooo_okay cleared */
+       skb->ooo_okay = 0;
+
        segs = skb_segment(skb, features);
        if (IS_ERR(segs))
                goto out;
 
+       /* Only first segment might have ooo_okay set */
+       segs->ooo_okay = ooo_okay;
+
        delta = htonl(oldlen + (thlen + mss));
 
        skb = segs;
@@ -2950,6 +2959,17 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb,
                                                    thlen, skb->csum));
 
                seq += mss;
+               if (copy_destructor) {
+                       skb->destructor = gso_skb->destructor;
+                       skb->sk = gso_skb->sk;
+                       /* {tcp|sock}_wfree() use exact truesize accounting :
+                        * sum(skb->truesize) MUST be exactly be gso_skb->truesize
+                        * So we account mss bytes of 'true size' for each segment.
+                        * The last segment will contain the remaining.
+                        */
+                       skb->truesize = mss;
+                       gso_skb->truesize -= mss;
+               }
                skb = skb->next;
                th = tcp_hdr(skb);
 
@@ -2962,7 +2982,7 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb,
         * is freed at TX completion, and not right now when gso_skb
         * is freed by GSO engine
         */
-       if (gso_skb->destructor == tcp_wfree) {
+       if (copy_destructor) {
                swap(gso_skb->sk, skb->sk);
                swap(gso_skb->destructor, skb->destructor);
                swap(gso_skb->truesize, skb->truesize);
@@ -3269,8 +3289,11 @@ int tcp_md5_hash_skb_data(struct tcp_md5sig_pool *hp,
 
        for (i = 0; i < shi->nr_frags; ++i) {
                const struct skb_frag_struct *f = &shi->frags[i];
-               struct page *page = skb_frag_page(f);
-               sg_set_page(&sg, page, skb_frag_size(f), f->page_offset);
+               unsigned int offset = f->page_offset;
+               struct page *page = skb_frag_page(f) + (offset >> PAGE_SHIFT);
+
+               sg_set_page(&sg, page, skb_frag_size(f),
+                           offset_in_page(offset));
                if (crypto_hash_update(desc, &sg, skb_frag_size(f)))
                        return 1;
        }
index 08bbe60..9c62257 100644 (file)
@@ -2743,8 +2743,8 @@ static void tcp_process_loss(struct sock *sk, int flag, bool is_dupack)
  * tcp_xmit_retransmit_queue().
  */
 static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked,
-                                 int prior_sacked, bool is_dupack,
-                                 int flag)
+                                 int prior_sacked, int prior_packets,
+                                 bool is_dupack, int flag)
 {
        struct inet_connection_sock *icsk = inet_csk(sk);
        struct tcp_sock *tp = tcp_sk(sk);
@@ -2804,7 +2804,8 @@ static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked,
                                tcp_add_reno_sack(sk);
                } else
                        do_lost = tcp_try_undo_partial(sk, pkts_acked);
-               newly_acked_sacked = pkts_acked + tp->sacked_out - prior_sacked;
+               newly_acked_sacked = prior_packets - tp->packets_out +
+                                    tp->sacked_out - prior_sacked;
                break;
        case TCP_CA_Loss:
                tcp_process_loss(sk, flag, is_dupack);
@@ -2818,7 +2819,8 @@ static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked,
                        if (is_dupack)
                                tcp_add_reno_sack(sk);
                }
-               newly_acked_sacked = pkts_acked + tp->sacked_out - prior_sacked;
+               newly_acked_sacked = prior_packets - tp->packets_out +
+                                    tp->sacked_out - prior_sacked;
 
                if (icsk->icsk_ca_state <= TCP_CA_Disorder)
                        tcp_try_undo_dsack(sk);
@@ -3330,9 +3332,10 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
        bool is_dupack = false;
        u32 prior_in_flight;
        u32 prior_fackets;
-       int prior_packets;
+       int prior_packets = tp->packets_out;
        int prior_sacked = tp->sacked_out;
        int pkts_acked = 0;
+       int previous_packets_out = 0;
 
        /* If the ack is older than previous acks
         * then we can probably ignore it.
@@ -3403,14 +3406,14 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
        sk->sk_err_soft = 0;
        icsk->icsk_probes_out = 0;
        tp->rcv_tstamp = tcp_time_stamp;
-       prior_packets = tp->packets_out;
        if (!prior_packets)
                goto no_queue;
 
        /* See if we can take anything off of the retransmit queue. */
+       previous_packets_out = tp->packets_out;
        flag |= tcp_clean_rtx_queue(sk, prior_fackets, prior_snd_una);
 
-       pkts_acked = prior_packets - tp->packets_out;
+       pkts_acked = previous_packets_out - tp->packets_out;
 
        if (tcp_ack_is_dubious(sk, flag)) {
                /* Advance CWND, if state allows this. */
@@ -3418,7 +3421,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
                        tcp_cong_avoid(sk, ack, prior_in_flight);
                is_dupack = !(flag & (FLAG_SND_UNA_ADVANCED | FLAG_NOT_DUP));
                tcp_fastretrans_alert(sk, pkts_acked, prior_sacked,
-                                     is_dupack, flag);
+                                     prior_packets, is_dupack, flag);
        } else {
                if (flag & FLAG_DATA_ACKED)
                        tcp_cong_avoid(sk, ack, prior_in_flight);
@@ -3441,7 +3444,7 @@ no_queue:
        /* If data was DSACKed, see if we can undo a cwnd reduction. */
        if (flag & FLAG_DSACKING_ACK)
                tcp_fastretrans_alert(sk, pkts_acked, prior_sacked,
-                                     is_dupack, flag);
+                                     prior_packets, is_dupack, flag);
        /* If this ack opens up a zero window, clear backoff.  It was
         * being used to time the probes, and is probably far higher than
         * it needs to be for normal retransmission.
@@ -3464,7 +3467,7 @@ old_ack:
        if (TCP_SKB_CB(skb)->sacked) {
                flag |= tcp_sacktag_write_queue(sk, skb, prior_snd_una);
                tcp_fastretrans_alert(sk, pkts_acked, prior_sacked,
-                                     is_dupack, flag);
+                                     prior_packets, is_dupack, flag);
        }
 
        SOCK_DEBUG(sk, "Ack %u before %u:%u\n", ack, tp->snd_una, tp->snd_nxt);
index 536d409..ec335fa 100644 (file)
@@ -874,11 +874,13 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,
                                                           &md5);
        tcp_header_size = tcp_options_size + sizeof(struct tcphdr);
 
-       if (tcp_packets_in_flight(tp) == 0) {
+       if (tcp_packets_in_flight(tp) == 0)
                tcp_ca_event(sk, CA_EVENT_TX_START);
-               skb->ooo_okay = 1;
-       } else
-               skb->ooo_okay = 0;
+
+       /* if no packet is in qdisc/device queue, then allow XPS to select
+        * another queue.
+        */
+       skb->ooo_okay = sk_wmem_alloc_get(sk) == 0;
 
        skb_push(skb, tcp_header_size);
        skb_reset_transport_header(skb);
index d1ab6ab..1bbf744 100644 (file)
@@ -1487,7 +1487,7 @@ static int ipv6_count_addresses(struct inet6_dev *idev)
 }
 
 int ipv6_chk_addr(struct net *net, const struct in6_addr *addr,
-                 struct net_device *dev, int strict)
+                 const struct net_device *dev, int strict)
 {
        struct inet6_ifaddr *ifp;
        unsigned int hash = inet6_addr_hash(addr);
@@ -2658,8 +2658,10 @@ static void init_loopback(struct net_device *dev)
                        sp_rt = addrconf_dst_alloc(idev, &sp_ifa->addr, 0);
 
                        /* Failure cases are ignored */
-                       if (!IS_ERR(sp_rt))
+                       if (!IS_ERR(sp_rt)) {
+                               sp_ifa->rt = sp_rt;
                                ip6_ins_rt(sp_rt);
+                       }
                }
                read_unlock_bh(&idev->lock);
        }
index d3ddd84..ecd6073 100644 (file)
@@ -1081,6 +1081,7 @@ static int ip6gre_tunnel_ioctl(struct net_device *dev,
                }
                if (t == NULL)
                        t = netdev_priv(dev);
+               memset(&p, 0, sizeof(p));
                ip6gre_tnl_parm_to_user(&p, &t->parms);
                if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p)))
                        err = -EFAULT;
@@ -1128,6 +1129,7 @@ static int ip6gre_tunnel_ioctl(struct net_device *dev,
                if (t) {
                        err = 0;
 
+                       memset(&p, 0, sizeof(p));
                        ip6gre_tnl_parm_to_user(&p, &t->parms);
                        if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p)))
                                err = -EFAULT;
index d2eedf1..dae1949 100644 (file)
@@ -1147,7 +1147,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
                        if (WARN_ON(np->cork.opt))
                                return -EINVAL;
 
-                       np->cork.opt = kmalloc(opt->tot_len, sk->sk_allocation);
+                       np->cork.opt = kzalloc(opt->tot_len, sk->sk_allocation);
                        if (unlikely(np->cork.opt == NULL))
                                return -ENOBUFS;
 
index 72836f4..95f3f1d 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/netfilter.h>
 #include <linux/netfilter_ipv6.h>
 #include <linux/export.h>
+#include <net/addrconf.h>
 #include <net/dst.h>
 #include <net/ipv6.h>
 #include <net/ip6_route.h>
@@ -186,6 +187,10 @@ static __sum16 nf_ip6_checksum_partial(struct sk_buff *skb, unsigned int hook,
        return csum;
 };
 
+static const struct nf_ipv6_ops ipv6ops = {
+       .chk_addr       = ipv6_chk_addr,
+};
+
 static const struct nf_afinfo nf_ip6_afinfo = {
        .family                 = AF_INET6,
        .checksum               = nf_ip6_checksum,
@@ -198,6 +203,7 @@ static const struct nf_afinfo nf_ip6_afinfo = {
 
 int __init ipv6_netfilter_init(void)
 {
+       RCU_INIT_POINTER(nf_ipv6_ops, &ipv6ops);
        return nf_register_afinfo(&nf_ip6_afinfo);
 }
 
@@ -206,5 +212,6 @@ int __init ipv6_netfilter_init(void)
  */
 void ipv6_netfilter_fini(void)
 {
+       RCU_INIT_POINTER(nf_ipv6_ops, NULL);
        nf_unregister_afinfo(&nf_ip6_afinfo);
 }
index f3c1ff4..51c3285 100644 (file)
@@ -90,7 +90,7 @@ static const struct snmp_mib snmp6_ipstats_list[] = {
        SNMP_MIB_ITEM("Ip6OutMcastOctets", IPSTATS_MIB_OUTMCASTOCTETS),
        SNMP_MIB_ITEM("Ip6InBcastOctets", IPSTATS_MIB_INBCASTOCTETS),
        SNMP_MIB_ITEM("Ip6OutBcastOctets", IPSTATS_MIB_OUTBCASTOCTETS),
-       SNMP_MIB_ITEM("InCsumErrors", IPSTATS_MIB_CSUMERRORS),
+       /* IPSTATS_MIB_CSUMERRORS is not relevant in IPv6 (no checksum) */
        SNMP_MIB_SENTINEL
 };
 
index 7116706..0a17ed9 100644 (file)
@@ -1890,6 +1890,17 @@ void tcp6_proc_exit(struct net *net)
 }
 #endif
 
+static void tcp_v6_clear_sk(struct sock *sk, int size)
+{
+       struct inet_sock *inet = inet_sk(sk);
+
+       /* we do not want to clear pinet6 field, because of RCU lookups */
+       sk_prot_clear_nulls(sk, offsetof(struct inet_sock, pinet6));
+
+       size -= offsetof(struct inet_sock, pinet6) + sizeof(inet->pinet6);
+       memset(&inet->pinet6 + 1, 0, size);
+}
+
 struct proto tcpv6_prot = {
        .name                   = "TCPv6",
        .owner                  = THIS_MODULE,
@@ -1933,6 +1944,7 @@ struct proto tcpv6_prot = {
 #ifdef CONFIG_MEMCG_KMEM
        .proto_cgroup           = tcp_proto_cgroup,
 #endif
+       .clear_sk               = tcp_v6_clear_sk,
 };
 
 static const struct inet6_protocol tcpv6_protocol = {
index d4defdd..42923b1 100644 (file)
@@ -1432,6 +1432,17 @@ void udp6_proc_exit(struct net *net) {
 }
 #endif /* CONFIG_PROC_FS */
 
+void udp_v6_clear_sk(struct sock *sk, int size)
+{
+       struct inet_sock *inet = inet_sk(sk);
+
+       /* we do not want to clear pinet6 field, because of RCU lookups */
+       sk_prot_clear_portaddr_nulls(sk, offsetof(struct inet_sock, pinet6));
+
+       size -= offsetof(struct inet_sock, pinet6) + sizeof(inet->pinet6);
+       memset(&inet->pinet6 + 1, 0, size);
+}
+
 /* ------------------------------------------------------------------------ */
 
 struct proto udpv6_prot = {
@@ -1462,7 +1473,7 @@ struct proto udpv6_prot = {
        .compat_setsockopt = compat_udpv6_setsockopt,
        .compat_getsockopt = compat_udpv6_getsockopt,
 #endif
-       .clear_sk          = sk_prot_clear_portaddr_nulls,
+       .clear_sk          = udp_v6_clear_sk,
 };
 
 static struct inet_protosw udpv6_protosw = {
index d757104..4691ed5 100644 (file)
@@ -31,6 +31,8 @@ extern int    udpv6_recvmsg(struct kiocb *iocb, struct sock *sk,
 extern int     udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb);
 extern void    udpv6_destroy_sock(struct sock *sk);
 
+extern void udp_v6_clear_sk(struct sock *sk, int size);
+
 #ifdef CONFIG_PROC_FS
 extern int     udp6_seq_show(struct seq_file *seq, void *v);
 #endif
index 3bb3a89..d3cfaf9 100644 (file)
@@ -46,11 +46,12 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
        unsigned int mss;
        unsigned int unfrag_ip6hlen, unfrag_len;
        struct frag_hdr *fptr;
-       u8 *mac_start, *prevhdr;
+       u8 *packet_start, *prevhdr;
        u8 nexthdr;
        u8 frag_hdr_sz = sizeof(struct frag_hdr);
        int offset;
        __wsum csum;
+       int tnl_hlen;
 
        mss = skb_shinfo(skb)->gso_size;
        if (unlikely(skb->len <= mss))
@@ -83,9 +84,11 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
        skb->ip_summed = CHECKSUM_NONE;
 
        /* Check if there is enough headroom to insert fragment header. */
-       if ((skb_mac_header(skb) < skb->head + frag_hdr_sz) &&
-           pskb_expand_head(skb, frag_hdr_sz, 0, GFP_ATOMIC))
-               goto out;
+       tnl_hlen = skb_tnl_header_len(skb);
+       if (skb_headroom(skb) < (tnl_hlen + frag_hdr_sz)) {
+               if (gso_pskb_expand_head(skb, tnl_hlen + frag_hdr_sz))
+                       goto out;
+       }
 
        /* Find the unfragmentable header and shift it left by frag_hdr_sz
         * bytes to insert fragment header.
@@ -93,11 +96,12 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
        unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr);
        nexthdr = *prevhdr;
        *prevhdr = NEXTHDR_FRAGMENT;
-       unfrag_len = skb_network_header(skb) - skb_mac_header(skb) +
-                    unfrag_ip6hlen;
-       mac_start = skb_mac_header(skb);
-       memmove(mac_start-frag_hdr_sz, mac_start, unfrag_len);
+       unfrag_len = (skb_network_header(skb) - skb_mac_header(skb)) +
+                    unfrag_ip6hlen + tnl_hlen;
+       packet_start = (u8 *) skb->head + SKB_GSO_CB(skb)->mac_offset;
+       memmove(packet_start-frag_hdr_sz, packet_start, unfrag_len);
 
+       SKB_GSO_CB(skb)->mac_offset -= frag_hdr_sz;
        skb->mac_header -= frag_hdr_sz;
        skb->network_header -= frag_hdr_sz;
 
index 1d08e21..dfcc4be 100644 (file)
@@ -56,7 +56,7 @@ struct proto udplitev6_prot = {
        .compat_setsockopt = compat_udpv6_setsockopt,
        .compat_getsockopt = compat_udpv6_getsockopt,
 #endif
-       .clear_sk          = sk_prot_clear_portaddr_nulls,
+       .clear_sk          = udp_v6_clear_sk,
 };
 
 static struct inet_protosw udplite6_protosw = {
index 4ef7bdb..23ed03d 100644 (file)
@@ -103,8 +103,10 @@ static int xfrm6_fill_dst(struct xfrm_dst *xdst, struct net_device *dev,
        dev_hold(dev);
 
        xdst->u.rt6.rt6i_idev = in6_dev_get(dev);
-       if (!xdst->u.rt6.rt6i_idev)
+       if (!xdst->u.rt6.rt6i_idev) {
+               dev_put(dev);
                return -ENODEV;
+       }
 
        rt6_transfer_peer(&xdst->u.rt6, rt);
 
index 8c00416..9ea0c93 100644 (file)
@@ -544,7 +544,7 @@ static void irlap_recv_discovery_xid_cmd(struct irlap_cb *self,
                /*
                 *  We now have some discovery info to deliver!
                 */
-               discovery = kmalloc(sizeof(discovery_t), GFP_ATOMIC);
+               discovery = kzalloc(sizeof(discovery_t), GFP_ATOMIC);
                if (!discovery) {
                        IRDA_WARNING("%s: unable to malloc!\n", __func__);
                        return;
index 5b1e5af..c5fbd75 100644 (file)
@@ -2366,6 +2366,8 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, const struct sa
 
 out:
        xfrm_pol_put(xp);
+       if (err == 0)
+               xfrm_garbage_collect(net);
        return err;
 }
 
@@ -2615,6 +2617,8 @@ static int pfkey_spdget(struct sock *sk, struct sk_buff *skb, const struct sadb_
 
 out:
        xfrm_pol_put(xp);
+       if (delete && err == 0)
+               xfrm_garbage_collect(net);
        return err;
 }
 
index 158e6eb..44be28c 100644 (file)
@@ -1267,6 +1267,7 @@ void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata);
 void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata);
 void ieee80211_mgd_conn_tx_status(struct ieee80211_sub_if_data *sdata,
                                  __le16 fc, bool acked);
+void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata);
 
 /* IBSS code */
 void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local);
index 60f1ce5..98d20c0 100644 (file)
@@ -159,9 +159,10 @@ static int ieee80211_change_mtu(struct net_device *dev, int new_mtu)
        return 0;
 }
 
-static int ieee80211_verify_mac(struct ieee80211_local *local, u8 *addr)
+static int ieee80211_verify_mac(struct ieee80211_sub_if_data *sdata, u8 *addr)
 {
-       struct ieee80211_sub_if_data *sdata;
+       struct ieee80211_local *local = sdata->local;
+       struct ieee80211_sub_if_data *iter;
        u64 new, mask, tmp;
        u8 *m;
        int ret = 0;
@@ -181,11 +182,14 @@ static int ieee80211_verify_mac(struct ieee80211_local *local, u8 *addr)
 
 
        mutex_lock(&local->iflist_mtx);
-       list_for_each_entry(sdata, &local->interfaces, list) {
-               if (sdata->vif.type == NL80211_IFTYPE_MONITOR)
+       list_for_each_entry(iter, &local->interfaces, list) {
+               if (iter == sdata)
+                       continue;
+
+               if (iter->vif.type == NL80211_IFTYPE_MONITOR)
                        continue;
 
-               m = sdata->vif.addr;
+               m = iter->vif.addr;
                tmp =   ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) |
                        ((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) |
                        ((u64)m[4] << 1*8) | ((u64)m[5] << 0*8);
@@ -209,7 +213,7 @@ static int ieee80211_change_mac(struct net_device *dev, void *addr)
        if (ieee80211_sdata_running(sdata))
                return -EBUSY;
 
-       ret = ieee80211_verify_mac(sdata->local, sa->sa_data);
+       ret = ieee80211_verify_mac(sdata, sa->sa_data);
        if (ret)
                return ret;
 
@@ -474,6 +478,9 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
                        master->control_port_protocol;
                sdata->control_port_no_encrypt =
                        master->control_port_no_encrypt;
+               sdata->vif.cab_queue = master->vif.cab_queue;
+               memcpy(sdata->vif.hw_queue, master->vif.hw_queue,
+                      sizeof(sdata->vif.hw_queue));
                break;
                }
        case NL80211_IFTYPE_AP:
@@ -653,7 +660,11 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
 
        ieee80211_recalc_ps(local, -1);
 
-       if (dev) {
+       if (sdata->vif.type == NL80211_IFTYPE_MONITOR ||
+           sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
+               /* XXX: for AP_VLAN, actually track AP queues */
+               netif_tx_start_all_queues(dev);
+       } else if (dev) {
                unsigned long flags;
                int n_acs = IEEE80211_NUM_ACS;
                int ac;
@@ -1479,7 +1490,17 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local,
                        break;
                }
 
+               /*
+                * Pick address of existing interface in case user changed
+                * MAC address manually, default to perm_addr.
+                */
                m = local->hw.wiphy->perm_addr;
+               list_for_each_entry(sdata, &local->interfaces, list) {
+                       if (sdata->vif.type == NL80211_IFTYPE_MONITOR)
+                               continue;
+                       m = sdata->vif.addr;
+                       break;
+               }
                start = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) |
                        ((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) |
                        ((u64)m[4] << 1*8) | ((u64)m[5] << 0*8);
@@ -1696,6 +1717,15 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local)
 
        ASSERT_RTNL();
 
+       /*
+        * Close all AP_VLAN interfaces first, as otherwise they
+        * might be closed while the AP interface they belong to
+        * is closed, causing unregister_netdevice_many() to crash.
+        */
+       list_for_each_entry(sdata, &local->interfaces, list)
+               if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+                       dev_close(sdata->dev);
+
        mutex_lock(&local->iflist_mtx);
        list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) {
                list_del(&sdata->list);
index 29620bf..a8c2130 100644 (file)
@@ -1015,7 +1015,8 @@ static void ieee80211_chswitch_timer(unsigned long data)
 
 static void
 ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
-                                u64 timestamp, struct ieee802_11_elems *elems)
+                                u64 timestamp, struct ieee802_11_elems *elems,
+                                bool beacon)
 {
        struct ieee80211_local *local = sdata->local;
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
@@ -1032,6 +1033,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
        struct cfg80211_chan_def new_vht_chandef = {};
        const struct ieee80211_sec_chan_offs_ie *sec_chan_offs;
        const struct ieee80211_wide_bw_chansw_ie *wide_bw_chansw_ie;
+       const struct ieee80211_ht_operation *ht_oper;
        int secondary_channel_offset = -1;
 
        ASSERT_MGD_MTX(ifmgd);
@@ -1048,11 +1050,14 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
 
        sec_chan_offs = elems->sec_chan_offs;
        wide_bw_chansw_ie = elems->wide_bw_chansw_ie;
+       ht_oper = elems->ht_operation;
 
        if (ifmgd->flags & (IEEE80211_STA_DISABLE_HT |
                            IEEE80211_STA_DISABLE_40MHZ)) {
                sec_chan_offs = NULL;
                wide_bw_chansw_ie = NULL;
+               /* only used for bandwidth here */
+               ht_oper = NULL;
        }
 
        if (ifmgd->flags & IEEE80211_STA_DISABLE_VHT)
@@ -1094,10 +1099,20 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
                return;
        }
 
-       if (sec_chan_offs) {
+       if (!beacon && sec_chan_offs) {
                secondary_channel_offset = sec_chan_offs->sec_chan_offs;
+       } else if (beacon && ht_oper) {
+               secondary_channel_offset =
+                       ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET;
        } else if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) {
-               /* if HT is enabled and the IE not present, it's still HT */
+               /*
+                * If it's not a beacon, HT is enabled and the IE not present,
+                * it's 20 MHz, 802.11-2012 8.5.2.6:
+                *      This element [the Secondary Channel Offset Element] is
+                *      present when switching to a 40 MHz channel. It may be
+                *      present when switching to a 20 MHz channel (in which
+                *      case the secondary channel offset is set to SCN).
+                */
                secondary_channel_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE;
        }
 
@@ -2796,7 +2811,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
                mutex_unlock(&local->iflist_mtx);
        }
 
-       ieee80211_sta_process_chanswitch(sdata, rx_status->mactime, elems);
+       ieee80211_sta_process_chanswitch(sdata, rx_status->mactime,
+                                        elems, true);
 
 }
 
@@ -3210,7 +3226,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
 
                        ieee80211_sta_process_chanswitch(sdata,
                                                         rx_status->mactime,
-                                                        &elems);
+                                                        &elems, false);
                } else if (mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) {
                        ies_len = skb->len -
                                  offsetof(struct ieee80211_mgmt,
@@ -3232,7 +3248,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
 
                        ieee80211_sta_process_chanswitch(sdata,
                                                         rx_status->mactime,
-                                                        &elems);
+                                                        &elems, false);
                }
                break;
        }
@@ -3305,10 +3321,6 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata)
        if (WARN_ON_ONCE(!auth_data))
                return -EINVAL;
 
-       if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)
-               tx_flags = IEEE80211_TX_CTL_REQ_TX_STATUS |
-                          IEEE80211_TX_INTFL_MLME_CONN_TX;
-
        auth_data->tries++;
 
        if (auth_data->tries > IEEE80211_AUTH_MAX_TRIES) {
@@ -3342,6 +3354,10 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata)
                        auth_data->expected_transaction = trans;
                }
 
+               if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)
+                       tx_flags = IEEE80211_TX_CTL_REQ_TX_STATUS |
+                                  IEEE80211_TX_INTFL_MLME_CONN_TX;
+
                ieee80211_send_auth(sdata, trans, auth_data->algorithm, status,
                                    auth_data->data, auth_data->data_len,
                                    auth_data->bss->bssid,
@@ -3365,12 +3381,12 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata)
                 * will not answer to direct packet in unassociated state.
                 */
                ieee80211_send_probe_req(sdata, NULL, ssidie + 2, ssidie[1],
-                                        NULL, 0, (u32) -1, true, tx_flags,
+                                        NULL, 0, (u32) -1, true, 0,
                                         auth_data->bss->channel, false);
                rcu_read_unlock();
        }
 
-       if (!(local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)) {
+       if (tx_flags == 0) {
                auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
                ifmgd->auth_data->timeout_started = true;
                run_again(ifmgd, auth_data->timeout);
@@ -3623,6 +3639,31 @@ static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata)
        }
 }
 
+#ifdef CONFIG_PM
+void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata)
+{
+       struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+
+       mutex_lock(&ifmgd->mtx);
+       if (!ifmgd->associated) {
+               mutex_unlock(&ifmgd->mtx);
+               return;
+       }
+
+       if (sdata->flags & IEEE80211_SDATA_DISCONNECT_RESUME) {
+               sdata->flags &= ~IEEE80211_SDATA_DISCONNECT_RESUME;
+               mlme_dbg(sdata, "driver requested disconnect after resume\n");
+               ieee80211_sta_connection_lost(sdata,
+                                             ifmgd->associated->bssid,
+                                             WLAN_REASON_UNSPECIFIED,
+                                             true);
+               mutex_unlock(&ifmgd->mtx);
+               return;
+       }
+       mutex_unlock(&ifmgd->mtx);
+}
+#endif
+
 /* interface setup */
 void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
 {
@@ -4329,7 +4370,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
        u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
        bool tx = !req->local_state_change;
-       bool sent_frame = false;
+       bool report_frame = false;
 
        mutex_lock(&ifmgd->mtx);
 
@@ -4346,7 +4387,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
                ieee80211_destroy_auth_data(sdata, false);
                mutex_unlock(&ifmgd->mtx);
 
-               sent_frame = tx;
+               report_frame = true;
                goto out;
        }
 
@@ -4354,12 +4395,12 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
            ether_addr_equal(ifmgd->associated->bssid, req->bssid)) {
                ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
                                       req->reason_code, tx, frame_buf);
-               sent_frame = tx;
+               report_frame = true;
        }
        mutex_unlock(&ifmgd->mtx);
 
  out:
-       if (sent_frame)
+       if (report_frame)
                __cfg80211_send_deauth(sdata->dev, frame_buf,
                                       IEEE80211_DEAUTH_FRAME_LEN);
 
index 0d51877..d3f414f 100644 (file)
@@ -688,8 +688,15 @@ int rate_control_set_rates(struct ieee80211_hw *hw,
                           struct ieee80211_sta *pubsta,
                           struct ieee80211_sta_rates *rates)
 {
-       struct ieee80211_sta_rates *old = rcu_dereference(pubsta->rates);
+       struct ieee80211_sta_rates *old;
 
+       /*
+        * mac80211 guarantees that this function will not be called
+        * concurrently, so the following RCU access is safe, even without
+        * extra locking. This can not be checked easily, so we just set
+        * the condition to true.
+        */
+       old = rcu_dereference_protected(pubsta->rates, true);
        rcu_assign_pointer(pubsta->rates, rates);
        if (old)
                kfree_rcu(old, rcu_head);
index c8447af..8e29526 100644 (file)
@@ -3036,6 +3036,9 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx,
                         * and location updates. Note that mac80211
                         * itself never looks at these frames.
                         */
+                       if (!multicast &&
+                           !ether_addr_equal(sdata->vif.addr, hdr->addr1))
+                               return 0;
                        if (ieee80211_is_public_action(hdr, skb->len))
                                return 1;
                        if (!ieee80211_is_beacon(hdr->frame_control))
index 3ed801d..124b1fd 100644 (file)
@@ -208,10 +208,10 @@ void ieee80211_get_tkip_p2k(struct ieee80211_key_conf *keyconf,
        u32 iv32 = get_unaligned_le32(&data[4]);
        u16 iv16 = data[2] | (data[0] << 8);
 
-       spin_lock_bh(&key->u.tkip.txlock);
+       spin_lock(&key->u.tkip.txlock);
        ieee80211_compute_tkip_p1k(key, iv32);
        tkip_mixing_phase2(tk, ctx, iv16, p2k);
-       spin_unlock_bh(&key->u.tkip.txlock);
+       spin_unlock(&key->u.tkip.txlock);
 }
 EXPORT_SYMBOL(ieee80211_get_tkip_p2k);
 
index 3f87fa4..27e0715 100644 (file)
@@ -1740,6 +1740,13 @@ int ieee80211_reconfig(struct ieee80211_local *local)
        mb();
        local->resuming = false;
 
+       list_for_each_entry(sdata, &local->interfaces, list) {
+               if (!ieee80211_sdata_running(sdata))
+                       continue;
+               if (sdata->vif.type == NL80211_IFTYPE_STATION)
+                       ieee80211_sta_restart(sdata);
+       }
+
        mod_timer(&local->sta_cleanup, jiffies + 1);
 #else
        WARN_ON(1);
index 07c865a..857ca9f 100644 (file)
@@ -30,6 +30,8 @@ static DEFINE_MUTEX(afinfo_mutex);
 
 const struct nf_afinfo __rcu *nf_afinfo[NFPROTO_NUMPROTO] __read_mostly;
 EXPORT_SYMBOL(nf_afinfo);
+const struct nf_ipv6_ops __rcu *nf_ipv6_ops __read_mostly;
+EXPORT_SYMBOL_GPL(nf_ipv6_ops);
 
 int nf_register_afinfo(const struct nf_afinfo *afinfo)
 {
index 085b588..05565d2 100644 (file)
@@ -1001,6 +1001,32 @@ static inline int is_tcp_reset(const struct sk_buff *skb, int nh_len)
        return th->rst;
 }
 
+static inline bool is_new_conn(const struct sk_buff *skb,
+                              struct ip_vs_iphdr *iph)
+{
+       switch (iph->protocol) {
+       case IPPROTO_TCP: {
+               struct tcphdr _tcph, *th;
+
+               th = skb_header_pointer(skb, iph->len, sizeof(_tcph), &_tcph);
+               if (th == NULL)
+                       return false;
+               return th->syn;
+       }
+       case IPPROTO_SCTP: {
+               sctp_chunkhdr_t *sch, schunk;
+
+               sch = skb_header_pointer(skb, iph->len + sizeof(sctp_sctphdr_t),
+                                        sizeof(schunk), &schunk);
+               if (sch == NULL)
+                       return false;
+               return sch->type == SCTP_CID_INIT;
+       }
+       default:
+               return false;
+       }
+}
+
 /* Handle response packets: rewrite addresses and send away...
  */
 static unsigned int
@@ -1612,6 +1638,15 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af)
         * Check if the packet belongs to an existing connection entry
         */
        cp = pp->conn_in_get(af, skb, &iph, 0);
+
+       if (unlikely(sysctl_expire_nodest_conn(ipvs)) && cp && cp->dest &&
+           unlikely(!atomic_read(&cp->dest->weight)) && !iph.fragoffs &&
+           is_new_conn(skb, &iph)) {
+               ip_vs_conn_expire_now(cp);
+               __ip_vs_conn_put(cp);
+               cp = NULL;
+       }
+
        if (unlikely(!cp) && !iph.fragoffs) {
                /* No (second) fragments need to enter here, as nf_defrag_ipv6
                 * replayed fragment zero will already have created the cp
index 5b142fb..9e6c2a0 100644 (file)
@@ -2542,6 +2542,7 @@ __ip_vs_get_dest_entries(struct net *net, const struct ip_vs_get_dests *get,
                struct ip_vs_dest *dest;
                struct ip_vs_dest_entry entry;
 
+               memset(&entry, 0, sizeof(entry));
                list_for_each_entry(dest, &svc->destinations, n_list) {
                        if (count >= get->num_dests)
                                break;
index 0df269d..a65edfe 100644 (file)
@@ -67,8 +67,8 @@ struct ip_vs_sh_bucket {
 #define IP_VS_SH_TAB_MASK               (IP_VS_SH_TAB_SIZE - 1)
 
 struct ip_vs_sh_state {
-       struct ip_vs_sh_bucket          buckets[IP_VS_SH_TAB_SIZE];
        struct rcu_head                 rcu_head;
+       struct ip_vs_sh_bucket          buckets[IP_VS_SH_TAB_SIZE];
 };
 
 /*
index 388656d..3b18dd1 100644 (file)
@@ -148,7 +148,7 @@ void nf_log_packet(struct net *net,
                va_start(args, fmt);
                vsnprintf(prefix, sizeof(prefix), fmt, args);
                va_end(args);
-               logger->logfn(pf, hooknum, skb, in, out, loginfo, prefix);
+               logger->logfn(net, pf, hooknum, skb, in, out, loginfo, prefix);
        }
        rcu_read_unlock();
 }
@@ -368,17 +368,20 @@ static int __net_init nf_log_net_init(struct net *net)
        return 0;
 
 out_sysctl:
+#ifdef CONFIG_PROC_FS
        /* For init_net: errors will trigger panic, don't unroll on error. */
        if (!net_eq(net, &init_net))
                remove_proc_entry("nf_log", net->nf.proc_netfilter);
-
+#endif
        return ret;
 }
 
 static void __net_exit nf_log_net_exit(struct net *net)
 {
        netfilter_log_sysctl_exit(net);
+#ifdef CONFIG_PROC_FS
        remove_proc_entry("nf_log", net->nf.proc_netfilter);
+#endif
 }
 
 static struct pernet_operations nf_log_net_ops = {
index dc3fd5d..c7b6d46 100644 (file)
@@ -149,9 +149,12 @@ nfnl_acct_dump(struct sk_buff *skb, struct netlink_callback *cb)
 
        rcu_read_lock();
        list_for_each_entry_rcu(cur, &nfnl_acct_list, head) {
-               if (last && cur != last)
-                       continue;
+               if (last) {
+                       if (cur != last)
+                               continue;
 
+                       last = NULL;
+               }
                if (nfnl_acct_fill_info(skb, NETLINK_CB(cb->skb).portid,
                                       cb->nlh->nlmsg_seq,
                                       NFNL_MSG_TYPE(cb->nlh->nlmsg_type),
index 701c88a..65074df 100644 (file)
@@ -220,9 +220,12 @@ ctnl_timeout_dump(struct sk_buff *skb, struct netlink_callback *cb)
 
        rcu_read_lock();
        list_for_each_entry_rcu(cur, &cttimeout_list, head) {
-               if (last && cur != last)
-                       continue;
+               if (last) {
+                       if (cur != last)
+                               continue;
 
+                       last = NULL;
+               }
                if (ctnl_timeout_fill_info(skb, NETLINK_CB(cb->skb).portid,
                                           cb->nlh->nlmsg_seq,
                                           NFNL_MSG_TYPE(cb->nlh->nlmsg_type),
index faf1e93..962e979 100644 (file)
@@ -602,7 +602,8 @@ static struct nf_loginfo default_loginfo = {
 
 /* log handler for internal netfilter logging api */
 void
-nfulnl_log_packet(u_int8_t pf,
+nfulnl_log_packet(struct net *net,
+                 u_int8_t pf,
                  unsigned int hooknum,
                  const struct sk_buff *skb,
                  const struct net_device *in,
@@ -615,7 +616,6 @@ nfulnl_log_packet(u_int8_t pf,
        const struct nf_loginfo *li;
        unsigned int qthreshold;
        unsigned int plen;
-       struct net *net = dev_net(in ? in : out);
        struct nfnl_log_net *log = nfnl_log_pernet(net);
 
        if (li_user && li_user->type == NF_LOG_TYPE_ULOG)
@@ -1045,7 +1045,9 @@ static int __net_init nfnl_log_net_init(struct net *net)
 
 static void __net_exit nfnl_log_net_exit(struct net *net)
 {
+#ifdef CONFIG_PROC_FS
        remove_proc_entry("nfnetlink_log", net->nf.proc_netfilter);
+#endif
 }
 
 static struct pernet_operations nfnl_log_net_ops = {
index 2e0e835..5352b2d 100644 (file)
@@ -637,9 +637,6 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
        if (queue->copy_mode == NFQNL_COPY_NONE)
                return -EINVAL;
 
-       if ((queue->flags & NFQA_CFG_F_GSO) || !skb_is_gso(entry->skb))
-               return __nfqnl_enqueue_packet(net, queue, entry);
-
        skb = entry->skb;
 
        switch (entry->pf) {
@@ -651,6 +648,9 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
                break;
        }
 
+       if ((queue->flags & NFQA_CFG_F_GSO) || !skb_is_gso(skb))
+               return __nfqnl_enqueue_packet(net, queue, entry);
+
        nf_bridge_adjust_skb_data(skb);
        segs = skb_gso_segment(skb, 0);
        /* Does not use PTR_ERR to limit the number of error codes that can be
@@ -1285,7 +1285,9 @@ static int __net_init nfnl_queue_net_init(struct net *net)
 
 static void __net_exit nfnl_queue_net_exit(struct net *net)
 {
+#ifdef CONFIG_PROC_FS
        remove_proc_entry("nfnetlink_queue", net->nf.proc_netfilter);
+#endif
 }
 
 static struct pernet_operations nfnl_queue_net_ops = {
index fe573f6..5ab2484 100644 (file)
@@ -466,7 +466,8 @@ log_packet_common(struct sbuff *m,
 
 
 static void
-ipt_log_packet(u_int8_t pf,
+ipt_log_packet(struct net *net,
+              u_int8_t pf,
               unsigned int hooknum,
               const struct sk_buff *skb,
               const struct net_device *in,
@@ -475,7 +476,6 @@ ipt_log_packet(u_int8_t pf,
               const char *prefix)
 {
        struct sbuff *m;
-       struct net *net = dev_net(in ? in : out);
 
        /* FIXME: Disabled from containers until syslog ns is supported */
        if (!net_eq(net, &init_net))
@@ -737,7 +737,7 @@ static void dump_ipv6_packet(struct sbuff *m,
                dump_sk_uid_gid(m, skb->sk);
 
        /* Max length: 16 "MARK=0xFFFFFFFF " */
-       if (!recurse && skb->mark)
+       if (recurse && skb->mark)
                sb_add(m, "MARK=0x%x ", skb->mark);
 }
 
@@ -797,7 +797,8 @@ fallback:
 }
 
 static void
-ip6t_log_packet(u_int8_t pf,
+ip6t_log_packet(struct net *net,
+               u_int8_t pf,
                unsigned int hooknum,
                const struct sk_buff *skb,
                const struct net_device *in,
@@ -806,7 +807,6 @@ ip6t_log_packet(u_int8_t pf,
                const char *prefix)
 {
        struct sbuff *m;
-       struct net *net = dev_net(in ? in : out);
 
        /* FIXME: Disabled from containers until syslog ns is supported */
        if (!net_eq(net, &init_net))
@@ -833,17 +833,18 @@ log_tg(struct sk_buff *skb, const struct xt_action_param *par)
 {
        const struct xt_log_info *loginfo = par->targinfo;
        struct nf_loginfo li;
+       struct net *net = dev_net(par->in ? par->in : par->out);
 
        li.type = NF_LOG_TYPE_LOG;
        li.u.log.level = loginfo->level;
        li.u.log.logflags = loginfo->logflags;
 
        if (par->family == NFPROTO_IPV4)
-               ipt_log_packet(NFPROTO_IPV4, par->hooknum, skb, par->in,
+               ipt_log_packet(net, NFPROTO_IPV4, par->hooknum, skb, par->in,
                               par->out, &li, loginfo->prefix);
 #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
        else if (par->family == NFPROTO_IPV6)
-               ip6t_log_packet(NFPROTO_IPV6, par->hooknum, skb, par->in,
+               ip6t_log_packet(net, NFPROTO_IPV6, par->hooknum, skb, par->in,
                                par->out, &li, loginfo->prefix);
 #endif
        else
index a17dd0f..fb7497c 100644 (file)
@@ -26,13 +26,14 @@ nflog_tg(struct sk_buff *skb, const struct xt_action_param *par)
 {
        const struct xt_nflog_info *info = par->targinfo;
        struct nf_loginfo li;
+       struct net *net = dev_net(par->in ? par->in : par->out);
 
        li.type              = NF_LOG_TYPE_ULOG;
        li.u.ulog.copy_len   = info->len;
        li.u.ulog.group      = info->group;
        li.u.ulog.qthreshold = info->threshold;
 
-       nfulnl_log_packet(par->family, par->hooknum, skb, par->in,
+       nfulnl_log_packet(net, par->family, par->hooknum, skb, par->in,
                          par->out, &li, info->prefix);
        return XT_CONTINUE;
 }
index a75240f..afaebc7 100644 (file)
@@ -125,6 +125,12 @@ tcpmss_mangle_packet(struct sk_buff *skb,
 
        skb_put(skb, TCPOLEN_MSS);
 
+       /* RFC 879 states that the default MSS is 536 without specific
+        * knowledge that the destination host is prepared to accept larger.
+        * Since no MSS was provided, we MUST NOT set a value > 536.
+        */
+       newmss = min(newmss, (u16)536);
+
        opt = (u_int8_t *)tcph + sizeof(struct tcphdr);
        memmove(opt + TCPOLEN_MSS, opt, tcplen - sizeof(struct tcphdr));
 
index 25fd1c4..1eb1a44 100644 (file)
@@ -30,17 +30,28 @@ static inline unsigned int optlen(const u_int8_t *opt, unsigned int offset)
 
 static unsigned int
 tcpoptstrip_mangle_packet(struct sk_buff *skb,
-                         const struct xt_tcpoptstrip_target_info *info,
+                         const struct xt_action_param *par,
                          unsigned int tcphoff, unsigned int minlen)
 {
+       const struct xt_tcpoptstrip_target_info *info = par->targinfo;
        unsigned int optl, i, j;
        struct tcphdr *tcph;
        u_int16_t n, o;
        u_int8_t *opt;
+       int len;
+
+       /* This is a fragment, no TCP header is available */
+       if (par->fragoff != 0)
+               return XT_CONTINUE;
 
        if (!skb_make_writable(skb, skb->len))
                return NF_DROP;
 
+       len = skb->len - tcphoff;
+       if (len < (int)sizeof(struct tcphdr) ||
+           tcp_hdr(skb)->doff * 4 > len)
+               return NF_DROP;
+
        tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff);
        opt  = (u_int8_t *)tcph;
 
@@ -76,7 +87,7 @@ tcpoptstrip_mangle_packet(struct sk_buff *skb,
 static unsigned int
 tcpoptstrip_tg4(struct sk_buff *skb, const struct xt_action_param *par)
 {
-       return tcpoptstrip_mangle_packet(skb, par->targinfo, ip_hdrlen(skb),
+       return tcpoptstrip_mangle_packet(skb, par, ip_hdrlen(skb),
               sizeof(struct iphdr) + sizeof(struct tcphdr));
 }
 
@@ -94,7 +105,7 @@ tcpoptstrip_tg6(struct sk_buff *skb, const struct xt_action_param *par)
        if (tcphoff < 0)
                return NF_DROP;
 
-       return tcpoptstrip_mangle_packet(skb, par->targinfo, tcphoff,
+       return tcpoptstrip_mangle_packet(skb, par, tcphoff,
               sizeof(*ipv6h) + sizeof(struct tcphdr));
 }
 #endif
index 49c5ff7..68ff29f 100644 (file)
@@ -22,6 +22,7 @@
 #include <net/ip6_fib.h>
 #endif
 
+#include <linux/netfilter_ipv6.h>
 #include <linux/netfilter/xt_addrtype.h>
 #include <linux/netfilter/x_tables.h>
 
@@ -33,12 +34,12 @@ MODULE_ALIAS("ip6t_addrtype");
 
 #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
 static u32 match_lookup_rt6(struct net *net, const struct net_device *dev,
-                           const struct in6_addr *addr)
+                           const struct in6_addr *addr, u16 mask)
 {
        const struct nf_afinfo *afinfo;
        struct flowi6 flow;
        struct rt6_info *rt;
-       u32 ret;
+       u32 ret = 0;
        int route_err;
 
        memset(&flow, 0, sizeof(flow));
@@ -49,12 +50,19 @@ static u32 match_lookup_rt6(struct net *net, const struct net_device *dev,
        rcu_read_lock();
 
        afinfo = nf_get_afinfo(NFPROTO_IPV6);
-       if (afinfo != NULL)
+       if (afinfo != NULL) {
+               const struct nf_ipv6_ops *v6ops;
+
+               if (dev && (mask & XT_ADDRTYPE_LOCAL)) {
+                       v6ops = nf_get_ipv6_ops();
+                       if (v6ops && v6ops->chk_addr(net, addr, dev, true))
+                               ret = XT_ADDRTYPE_LOCAL;
+               }
                route_err = afinfo->route(net, (struct dst_entry **)&rt,
-                                       flowi6_to_flowi(&flow), !!dev);
-       else
+                                         flowi6_to_flowi(&flow), false);
+       } else {
                route_err = 1;
-
+       }
        rcu_read_unlock();
 
        if (route_err)
@@ -62,15 +70,12 @@ static u32 match_lookup_rt6(struct net *net, const struct net_device *dev,
 
        if (rt->rt6i_flags & RTF_REJECT)
                ret = XT_ADDRTYPE_UNREACHABLE;
-       else
-               ret = 0;
 
-       if (rt->rt6i_flags & RTF_LOCAL)
+       if (dev == NULL && rt->rt6i_flags & RTF_LOCAL)
                ret |= XT_ADDRTYPE_LOCAL;
        if (rt->rt6i_flags & RTF_ANYCAST)
                ret |= XT_ADDRTYPE_ANYCAST;
 
-
        dst_release(&rt->dst);
        return ret;
 }
@@ -90,7 +95,7 @@ static bool match_type6(struct net *net, const struct net_device *dev,
 
        if ((XT_ADDRTYPE_LOCAL | XT_ADDRTYPE_ANYCAST |
             XT_ADDRTYPE_UNREACHABLE) & mask)
-               return !!(mask & match_lookup_rt6(net, dev, addr));
+               return !!(mask & match_lookup_rt6(net, dev, addr, mask));
        return true;
 }
 
index d8d4243..6bb1d42 100644 (file)
@@ -245,6 +245,71 @@ static void netlbl_domhsh_audit_add(struct netlbl_dom_map *entry,
        }
 }
 
+/**
+ * netlbl_domhsh_validate - Validate a new domain mapping entry
+ * @entry: the entry to validate
+ *
+ * This function validates the new domain mapping entry to ensure that it is
+ * a valid entry.  Returns zero on success, negative values on failure.
+ *
+ */
+static int netlbl_domhsh_validate(const struct netlbl_dom_map *entry)
+{
+       struct netlbl_af4list *iter4;
+       struct netlbl_domaddr4_map *map4;
+#if IS_ENABLED(CONFIG_IPV6)
+       struct netlbl_af6list *iter6;
+       struct netlbl_domaddr6_map *map6;
+#endif /* IPv6 */
+
+       if (entry == NULL)
+               return -EINVAL;
+
+       switch (entry->type) {
+       case NETLBL_NLTYPE_UNLABELED:
+               if (entry->type_def.cipsov4 != NULL ||
+                   entry->type_def.addrsel != NULL)
+                       return -EINVAL;
+               break;
+       case NETLBL_NLTYPE_CIPSOV4:
+               if (entry->type_def.cipsov4 == NULL)
+                       return -EINVAL;
+               break;
+       case NETLBL_NLTYPE_ADDRSELECT:
+               netlbl_af4list_foreach(iter4, &entry->type_def.addrsel->list4) {
+                       map4 = netlbl_domhsh_addr4_entry(iter4);
+                       switch (map4->type) {
+                       case NETLBL_NLTYPE_UNLABELED:
+                               if (map4->type_def.cipsov4 != NULL)
+                                       return -EINVAL;
+                               break;
+                       case NETLBL_NLTYPE_CIPSOV4:
+                               if (map4->type_def.cipsov4 == NULL)
+                                       return -EINVAL;
+                               break;
+                       default:
+                               return -EINVAL;
+                       }
+               }
+#if IS_ENABLED(CONFIG_IPV6)
+               netlbl_af6list_foreach(iter6, &entry->type_def.addrsel->list6) {
+                       map6 = netlbl_domhsh_addr6_entry(iter6);
+                       switch (map6->type) {
+                       case NETLBL_NLTYPE_UNLABELED:
+                               break;
+                       default:
+                               return -EINVAL;
+                       }
+               }
+#endif /* IPv6 */
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 /*
  * Domain Hash Table Functions
  */
@@ -311,6 +376,10 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry,
        struct netlbl_af6list *tmp6;
 #endif /* IPv6 */
 
+       ret_val = netlbl_domhsh_validate(entry);
+       if (ret_val != 0)
+               return ret_val;
+
        /* XXX - we can remove this RCU read lock as the spinlock protects the
         *       entire function, but before we do we need to fixup the
         *       netlbl_af[4,6]list RCU functions to do "the right thing" with
index 12ac6b4..57ee84d 100644 (file)
@@ -371,7 +371,7 @@ static int netlink_mmap(struct file *file, struct socket *sock,
        err = 0;
 out:
        mutex_unlock(&nlk->pg_vec_lock);
-       return 0;
+       return err;
 }
 
 static void netlink_frame_flush_dcache(const struct nl_mmap_hdr *hdr)
@@ -747,7 +747,7 @@ static void netlink_skb_destructor(struct sk_buff *skb)
                atomic_dec(&ring->pending);
                sock_put(sk);
 
-               skb->data = NULL;
+               skb->head = NULL;
        }
 #endif
        if (skb->sk != NULL)
index fb799de..a76f453 100644 (file)
@@ -5,7 +5,6 @@
 obj-$(CONFIG_NFC) += nfc.o
 obj-$(CONFIG_NFC_NCI) += nci/
 obj-$(CONFIG_NFC_HCI) += hci/
-#obj-$(CONFIG_NFC_LLCP) += llcp/
 
 nfc-objs := core.o netlink.o af_nfc.o rawsock.o llcp_core.o llcp_commands.o \
                llcp_sock.o
index 823463a..189e3c5 100644 (file)
@@ -231,14 +231,14 @@ override:
        }
        if (R_tab) {
                police->rate_present = true;
-               psched_ratecfg_precompute(&police->rate, R_tab->rate.rate);
+               psched_ratecfg_precompute(&police->rate, &R_tab->rate);
                qdisc_put_rtab(R_tab);
        } else {
                police->rate_present = false;
        }
        if (P_tab) {
                police->peak_present = true;
-               psched_ratecfg_precompute(&police->peak, P_tab->rate.rate);
+               psched_ratecfg_precompute(&police->peak, &P_tab->rate);
                qdisc_put_rtab(P_tab);
        } else {
                police->peak_present = false;
@@ -376,9 +376,9 @@ tcf_act_police_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
        };
 
        if (police->rate_present)
-               opt.rate.rate = psched_ratecfg_getrate(&police->rate);
+               psched_ratecfg_getrate(&opt.rate, &police->rate);
        if (police->peak_present)
-               opt.peakrate.rate = psched_ratecfg_getrate(&police->peak);
+               psched_ratecfg_getrate(&opt.peakrate, &police->peak);
        if (nla_put(skb, TCA_POLICE_TBF, sizeof(opt), &opt))
                goto nla_put_failure;
        if (police->tcfp_result &&
index 2b935e7..281c1bd 100644 (file)
@@ -291,17 +291,18 @@ struct qdisc_rate_table *qdisc_get_rtab(struct tc_ratespec *r, struct nlattr *ta
 {
        struct qdisc_rate_table *rtab;
 
+       if (tab == NULL || r->rate == 0 || r->cell_log == 0 ||
+           nla_len(tab) != TC_RTAB_SIZE)
+               return NULL;
+
        for (rtab = qdisc_rtab_list; rtab; rtab = rtab->next) {
-               if (memcmp(&rtab->rate, r, sizeof(struct tc_ratespec)) == 0) {
+               if (!memcmp(&rtab->rate, r, sizeof(struct tc_ratespec)) &&
+                   !memcmp(&rtab->data, nla_data(tab), 1024)) {
                        rtab->refcnt++;
                        return rtab;
                }
        }
 
-       if (tab == NULL || r->rate == 0 || r->cell_log == 0 ||
-           nla_len(tab) != TC_RTAB_SIZE)
-               return NULL;
-
        rtab = kmalloc(sizeof(*rtab), GFP_KERNEL);
        if (rtab) {
                rtab->rate = *r;
index eac7e0e..2022408 100644 (file)
@@ -898,14 +898,16 @@ void dev_shutdown(struct net_device *dev)
        WARN_ON(timer_pending(&dev->watchdog_timer));
 }
 
-void psched_ratecfg_precompute(struct psched_ratecfg *r, u32 rate)
+void psched_ratecfg_precompute(struct psched_ratecfg *r,
+                              const struct tc_ratespec *conf)
 {
        u64 factor;
        u64 mult;
        int shift;
 
-       r->rate_bps = (u64)rate << 3;
-       r->shift = 0;
+       memset(r, 0, sizeof(*r));
+       r->overhead = conf->overhead;
+       r->rate_bps = (u64)conf->rate << 3;
        r->mult = 1;
        /*
         * Calibrate mult, shift so that token counting is accurate
index 79b1876..adaedd7 100644 (file)
@@ -109,7 +109,7 @@ struct htb_class {
        } un;
        struct rb_node node[TC_HTB_NUMPRIO];    /* node for self or feed tree */
        struct rb_node pq_node; /* node for event queue */
-       psched_time_t pq_key;
+       s64     pq_key;
 
        int prio_activity;      /* for which prios are we active */
        enum htb_cmode cmode;   /* current mode of the class */
@@ -121,10 +121,10 @@ struct htb_class {
        /* token bucket parameters */
        struct psched_ratecfg rate;
        struct psched_ratecfg ceil;
-       s64 buffer, cbuffer;    /* token bucket depth/rate */
-       psched_tdiff_t mbuffer; /* max wait time */
-       s64 tokens, ctokens;    /* current number of tokens */
-       psched_time_t t_c;      /* checkpoint time */
+       s64     buffer, cbuffer;        /* token bucket depth/rate */
+       s64     mbuffer;                /* max wait time */
+       s64     tokens, ctokens;        /* current number of tokens */
+       s64     t_c;                    /* checkpoint time */
 };
 
 struct htb_sched {
@@ -141,15 +141,15 @@ struct htb_sched {
        struct rb_root wait_pq[TC_HTB_MAXDEPTH];
 
        /* time of nearest event per level (row) */
-       psched_time_t near_ev_cache[TC_HTB_MAXDEPTH];
+       s64     near_ev_cache[TC_HTB_MAXDEPTH];
 
        int defcls;             /* class where unclassified flows go to */
 
        /* filters for qdisc itself */
        struct tcf_proto *filter_list;
 
-       int rate2quantum;       /* quant = rate / rate2quantum */
-       psched_time_t now;      /* cached dequeue time */
+       int     rate2quantum;   /* quant = rate / rate2quantum */
+       s64     now;    /* cached dequeue time */
        struct qdisc_watchdog watchdog;
 
        /* non shaped skbs; let them go directly thru */
@@ -664,8 +664,8 @@ static void htb_charge_class(struct htb_sched *q, struct htb_class *cl,
  * next pending event (0 for no event in pq, q->now for too many events).
  * Note: Applied are events whose have cl->pq_key <= q->now.
  */
-static psched_time_t htb_do_events(struct htb_sched *q, int level,
-                                  unsigned long start)
+static s64 htb_do_events(struct htb_sched *q, int level,
+                        unsigned long start)
 {
        /* don't run for longer than 2 jiffies; 2 is used instead of
         * 1 to simplify things when jiffy is going to be incremented
@@ -857,7 +857,7 @@ static struct sk_buff *htb_dequeue(struct Qdisc *sch)
        struct sk_buff *skb;
        struct htb_sched *q = qdisc_priv(sch);
        int level;
-       psched_time_t next_event;
+       s64 next_event;
        unsigned long start_at;
 
        /* try to dequeue direct packets as high prio (!) to minimize cpu work */
@@ -880,7 +880,7 @@ ok:
        for (level = 0; level < TC_HTB_MAXDEPTH; level++) {
                /* common case optimization - skip event handler quickly */
                int m;
-               psched_time_t event;
+               s64 event;
 
                if (q->now >= q->near_ev_cache[level]) {
                        event = htb_do_events(q, level, start_at);
@@ -1090,9 +1090,9 @@ static int htb_dump_class(struct Qdisc *sch, unsigned long arg,
 
        memset(&opt, 0, sizeof(opt));
 
-       opt.rate.rate = psched_ratecfg_getrate(&cl->rate);
+       psched_ratecfg_getrate(&opt.rate, &cl->rate);
        opt.buffer = PSCHED_NS2TICKS(cl->buffer);
-       opt.ceil.rate = psched_ratecfg_getrate(&cl->ceil);
+       psched_ratecfg_getrate(&opt.ceil, &cl->ceil);
        opt.cbuffer = PSCHED_NS2TICKS(cl->cbuffer);
        opt.quantum = cl->quantum;
        opt.prio = cl->prio;
@@ -1117,8 +1117,8 @@ htb_dump_class_stats(struct Qdisc *sch, unsigned long arg, struct gnet_dump *d)
 
        if (!cl->level && cl->un.leaf.q)
                cl->qstats.qlen = cl->un.leaf.q->q.qlen;
-       cl->xstats.tokens = cl->tokens;
-       cl->xstats.ctokens = cl->ctokens;
+       cl->xstats.tokens = PSCHED_NS2TICKS(cl->tokens);
+       cl->xstats.ctokens = PSCHED_NS2TICKS(cl->ctokens);
 
        if (gnet_stats_copy_basic(d, &cl->bstats) < 0 ||
            gnet_stats_copy_rate_est(d, NULL, &cl->rate_est) < 0 ||
@@ -1200,7 +1200,7 @@ static void htb_parent_to_leaf(struct htb_sched *q, struct htb_class *cl,
        parent->un.leaf.q = new_q ? new_q : &noop_qdisc;
        parent->tokens = parent->buffer;
        parent->ctokens = parent->cbuffer;
-       parent->t_c = psched_get_time();
+       parent->t_c = ktime_to_ns(ktime_get());
        parent->cmode = HTB_CAN_SEND;
 }
 
@@ -1417,8 +1417,8 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
                /* set class to be in HTB_CAN_SEND state */
                cl->tokens = PSCHED_TICKS2NS(hopt->buffer);
                cl->ctokens = PSCHED_TICKS2NS(hopt->cbuffer);
-               cl->mbuffer = 60 * PSCHED_TICKS_PER_SEC;        /* 1min */
-               cl->t_c = psched_get_time();
+               cl->mbuffer = 60ULL * NSEC_PER_SEC;     /* 1min */
+               cl->t_c = ktime_to_ns(ktime_get());
                cl->cmode = HTB_CAN_SEND;
 
                /* attach to the hash list and parent's family */
@@ -1459,8 +1459,8 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
                        cl->prio = TC_HTB_NUMPRIO - 1;
        }
 
-       psched_ratecfg_precompute(&cl->rate, hopt->rate.rate);
-       psched_ratecfg_precompute(&cl->ceil, hopt->ceil.rate);
+       psched_ratecfg_precompute(&cl->rate, &hopt->rate);
+       psched_ratecfg_precompute(&cl->ceil, &hopt->ceil);
 
        cl->buffer = PSCHED_TICKS2NS(hopt->buffer);
        cl->cbuffer = PSCHED_TICKS2NS(hopt->buffer);
index c8388f3..e478d31 100644 (file)
@@ -298,9 +298,9 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt)
        q->tokens = q->buffer;
        q->ptokens = q->mtu;
 
-       psched_ratecfg_precompute(&q->rate, rtab->rate.rate);
+       psched_ratecfg_precompute(&q->rate, &rtab->rate);
        if (ptab) {
-               psched_ratecfg_precompute(&q->peak, ptab->rate.rate);
+               psched_ratecfg_precompute(&q->peak, &ptab->rate);
                q->peak_present = true;
        } else {
                q->peak_present = false;
@@ -350,9 +350,9 @@ static int tbf_dump(struct Qdisc *sch, struct sk_buff *skb)
                goto nla_put_failure;
 
        opt.limit = q->limit;
-       opt.rate.rate = psched_ratecfg_getrate(&q->rate);
+       psched_ratecfg_getrate(&opt.rate, &q->rate);
        if (q->peak_present)
-               opt.peakrate.rate = psched_ratecfg_getrate(&q->peak);
+               psched_ratecfg_getrate(&opt.peakrate, &q->peak);
        else
                memset(&opt.peakrate, 0, sizeof(opt.peakrate));
        opt.mtu = PSCHED_NS2TICKS(q->mtu);
index f631c5f..6abb1ca 100644 (file)
@@ -4003,6 +4003,12 @@ SCTP_STATIC void sctp_destroy_sock(struct sock *sk)
 
        /* Release our hold on the endpoint. */
        sp = sctp_sk(sk);
+       /* This could happen during socket init, thus we bail out
+        * early, since the rest of the below is not setup either.
+        */
+       if (sp->ep == NULL)
+               return;
+
        if (sp->do_auto_asconf) {
                sp->do_auto_asconf = 0;
                list_del(&sp->auto_asconf_list);
index b416093..4ca1526 100644 (file)
@@ -1956,7 +1956,7 @@ struct used_address {
        unsigned int name_len;
 };
 
-static int __sys_sendmsg(struct socket *sock, struct msghdr __user *msg,
+static int ___sys_sendmsg(struct socket *sock, struct msghdr __user *msg,
                         struct msghdr *msg_sys, unsigned int flags,
                         struct used_address *used_address)
 {
@@ -2071,22 +2071,30 @@ out:
  *     BSD sendmsg interface
  */
 
-SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned int, flags)
+long __sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags)
 {
        int fput_needed, err;
        struct msghdr msg_sys;
-       struct socket *sock = sockfd_lookup_light(fd, &err, &fput_needed);
+       struct socket *sock;
 
+       sock = sockfd_lookup_light(fd, &err, &fput_needed);
        if (!sock)
                goto out;
 
-       err = __sys_sendmsg(sock, msg, &msg_sys, flags, NULL);
+       err = ___sys_sendmsg(sock, msg, &msg_sys, flags, NULL);
 
        fput_light(sock->file, fput_needed);
 out:
        return err;
 }
 
+SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned int, flags)
+{
+       if (flags & MSG_CMSG_COMPAT)
+               return -EINVAL;
+       return __sys_sendmsg(fd, msg, flags);
+}
+
 /*
  *     Linux sendmmsg interface
  */
@@ -2117,15 +2125,16 @@ int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
 
        while (datagrams < vlen) {
                if (MSG_CMSG_COMPAT & flags) {
-                       err = __sys_sendmsg(sock, (struct msghdr __user *)compat_entry,
-                                           &msg_sys, flags, &used_address);
+                       err = ___sys_sendmsg(sock, (struct msghdr __user *)compat_entry,
+                                            &msg_sys, flags, &used_address);
                        if (err < 0)
                                break;
                        err = __put_user(err, &compat_entry->msg_len);
                        ++compat_entry;
                } else {
-                       err = __sys_sendmsg(sock, (struct msghdr __user *)entry,
-                                           &msg_sys, flags, &used_address);
+                       err = ___sys_sendmsg(sock,
+                                            (struct msghdr __user *)entry,
+                                            &msg_sys, flags, &used_address);
                        if (err < 0)
                                break;
                        err = put_user(err, &entry->msg_len);
@@ -2149,10 +2158,12 @@ int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
 SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg,
                unsigned int, vlen, unsigned int, flags)
 {
+       if (flags & MSG_CMSG_COMPAT)
+               return -EINVAL;
        return __sys_sendmmsg(fd, mmsg, vlen, flags);
 }
 
-static int __sys_recvmsg(struct socket *sock, struct msghdr __user *msg,
+static int ___sys_recvmsg(struct socket *sock, struct msghdr __user *msg,
                         struct msghdr *msg_sys, unsigned int flags, int nosec)
 {
        struct compat_msghdr __user *msg_compat =
@@ -2244,23 +2255,31 @@ out:
  *     BSD recvmsg interface
  */
 
-SYSCALL_DEFINE3(recvmsg, int, fd, struct msghdr __user *, msg,
-               unsigned int, flags)
+long __sys_recvmsg(int fd, struct msghdr __user *msg, unsigned flags)
 {
        int fput_needed, err;
        struct msghdr msg_sys;
-       struct socket *sock = sockfd_lookup_light(fd, &err, &fput_needed);
+       struct socket *sock;
 
+       sock = sockfd_lookup_light(fd, &err, &fput_needed);
        if (!sock)
                goto out;
 
-       err = __sys_recvmsg(sock, msg, &msg_sys, flags, 0);
+       err = ___sys_recvmsg(sock, msg, &msg_sys, flags, 0);
 
        fput_light(sock->file, fput_needed);
 out:
        return err;
 }
 
+SYSCALL_DEFINE3(recvmsg, int, fd, struct msghdr __user *, msg,
+               unsigned int, flags)
+{
+       if (flags & MSG_CMSG_COMPAT)
+               return -EINVAL;
+       return __sys_recvmsg(fd, msg, flags);
+}
+
 /*
  *     Linux recvmmsg interface
  */
@@ -2298,17 +2317,18 @@ int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
                 * No need to ask LSM for more than the first datagram.
                 */
                if (MSG_CMSG_COMPAT & flags) {
-                       err = __sys_recvmsg(sock, (struct msghdr __user *)compat_entry,
-                                           &msg_sys, flags & ~MSG_WAITFORONE,
-                                           datagrams);
+                       err = ___sys_recvmsg(sock, (struct msghdr __user *)compat_entry,
+                                            &msg_sys, flags & ~MSG_WAITFORONE,
+                                            datagrams);
                        if (err < 0)
                                break;
                        err = __put_user(err, &compat_entry->msg_len);
                        ++compat_entry;
                } else {
-                       err = __sys_recvmsg(sock, (struct msghdr __user *)entry,
-                                           &msg_sys, flags & ~MSG_WAITFORONE,
-                                           datagrams);
+                       err = ___sys_recvmsg(sock,
+                                            (struct msghdr __user *)entry,
+                                            &msg_sys, flags & ~MSG_WAITFORONE,
+                                            datagrams);
                        if (err < 0)
                                break;
                        err = put_user(err, &entry->msg_len);
@@ -2375,6 +2395,9 @@ SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg,
        int datagrams;
        struct timespec timeout_sys;
 
+       if (flags & MSG_CMSG_COMPAT)
+               return -EINVAL;
+
        if (!timeout)
                return __sys_recvmmsg(fd, mmsg, vlen, flags, NULL);
 
@@ -2412,7 +2435,7 @@ static const unsigned char nargs[21] = {
 
 SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)
 {
-       unsigned long a[6];
+       unsigned long a[AUDITSC_ARGS];
        unsigned long a0, a1;
        int err;
        unsigned int len;
@@ -2428,7 +2451,9 @@ SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)
        if (copy_from_user(a, args, len))
                return -EFAULT;
 
-       audit_socketcall(nargs[call] / sizeof(unsigned long), a);
+       err = audit_socketcall(nargs[call] / sizeof(unsigned long), a);
+       if (err)
+               return err;
 
        a0 = a[0];
        a1 = a[1];
index 7da6b45..fc2f78d 100644 (file)
@@ -52,6 +52,8 @@
 #include <linux/sunrpc/gss_api.h>
 #include <asm/uaccess.h>
 
+#include "../netns.h"
+
 static const struct rpc_authops authgss_ops;
 
 static const struct rpc_credops gss_credops;
@@ -85,8 +87,6 @@ struct gss_auth {
 };
 
 /* pipe_version >= 0 if and only if someone has a pipe open. */
-static int pipe_version = -1;
-static atomic_t pipe_users = ATOMIC_INIT(0);
 static DEFINE_SPINLOCK(pipe_version_lock);
 static struct rpc_wait_queue pipe_version_rpc_waitqueue;
 static DECLARE_WAIT_QUEUE_HEAD(pipe_version_waitqueue);
@@ -266,24 +266,27 @@ struct gss_upcall_msg {
        char databuf[UPCALL_BUF_LEN];
 };
 
-static int get_pipe_version(void)
+static int get_pipe_version(struct net *net)
 {
+       struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
        int ret;
 
        spin_lock(&pipe_version_lock);
-       if (pipe_version >= 0) {
-               atomic_inc(&pipe_users);
-               ret = pipe_version;
+       if (sn->pipe_version >= 0) {
+               atomic_inc(&sn->pipe_users);
+               ret = sn->pipe_version;
        } else
                ret = -EAGAIN;
        spin_unlock(&pipe_version_lock);
        return ret;
 }
 
-static void put_pipe_version(void)
+static void put_pipe_version(struct net *net)
 {
-       if (atomic_dec_and_lock(&pipe_users, &pipe_version_lock)) {
-               pipe_version = -1;
+       struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
+
+       if (atomic_dec_and_lock(&sn->pipe_users, &pipe_version_lock)) {
+               sn->pipe_version = -1;
                spin_unlock(&pipe_version_lock);
        }
 }
@@ -291,9 +294,10 @@ static void put_pipe_version(void)
 static void
 gss_release_msg(struct gss_upcall_msg *gss_msg)
 {
+       struct net *net = rpc_net_ns(gss_msg->auth->client);
        if (!atomic_dec_and_test(&gss_msg->count))
                return;
-       put_pipe_version();
+       put_pipe_version(net);
        BUG_ON(!list_empty(&gss_msg->list));
        if (gss_msg->ctx != NULL)
                gss_put_ctx(gss_msg->ctx);
@@ -439,7 +443,10 @@ static void gss_encode_msg(struct gss_upcall_msg *gss_msg,
                                struct rpc_clnt *clnt,
                                const char *service_name)
 {
-       if (pipe_version == 0)
+       struct net *net = rpc_net_ns(clnt);
+       struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
+
+       if (sn->pipe_version == 0)
                gss_encode_v0_msg(gss_msg);
        else /* pipe_version == 1 */
                gss_encode_v1_msg(gss_msg, clnt, service_name);
@@ -455,7 +462,7 @@ gss_alloc_msg(struct gss_auth *gss_auth, struct rpc_clnt *clnt,
        gss_msg = kzalloc(sizeof(*gss_msg), GFP_NOFS);
        if (gss_msg == NULL)
                return ERR_PTR(-ENOMEM);
-       vers = get_pipe_version();
+       vers = get_pipe_version(rpc_net_ns(clnt));
        if (vers < 0) {
                kfree(gss_msg);
                return ERR_PTR(vers);
@@ -559,24 +566,34 @@ out:
 static inline int
 gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred)
 {
+       struct net *net = rpc_net_ns(gss_auth->client);
+       struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
        struct rpc_pipe *pipe;
        struct rpc_cred *cred = &gss_cred->gc_base;
        struct gss_upcall_msg *gss_msg;
+       unsigned long timeout;
        DEFINE_WAIT(wait);
-       int err = 0;
+       int err;
 
        dprintk("RPC:       %s for uid %u\n",
                __func__, from_kuid(&init_user_ns, cred->cr_uid));
 retry:
+       err = 0;
+       /* Default timeout is 15s unless we know that gssd is not running */
+       timeout = 15 * HZ;
+       if (!sn->gssd_running)
+               timeout = HZ >> 2;
        gss_msg = gss_setup_upcall(gss_auth->client, gss_auth, cred);
        if (PTR_ERR(gss_msg) == -EAGAIN) {
                err = wait_event_interruptible_timeout(pipe_version_waitqueue,
-                               pipe_version >= 0, 15*HZ);
-               if (pipe_version < 0) {
+                               sn->pipe_version >= 0, timeout);
+               if (sn->pipe_version < 0) {
+                       if (err == 0)
+                               sn->gssd_running = 0;
                        warn_gssd();
                        err = -EACCES;
                }
-               if (err)
+               if (err < 0)
                        goto out;
                goto retry;
        }
@@ -707,20 +724,22 @@ out:
 
 static int gss_pipe_open(struct inode *inode, int new_version)
 {
+       struct net *net = inode->i_sb->s_fs_info;
+       struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
        int ret = 0;
 
        spin_lock(&pipe_version_lock);
-       if (pipe_version < 0) {
+       if (sn->pipe_version < 0) {
                /* First open of any gss pipe determines the version: */
-               pipe_version = new_version;
+               sn->pipe_version = new_version;
                rpc_wake_up(&pipe_version_rpc_waitqueue);
                wake_up(&pipe_version_waitqueue);
-       } else if (pipe_version != new_version) {
+       } else if (sn->pipe_version != new_version) {
                /* Trying to open a pipe of a different version */
                ret = -EBUSY;
                goto out;
        }
-       atomic_inc(&pipe_users);
+       atomic_inc(&sn->pipe_users);
 out:
        spin_unlock(&pipe_version_lock);
        return ret;
@@ -740,6 +759,7 @@ static int gss_pipe_open_v1(struct inode *inode)
 static void
 gss_pipe_release(struct inode *inode)
 {
+       struct net *net = inode->i_sb->s_fs_info;
        struct rpc_pipe *pipe = RPC_I(inode)->pipe;
        struct gss_upcall_msg *gss_msg;
 
@@ -758,7 +778,7 @@ restart:
        }
        spin_unlock(&pipe->lock);
 
-       put_pipe_version();
+       put_pipe_version(net);
 }
 
 static void
index 5c4c61d..357f613 100644 (file)
 #include <linux/sunrpc/svcauth.h>
 #include "gss_rpc_xdr.h"
 
-static bool gssx_check_pointer(struct xdr_stream *xdr)
-{
-       __be32 *p;
-
-       p = xdr_reserve_space(xdr, 4);
-       if (unlikely(p == NULL))
-               return -ENOSPC;
-       return *p?true:false;
-}
-
 static int gssx_enc_bool(struct xdr_stream *xdr, int v)
 {
        __be32 *p;
@@ -264,25 +254,27 @@ static int gssx_dec_option_array(struct xdr_stream *xdr,
        if (unlikely(p == NULL))
                return -ENOSPC;
        count = be32_to_cpup(p++);
-       if (count != 0) {
-               /* we recognize only 1 currently: CREDS_VALUE */
-               oa->count = 1;
+       if (!count)
+               return 0;
 
-               oa->data = kmalloc(sizeof(struct gssx_option), GFP_KERNEL);
-               if (!oa->data)
-                       return -ENOMEM;
+       /* we recognize only 1 currently: CREDS_VALUE */
+       oa->count = 1;
 
-               creds = kmalloc(sizeof(struct svc_cred), GFP_KERNEL);
-               if (!creds) {
-                       kfree(oa->data);
-                       return -ENOMEM;
-               }
+       oa->data = kmalloc(sizeof(struct gssx_option), GFP_KERNEL);
+       if (!oa->data)
+               return -ENOMEM;
 
-               oa->data[0].option.data = CREDS_VALUE;
-               oa->data[0].option.len = sizeof(CREDS_VALUE);
-               oa->data[0].value.data = (void *)creds;
-               oa->data[0].value.len = 0;
+       creds = kmalloc(sizeof(struct svc_cred), GFP_KERNEL);
+       if (!creds) {
+               kfree(oa->data);
+               return -ENOMEM;
        }
+
+       oa->data[0].option.data = CREDS_VALUE;
+       oa->data[0].option.len = sizeof(CREDS_VALUE);
+       oa->data[0].value.data = (void *)creds;
+       oa->data[0].value.len = 0;
+
        for (i = 0; i < count; i++) {
                gssx_buffer dummy = { 0, NULL };
                u32 length;
@@ -800,6 +792,7 @@ int gssx_dec_accept_sec_context(struct rpc_rqst *rqstp,
                                struct xdr_stream *xdr,
                                struct gssx_res_accept_sec_context *res)
 {
+       u32 value_follows;
        int err;
 
        /* res->status */
@@ -808,7 +801,10 @@ int gssx_dec_accept_sec_context(struct rpc_rqst *rqstp,
                return err;
 
        /* res->context_handle */
-       if (gssx_check_pointer(xdr)) {
+       err = gssx_dec_bool(xdr, &value_follows);
+       if (err)
+               return err;
+       if (value_follows) {
                err = gssx_dec_ctx(xdr, res->context_handle);
                if (err)
                        return err;
@@ -817,7 +813,10 @@ int gssx_dec_accept_sec_context(struct rpc_rqst *rqstp,
        }
 
        /* res->output_token */
-       if (gssx_check_pointer(xdr)) {
+       err = gssx_dec_bool(xdr, &value_follows);
+       if (err)
+               return err;
+       if (value_follows) {
                err = gssx_dec_buffer(xdr, res->output_token);
                if (err)
                        return err;
@@ -826,7 +825,10 @@ int gssx_dec_accept_sec_context(struct rpc_rqst *rqstp,
        }
 
        /* res->delegated_cred_handle */
-       if (gssx_check_pointer(xdr)) {
+       err = gssx_dec_bool(xdr, &value_follows);
+       if (err)
+               return err;
+       if (value_follows) {
                /* we do not support upcall servers sending this data. */
                return -EINVAL;
        }
index 871c73c..29b4ba9 100644 (file)
@@ -1287,7 +1287,7 @@ static bool use_gss_proxy(struct net *net)
 
 #ifdef CONFIG_PROC_FS
 
-static bool set_gss_proxy(struct net *net, int type)
+static int set_gss_proxy(struct net *net, int type)
 {
        struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
        int ret = 0;
@@ -1317,10 +1317,12 @@ static inline bool gssp_ready(struct sunrpc_net *sn)
        return false;
 }
 
-static int wait_for_gss_proxy(struct net *net)
+static int wait_for_gss_proxy(struct net *net, struct file *file)
 {
        struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
 
+       if (file->f_flags & O_NONBLOCK && !gssp_ready(sn))
+               return -EAGAIN;
        return wait_event_interruptible(sn->gssp_wq, gssp_ready(sn));
 }
 
@@ -1362,7 +1364,7 @@ static ssize_t read_gssp(struct file *file, char __user *buf,
        size_t len;
        int ret;
 
-       ret = wait_for_gss_proxy(net);
+       ret = wait_for_gss_proxy(net, file);
        if (ret)
                return ret;
 
index 7111a4c..74d948f 100644 (file)
@@ -28,7 +28,11 @@ struct sunrpc_net {
        wait_queue_head_t gssp_wq;
        struct rpc_clnt *gssp_clnt;
        int use_gss_proxy;
+       int pipe_version;
+       atomic_t pipe_users;
        struct proc_dir_entry *use_gssp_proc;
+
+       unsigned int gssd_running;
 };
 
 extern int sunrpc_net_id;
index a9129f8..e7ce4b3 100644 (file)
@@ -216,11 +216,14 @@ rpc_destroy_inode(struct inode *inode)
 static int
 rpc_pipe_open(struct inode *inode, struct file *filp)
 {
+       struct net *net = inode->i_sb->s_fs_info;
+       struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
        struct rpc_pipe *pipe;
        int first_open;
        int res = -ENXIO;
 
        mutex_lock(&inode->i_mutex);
+       sn->gssd_running = 1;
        pipe = RPC_I(inode)->pipe;
        if (pipe == NULL)
                goto out;
@@ -1069,6 +1072,8 @@ void rpc_pipefs_init_net(struct net *net)
        struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
 
        mutex_init(&sn->pipefs_sb_lock);
+       sn->gssd_running = 1;
+       sn->pipe_version = -1;
 }
 
 /*
index f8529fc..5356b12 100644 (file)
@@ -324,11 +324,17 @@ EXPORT_SYMBOL_GPL(__rpc_wait_for_completion_task);
  * Note: If the task is ASYNC, and is being made runnable after sitting on an
  * rpc_wait_queue, this must be called with the queue spinlock held to protect
  * the wait queue operation.
+ * Note the ordering of rpc_test_and_set_running() and rpc_clear_queued(),
+ * which is needed to ensure that __rpc_execute() doesn't loop (due to the
+ * lockless RPC_IS_QUEUED() test) before we've had a chance to test
+ * the RPC_TASK_RUNNING flag.
  */
 static void rpc_make_runnable(struct rpc_task *task)
 {
+       bool need_wakeup = !rpc_test_and_set_running(task);
+
        rpc_clear_queued(task);
-       if (rpc_test_and_set_running(task))
+       if (!need_wakeup)
                return;
        if (RPC_IS_ASYNC(task)) {
                INIT_WORK(&task->u.tk_work, rpc_async_schedule);
index c3f9e1e..06bdf5a 100644 (file)
@@ -810,11 +810,15 @@ svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp)
                goto badcred;
        argv->iov_base = (void*)((__be32*)argv->iov_base + slen);       /* skip machname */
        argv->iov_len -= slen*4;
-
+       /*
+        * Note: we skip uid_valid()/gid_valid() checks here for
+        * backwards compatibility with clients that use -1 id's.
+        * Instead, -1 uid or gid is later mapped to the
+        * (export-specific) anonymous id by nfsd_setuser.
+        * Supplementary gid's will be left alone.
+        */
        cred->cr_uid = make_kuid(&init_user_ns, svc_getnl(argv)); /* uid */
        cred->cr_gid = make_kgid(&init_user_ns, svc_getnl(argv)); /* gid */
-       if (!uid_valid(cred->cr_uid) || !gid_valid(cred->cr_gid))
-               goto badcred;
        slen = svc_getnl(argv);                 /* gids length */
        if (slen > 16 || (len -= (slen + 2)*4) < 0)
                goto badcred;
@@ -823,8 +827,6 @@ svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp)
                return SVC_CLOSE;
        for (i = 0; i < slen; i++) {
                kgid_t kgid = make_kgid(&init_user_ns, svc_getnl(argv));
-               if (!gid_valid(kgid))
-                       goto badcred;
                GROUP_AT(cred->cr_group_info, i) = kgid;
        }
        if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) {
index 84c9ad7..73405e0 100644 (file)
@@ -638,17 +638,21 @@ int wiphy_register(struct wiphy *wiphy)
         * cfg80211_mutex lock
         */
        res = rfkill_register(rdev->rfkill);
-       if (res)
-               goto out_rm_dev;
+       if (res) {
+               device_del(&rdev->wiphy.dev);
+
+               mutex_lock(&cfg80211_mutex);
+               debugfs_remove_recursive(rdev->wiphy.debugfsdir);
+               list_del_rcu(&rdev->list);
+               wiphy_regulatory_deregister(wiphy);
+               mutex_unlock(&cfg80211_mutex);
+               return res;
+       }
 
        rtnl_lock();
        rdev->wiphy.registered = true;
        rtnl_unlock();
        return 0;
-
-out_rm_dev:
-       device_del(&rdev->wiphy.dev);
-       return res;
 }
 EXPORT_SYMBOL(wiphy_register);
 
@@ -866,7 +870,6 @@ void cfg80211_leave(struct cfg80211_registered_device *rdev,
 #endif
                __cfg80211_disconnect(rdev, dev,
                                      WLAN_REASON_DEAUTH_LEAVING, true);
-               cfg80211_mlme_down(rdev, dev);
                wdev_unlock(wdev);
                break;
        case NL80211_IFTYPE_MESH_POINT:
index afa2838..d5aed3b 100644 (file)
@@ -3411,7 +3411,7 @@ static int nl80211_send_station(struct sk_buff *msg, u32 portid, u32 seq,
                        (u32)sinfo->rx_bytes))
                goto nla_put_failure;
        if ((sinfo->filled & (STATION_INFO_TX_BYTES |
-                             NL80211_STA_INFO_TX_BYTES64)) &&
+                             STATION_INFO_TX_BYTES64)) &&
            nla_put_u32(msg, NL80211_STA_INFO_TX_BYTES,
                        (u32)sinfo->tx_bytes))
                goto nla_put_failure;
@@ -7577,6 +7577,8 @@ static int nl80211_send_wowlan_tcp(struct sk_buff *msg,
                    &tcp->payload_tok))
                return -ENOBUFS;
 
+       nla_nest_end(msg, nl_tcp);
+
        return 0;
 }
 
@@ -9970,6 +9972,7 @@ int nl80211_send_mgmt(struct cfg80211_registered_device *rdev,
        if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
            (netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
                                        netdev->ifindex)) ||
+           nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)) ||
            nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq) ||
            (sig_dbm &&
             nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm)) ||
@@ -10010,6 +10013,7 @@ void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie,
        if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
            (netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
                                   netdev->ifindex)) ||
+           nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)) ||
            nla_put(msg, NL80211_ATTR_FRAME, len, buf) ||
            nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie) ||
            (ack && nla_put_flag(msg, NL80211_ATTR_ACK)))
index a9dc5c7..3ed35c3 100644 (file)
@@ -231,6 +231,9 @@ void cfg80211_conn_work(struct work_struct *work)
        mutex_lock(&rdev->sched_scan_mtx);
 
        list_for_each_entry(wdev, &rdev->wdev_list, list) {
+               if (!wdev->netdev)
+                       continue;
+
                wdev_lock(wdev);
                if (!netif_running(wdev->netdev)) {
                        wdev_unlock(wdev);
@@ -961,7 +964,7 @@ int __cfg80211_disconnect(struct cfg80211_registered_device *rdev,
                /* was it connected by userspace SME? */
                if (!wdev->conn) {
                        cfg80211_mlme_down(rdev, dev);
-                       return 0;
+                       goto disconnect;
                }
 
                if (wdev->sme_state == CFG80211_SME_CONNECTING &&
@@ -987,6 +990,7 @@ int __cfg80211_disconnect(struct cfg80211_registered_device *rdev,
                        return err;
        }
 
+ disconnect:
        if (wdev->sme_state == CFG80211_SME_CONNECTED)
                __cfg80211_disconnected(dev, NULL, 0, 0, false);
        else if (wdev->sme_state == CFG80211_SME_CONNECTING)
index ecd4fce..5755bc1 100644 (file)
@@ -2441,6 +2441,7 @@ TRACE_EVENT(cfg80211_report_wowlan_wakeup,
        TP_STRUCT__entry(
                WIPHY_ENTRY
                WDEV_ENTRY
+               __field(bool, non_wireless)
                __field(bool, disconnect)
                __field(bool, magic_pkt)
                __field(bool, gtk_rekey_failure)
@@ -2449,20 +2450,22 @@ TRACE_EVENT(cfg80211_report_wowlan_wakeup,
                __field(bool, rfkill_release)
                __field(s32, pattern_idx)
                __field(u32, packet_len)
-               __dynamic_array(u8, packet, wakeup->packet_present_len)
+               __dynamic_array(u8, packet,
+                               wakeup ? wakeup->packet_present_len : 0)
        ),
        TP_fast_assign(
                WIPHY_ASSIGN;
                WDEV_ASSIGN;
-               __entry->disconnect = wakeup->disconnect;
-               __entry->magic_pkt = wakeup->magic_pkt;
-               __entry->gtk_rekey_failure = wakeup->gtk_rekey_failure;
-               __entry->eap_identity_req = wakeup->eap_identity_req;
-               __entry->four_way_handshake = wakeup->four_way_handshake;
-               __entry->rfkill_release = wakeup->rfkill_release;
-               __entry->pattern_idx = wakeup->pattern_idx;
-               __entry->packet_len = wakeup->packet_len;
-               if (wakeup->packet && wakeup->packet_present_len)
+               __entry->non_wireless = !wakeup;
+               __entry->disconnect = wakeup ? wakeup->disconnect : false;
+               __entry->magic_pkt = wakeup ? wakeup->magic_pkt : false;
+               __entry->gtk_rekey_failure = wakeup ? wakeup->gtk_rekey_failure : false;
+               __entry->eap_identity_req = wakeup ? wakeup->eap_identity_req : false;
+               __entry->four_way_handshake = wakeup ? wakeup->four_way_handshake : false;
+               __entry->rfkill_release = wakeup ? wakeup->rfkill_release : false;
+               __entry->pattern_idx = wakeup ? wakeup->pattern_idx : false;
+               __entry->packet_len = wakeup ? wakeup->packet_len : false;
+               if (wakeup && wakeup->packet && wakeup->packet_present_len)
                        memcpy(__get_dynamic_array(packet), wakeup->packet,
                               wakeup->packet_present_len);
        ),
index bcfda89..0cf003d 100644 (file)
@@ -64,6 +64,7 @@ static int xfrm_output_one(struct sk_buff *skb, int err)
 
                if (unlikely(x->km.state != XFRM_STATE_VALID)) {
                        XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTSTATEINVALID);
+                       err = -EINVAL;
                        goto error;
                }
 
index 23cea0f..ea970b8 100644 (file)
@@ -2557,11 +2557,12 @@ static void __xfrm_garbage_collect(struct net *net)
        }
 }
 
-static void xfrm_garbage_collect(struct net *net)
+void xfrm_garbage_collect(struct net *net)
 {
        flow_cache_flush();
        __xfrm_garbage_collect(net);
 }
+EXPORT_SYMBOL(xfrm_garbage_collect);
 
 static void xfrm_garbage_collect_deferred(struct net *net)
 {
index aa77874..3f565e4 100644 (file)
@@ -1681,6 +1681,8 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
 
 out:
        xfrm_pol_put(xp);
+       if (delete && err == 0)
+               xfrm_garbage_collect(net);
        return err;
 }
 
index 51bb3de..8337663 100644 (file)
@@ -264,7 +264,7 @@ $(obj)/%.dtb.S: $(obj)/%.dtb
 quiet_cmd_dtc = DTC     $@
 cmd_dtc = $(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \
        $(objtree)/scripts/dtc/dtc -O dtb -o $@ -b 0 \
-               -i $(srctree)/arch/$(SRCARCH)/boot/dts $(DTC_FLAGS) \
+               -i $(dir $<) $(DTC_FLAGS) \
                -d $(depfile).dtc $(dtc-tmp) ; \
        cat $(depfile).pre $(depfile).dtc > $(depfile)
 
index bb4d3de..a65ecbb 100755 (executable)
@@ -105,7 +105,7 @@ while [ "$1" != "" ] ; do
                ;;
        --refresh)
                ;;
-       --*-after)
+       --*-after|-E|-D|-M)
                checkarg "$1"
                A=$ARG
                checkarg "$2"
index 48d382e..38cd69c 100644 (file)
@@ -303,10 +303,11 @@ do_resize:
                                }
                }
 
-               if (i < max_choice ||
-                   key == KEY_UP || key == KEY_DOWN ||
-                   key == '-' || key == '+' ||
-                   key == KEY_PPAGE || key == KEY_NPAGE) {
+               if (item_count() != 0 &&
+                   (i < max_choice ||
+                    key == KEY_UP || key == KEY_DOWN ||
+                    key == '-' || key == '+' ||
+                    key == KEY_PPAGE || key == KEY_NPAGE)) {
                        /* Remove highligt of current item */
                        print_item(scroll + choice, choice, FALSE);
 
index 387dc8d..a69cbd7 100644 (file)
@@ -670,11 +670,12 @@ static void conf(struct menu *menu, struct menu *active_menu)
                                  active_menu, &s_scroll);
                if (res == 1 || res == KEY_ESC || res == -ERRDISPLAYTOOSMALL)
                        break;
-               if (!item_activate_selected())
-                       continue;
-               if (!item_tag())
-                       continue;
-
+               if (item_count() != 0) {
+                       if (!item_activate_selected())
+                               continue;
+                       if (!item_tag())
+                               continue;
+               }
                submenu = item_data();
                active_menu = item_data();
                if (submenu)
index b5c7d90..fd3f018 100644 (file)
@@ -146,11 +146,24 @@ struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *e
                        struct menu *menu = current_entry;
 
                        while ((menu = menu->parent) != NULL) {
+                               struct expr *dup_expr;
+
                                if (!menu->visibility)
                                        continue;
+                               /*
+                                * Do not add a reference to the
+                                * menu's visibility expression but
+                                * use a copy of it.  Otherwise the
+                                * expression reduction functions
+                                * will modify expressions that have
+                                * multiple references which can
+                                * cause unwanted side effects.
+                                */
+                               dup_expr = expr_copy(menu->visibility);
+
                                prop->visible.expr
                                        = expr_alloc_and(prop->visible.expr,
-                                                        menu->visibility);
+                                                        dup_expr);
                        }
                }
 
index 84a4060..a4f31c9 100644 (file)
@@ -63,7 +63,7 @@ binrpm-pkg: FORCE
        mv -f $(objtree)/.tmp_version $(objtree)/.version
 
        $(RPM) $(RPMOPTS) --define "_builddir $(objtree)" --target \
-               $(UTS_MACHINE) -bb $<
+               $(UTS_MACHINE) -bb $(objtree)/binkernel.spec
        rm binkernel.spec
 
 # Deb target
index 8ab2951..d030818 100644 (file)
@@ -316,6 +316,7 @@ int selinux_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx,
 
                memcpy(new_ctx, old_ctx, sizeof(*new_ctx));
                memcpy(new_ctx->ctx_str, old_ctx->ctx_str, new_ctx->ctx_len);
+               atomic_inc(&selinux_xfrm_refcount);
                *new_ctxp = new_ctx;
        }
        return 0;
@@ -326,6 +327,7 @@ int selinux_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx,
  */
 void selinux_xfrm_policy_free(struct xfrm_sec_ctx *ctx)
 {
+       atomic_dec(&selinux_xfrm_refcount);
        kfree(ctx);
 }
 
@@ -335,17 +337,13 @@ void selinux_xfrm_policy_free(struct xfrm_sec_ctx *ctx)
 int selinux_xfrm_policy_delete(struct xfrm_sec_ctx *ctx)
 {
        const struct task_security_struct *tsec = current_security();
-       int rc = 0;
 
-       if (ctx) {
-               rc = avc_has_perm(tsec->sid, ctx->ctx_sid,
-                                 SECCLASS_ASSOCIATION,
-                                 ASSOCIATION__SETCONTEXT, NULL);
-               if (rc == 0)
-                       atomic_dec(&selinux_xfrm_refcount);
-       }
+       if (!ctx)
+               return 0;
 
-       return rc;
+       return avc_has_perm(tsec->sid, ctx->ctx_sid,
+                           SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT,
+                           NULL);
 }
 
 /*
@@ -370,8 +368,8 @@ int selinux_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *uct
  */
 void selinux_xfrm_state_free(struct xfrm_state *x)
 {
-       struct xfrm_sec_ctx *ctx = x->security;
-       kfree(ctx);
+       atomic_dec(&selinux_xfrm_refcount);
+       kfree(x->security);
 }
 
  /*
@@ -381,17 +379,13 @@ int selinux_xfrm_state_delete(struct xfrm_state *x)
 {
        const struct task_security_struct *tsec = current_security();
        struct xfrm_sec_ctx *ctx = x->security;
-       int rc = 0;
 
-       if (ctx) {
-               rc = avc_has_perm(tsec->sid, ctx->ctx_sid,
-                                 SECCLASS_ASSOCIATION,
-                                 ASSOCIATION__SETCONTEXT, NULL);
-               if (rc == 0)
-                       atomic_dec(&selinux_xfrm_refcount);
-       }
+       if (!ctx)
+               return 0;
 
-       return rc;
+       return avc_has_perm(tsec->sid, ctx->ctx_sid,
+                           SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT,
+                           NULL);
 }
 
 /*
index 552b97a..61ab640 100644 (file)
@@ -113,6 +113,7 @@ MODULE_ALIAS("sound-layout-100");
 MODULE_ALIAS("aoa-device-id-14");
 MODULE_ALIAS("aoa-device-id-22");
 MODULE_ALIAS("aoa-device-id-35");
+MODULE_ALIAS("aoa-device-id-44");
 
 /* onyx with all but microphone connected */
 static struct codec_connection onyx_connections_nomic[] = {
@@ -361,6 +362,13 @@ static struct layout layouts[] = {
                .connections = tas_connections_nolineout,
          },
        },
+       /* PowerBook6,5 */
+       { .device_id = 44,
+         .codecs[0] = {
+               .name = "tas",
+               .connections = tas_connections_all,
+         },
+       },
        /* PowerBook6,7 */
        { .layout_id = 80,
          .codecs[0] = {
index 0106583..15e7613 100644 (file)
@@ -200,7 +200,8 @@ static int i2sbus_add_dev(struct macio_dev *macio,
                         * We probably cannot handle all device-id machines,
                         * so restrict to those we do handle for now.
                         */
-                       if (id && (*id == 22 || *id == 14 || *id == 35)) {
+                       if (id && (*id == 22 || *id == 14 || *id == 35 ||
+                                  *id == 44)) {
                                snprintf(dev->sound.modalias, 32,
                                         "aoa-device-id-%d", *id);
                                ok = 1;
index 51c4ba9..1a96402 100644 (file)
@@ -250,7 +250,7 @@ config MSND_FIFOSIZE
 menuconfig SOUND_OSS
        tristate "OSS sound modules"
        depends on ISA_DMA_API && VIRT_TO_BUS
-       depends on !ISA_DMA_SUPPORT_BROKEN
+       depends on !GENERIC_ISA_DMA_SUPPORT_BROKEN
        help
          OSS is the Open Sound System suite of sound card drivers.  They make
          sound programming easier since they provide a common API.  Say Y or
index ac079f9..4b1524a 100644 (file)
@@ -606,6 +606,10 @@ static bool is_active_nid(struct hda_codec *codec, hda_nid_t nid,
        return false;
 }
 
+/* check whether the NID is referred by any active paths */
+#define is_active_nid_for_any(codec, nid) \
+       is_active_nid(codec, nid, HDA_OUTPUT, 0)
+
 /* get the default amp value for the target state */
 static int get_amp_val_to_activate(struct hda_codec *codec, hda_nid_t nid,
                                   int dir, unsigned int caps, bool enable)
@@ -759,7 +763,8 @@ static void path_power_down_sync(struct hda_codec *codec, struct nid_path *path)
 
        for (i = 0; i < path->depth; i++) {
                hda_nid_t nid = path->path[i];
-               if (!snd_hda_check_power_state(codec, nid, AC_PWRST_D3)) {
+               if (!snd_hda_check_power_state(codec, nid, AC_PWRST_D3) &&
+                   !is_active_nid_for_any(codec, nid)) {
                        snd_hda_codec_write(codec, nid, 0,
                                            AC_VERB_SET_POWER_STATE,
                                            AC_PWRST_D3);
@@ -783,6 +788,8 @@ static void set_pin_eapd(struct hda_codec *codec, hda_nid_t pin, bool enable)
                return;
        if (codec->inv_eapd)
                enable = !enable;
+       if (spec->keep_eapd_on && !enable)
+               return;
        snd_hda_codec_update_cache(codec, pin, 0,
                                   AC_VERB_SET_EAPD_BTLENABLE,
                                   enable ? 0x02 : 0x00);
@@ -1933,17 +1940,7 @@ static int create_speaker_out_ctls(struct hda_codec *codec)
  * independent HP controls
  */
 
-/* update HP auto-mute state too */
-static void update_hp_automute_hook(struct hda_codec *codec)
-{
-       struct hda_gen_spec *spec = codec->spec;
-
-       if (spec->hp_automute_hook)
-               spec->hp_automute_hook(codec, NULL);
-       else
-               snd_hda_gen_hp_automute(codec, NULL);
-}
-
+static void call_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *jack);
 static int indep_hp_info(struct snd_kcontrol *kcontrol,
                         struct snd_ctl_elem_info *uinfo)
 {
@@ -2004,7 +2001,7 @@ static int indep_hp_put(struct snd_kcontrol *kcontrol,
                else
                        *dacp = spec->alt_dac_nid;
 
-               update_hp_automute_hook(codec);
+               call_hp_automute(codec, NULL);
                ret = 1;
        }
  unlock:
@@ -2300,7 +2297,7 @@ static void update_hp_mic(struct hda_codec *codec, int adc_mux, bool force)
                else
                        val = PIN_HP;
                set_pin_target(codec, pin, val, true);
-               update_hp_automute_hook(codec);
+               call_hp_automute(codec, NULL);
        }
 }
 
@@ -2709,7 +2706,7 @@ static int hp_mic_jack_mode_put(struct snd_kcontrol *kcontrol,
                        val = snd_hda_get_default_vref(codec, nid);
        }
        snd_hda_set_pin_ctl_cache(codec, nid, val);
-       update_hp_automute_hook(codec);
+       call_hp_automute(codec, NULL);
 
        return 1;
 }
@@ -3854,20 +3851,42 @@ void snd_hda_gen_mic_autoswitch(struct hda_codec *codec, struct hda_jack_tbl *ja
 }
 EXPORT_SYMBOL_HDA(snd_hda_gen_mic_autoswitch);
 
-/* update jack retasking */
-static void update_automute_all(struct hda_codec *codec)
+/* call appropriate hooks */
+static void call_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *jack)
 {
        struct hda_gen_spec *spec = codec->spec;
+       if (spec->hp_automute_hook)
+               spec->hp_automute_hook(codec, jack);
+       else
+               snd_hda_gen_hp_automute(codec, jack);
+}
 
-       update_hp_automute_hook(codec);
+static void call_line_automute(struct hda_codec *codec,
+                              struct hda_jack_tbl *jack)
+{
+       struct hda_gen_spec *spec = codec->spec;
        if (spec->line_automute_hook)
-               spec->line_automute_hook(codec, NULL);
+               spec->line_automute_hook(codec, jack);
        else
-               snd_hda_gen_line_automute(codec, NULL);
+               snd_hda_gen_line_automute(codec, jack);
+}
+
+static void call_mic_autoswitch(struct hda_codec *codec,
+                               struct hda_jack_tbl *jack)
+{
+       struct hda_gen_spec *spec = codec->spec;
        if (spec->mic_autoswitch_hook)
-               spec->mic_autoswitch_hook(codec, NULL);
+               spec->mic_autoswitch_hook(codec, jack);
        else
-               snd_hda_gen_mic_autoswitch(codec, NULL);
+               snd_hda_gen_mic_autoswitch(codec, jack);
+}
+
+/* update jack retasking */
+static void update_automute_all(struct hda_codec *codec)
+{
+       call_hp_automute(codec, NULL);
+       call_line_automute(codec, NULL);
+       call_mic_autoswitch(codec, NULL);
 }
 
 /*
@@ -4004,9 +4023,7 @@ static int check_auto_mute_availability(struct hda_codec *codec)
                snd_printdd("hda-codec: Enable HP auto-muting on NID 0x%x\n",
                            nid);
                snd_hda_jack_detect_enable_callback(codec, nid, HDA_GEN_HP_EVENT,
-                                                   spec->hp_automute_hook ?
-                                                   spec->hp_automute_hook :
-                                                   snd_hda_gen_hp_automute);
+                                                   call_hp_automute);
                spec->detect_hp = 1;
        }
 
@@ -4019,9 +4036,7 @@ static int check_auto_mute_availability(struct hda_codec *codec)
                                snd_printdd("hda-codec: Enable Line-Out auto-muting on NID 0x%x\n", nid);
                                snd_hda_jack_detect_enable_callback(codec, nid,
                                                                    HDA_GEN_FRONT_EVENT,
-                                                                   spec->line_automute_hook ?
-                                                                   spec->line_automute_hook :
-                                                                   snd_hda_gen_line_automute);
+                                                                   call_line_automute);
                                spec->detect_lo = 1;
                        }
                spec->automute_lo_possible = spec->detect_hp;
@@ -4063,9 +4078,7 @@ static bool auto_mic_check_imux(struct hda_codec *codec)
                snd_hda_jack_detect_enable_callback(codec,
                                                    spec->am_entry[i].pin,
                                                    HDA_GEN_MIC_EVENT,
-                                                   spec->mic_autoswitch_hook ?
-                                                   spec->mic_autoswitch_hook :
-                                                   snd_hda_gen_mic_autoswitch);
+                                                   call_mic_autoswitch);
        return true;
 }
 
@@ -4157,7 +4170,7 @@ static unsigned int snd_hda_gen_path_power_filter(struct hda_codec *codec,
                return power_state;
        if (get_wcaps_type(get_wcaps(codec, nid)) >= AC_WID_POWER)
                return power_state;
-       if (is_active_nid(codec, nid, HDA_OUTPUT, 0))
+       if (is_active_nid_for_any(codec, nid))
                return power_state;
        return AC_PWRST_D3;
 }
index 54e6651..7620031 100644 (file)
@@ -222,6 +222,7 @@ struct hda_gen_spec {
        unsigned int multi_cap_vol:1; /* allow multiple capture xxx volumes */
        unsigned int inv_dmic_split:1; /* inverted dmic w/a for conexant */
        unsigned int own_eapd_ctl:1; /* set EAPD by own function */
+       unsigned int keep_eapd_on:1; /* don't turn off EAPD automatically */
        unsigned int vmaster_mute_enum:1; /* add vmaster mute mode enum */
        unsigned int indep_hp:1; /* independent HP supported */
        unsigned int prefer_hp_amp:1; /* enable HP amp for speaker if any */
index 6bf47f7..02e22b4 100644 (file)
@@ -3482,6 +3482,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1028, 0x05c9, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x05ca, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x05cb, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x05de, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x05e9, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x05ea, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x05eb, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
@@ -3492,6 +3493,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1028, 0x05f4, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x05f5, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x05f6, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x05f8, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x0609, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2),
        SND_PCI_QUIRK(0x103c, 0x18e6, "HP", ALC269_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x1973, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1),
@@ -3529,6 +3532,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x17aa, 0x21fa, "Thinkpad X230", ALC269_FIXUP_LENOVO_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x21f3, "Thinkpad T430", ALC269_FIXUP_LENOVO_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x21fb, "Thinkpad T430s", ALC269_FIXUP_LENOVO_DOCK),
+       SND_PCI_QUIRK(0x17aa, 0x2208, "Thinkpad T431s", ALC269_FIXUP_LENOVO_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x2203, "Thinkpad X230 Tablet", ALC269_FIXUP_LENOVO_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K),
        SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD),
index e0dadcf..e524554 100644 (file)
@@ -136,6 +136,7 @@ static struct via_spec *via_new_spec(struct hda_codec *codec)
                spec->codec_type = VT1708S;
        spec->no_pin_power_ctl = 1;
        spec->gen.indep_hp = 1;
+       spec->gen.keep_eapd_on = 1;
        spec->gen.pcm_playback_hook = via_playback_pcm_hook;
        return spec;
 }
@@ -231,9 +232,14 @@ static void vt1708_update_hp_work(struct hda_codec *codec)
 
 static void set_widgets_power_state(struct hda_codec *codec)
 {
+#if 0 /* FIXME: the assumed connections don't match always with the
+       * actual routes by the generic parser, so better to disable
+       * the control for safety.
+       */
        struct via_spec *spec = codec->spec;
        if (spec->set_widgets_power_state)
                spec->set_widgets_power_state(codec);
+#endif
 }
 
 static void update_power_state(struct hda_codec *codec, hda_nid_t nid,
@@ -478,7 +484,9 @@ static int via_suspend(struct hda_codec *codec)
                /* Fix pop noise on headphones */
                int i;
                for (i = 0; i < spec->gen.autocfg.hp_outs; i++)
-                       snd_hda_set_pin_ctl(codec, spec->gen.autocfg.hp_pins[i], 0);
+                       snd_hda_codec_write(codec, spec->gen.autocfg.hp_pins[i],
+                                           0, AC_VERB_SET_PIN_WIDGET_CONTROL,
+                                           0x00);
        }
 
        return 0;
index d59abe1..748e82d 100644 (file)
@@ -1341,7 +1341,8 @@ static int sis_chip_create(struct snd_card *card,
        if (rc)
                goto error_out;
 
-       if (pci_set_dma_mask(pci, DMA_BIT_MASK(30)) < 0) {
+       rc = pci_set_dma_mask(pci, DMA_BIT_MASK(30));
+       if (rc < 0) {
                dev_err(&pci->dev, "architecture does not support 30-bit PCI busmaster DMA");
                goto error_out_enabled;
        }
index 114f69a..306d0bc 100644 (file)
 
 /* AB8500_ADSLOTSELX */
 #define AB8500_ADSLOTSELX_AD_OUT1_TO_SLOT_ODD  0x00
-#define AB8500_ADSLOTSELX_AD_OUT2_TO_SLOT_ODD  0x01
-#define AB8500_ADSLOTSELX_AD_OUT3_TO_SLOT_ODD  0x02
-#define AB8500_ADSLOTSELX_AD_OUT4_TO_SLOT_ODD  0x03
-#define AB8500_ADSLOTSELX_AD_OUT5_TO_SLOT_ODD  0x04
-#define AB8500_ADSLOTSELX_AD_OUT6_TO_SLOT_ODD  0x05
-#define AB8500_ADSLOTSELX_AD_OUT7_TO_SLOT_ODD  0x06
-#define AB8500_ADSLOTSELX_AD_OUT8_TO_SLOT_ODD  0x07
-#define AB8500_ADSLOTSELX_ZEROES_TO_SLOT_ODD   0x08
-#define AB8500_ADSLOTSELX_TRISTATE_TO_SLOT_ODD 0x0F
+#define AB8500_ADSLOTSELX_AD_OUT2_TO_SLOT_ODD  0x10
+#define AB8500_ADSLOTSELX_AD_OUT3_TO_SLOT_ODD  0x20
+#define AB8500_ADSLOTSELX_AD_OUT4_TO_SLOT_ODD  0x30
+#define AB8500_ADSLOTSELX_AD_OUT5_TO_SLOT_ODD  0x40
+#define AB8500_ADSLOTSELX_AD_OUT6_TO_SLOT_ODD  0x50
+#define AB8500_ADSLOTSELX_AD_OUT7_TO_SLOT_ODD  0x60
+#define AB8500_ADSLOTSELX_AD_OUT8_TO_SLOT_ODD  0x70
+#define AB8500_ADSLOTSELX_ZEROES_TO_SLOT_ODD   0x80
+#define AB8500_ADSLOTSELX_TRISTATE_TO_SLOT_ODD 0xF0
 #define AB8500_ADSLOTSELX_AD_OUT1_TO_SLOT_EVEN 0x00
-#define AB8500_ADSLOTSELX_AD_OUT2_TO_SLOT_EVEN 0x10
-#define AB8500_ADSLOTSELX_AD_OUT3_TO_SLOT_EVEN 0x20
-#define AB8500_ADSLOTSELX_AD_OUT4_TO_SLOT_EVEN 0x30
-#define AB8500_ADSLOTSELX_AD_OUT5_TO_SLOT_EVEN 0x40
-#define AB8500_ADSLOTSELX_AD_OUT6_TO_SLOT_EVEN 0x50
-#define AB8500_ADSLOTSELX_AD_OUT7_TO_SLOT_EVEN 0x60
-#define AB8500_ADSLOTSELX_AD_OUT8_TO_SLOT_EVEN 0x70
-#define AB8500_ADSLOTSELX_ZEROES_TO_SLOT_EVEN  0x80
-#define AB8500_ADSLOTSELX_TRISTATE_TO_SLOT_EVEN        0xF0
+#define AB8500_ADSLOTSELX_AD_OUT2_TO_SLOT_EVEN 0x01
+#define AB8500_ADSLOTSELX_AD_OUT3_TO_SLOT_EVEN 0x02
+#define AB8500_ADSLOTSELX_AD_OUT4_TO_SLOT_EVEN 0x03
+#define AB8500_ADSLOTSELX_AD_OUT5_TO_SLOT_EVEN 0x04
+#define AB8500_ADSLOTSELX_AD_OUT6_TO_SLOT_EVEN 0x05
+#define AB8500_ADSLOTSELX_AD_OUT7_TO_SLOT_EVEN 0x06
+#define AB8500_ADSLOTSELX_AD_OUT8_TO_SLOT_EVEN 0x07
+#define AB8500_ADSLOTSELX_ZEROES_TO_SLOT_EVEN  0x08
+#define AB8500_ADSLOTSELX_TRISTATE_TO_SLOT_EVEN        0x0F
 #define AB8500_ADSLOTSELX_EVEN_SHIFT           0
 #define AB8500_ADSLOTSELX_ODD_SHIFT            4
 
index 0f6f481..030f53c 100644 (file)
@@ -86,7 +86,7 @@ static const struct reg_default cs42l52_reg_defaults[] = {
        { CS42L52_BEEP_VOL, 0x00 },     /* r1D Beep Volume off Time */
        { CS42L52_BEEP_TONE_CTL, 0x00 },        /* r1E Beep Tone Cfg. */
        { CS42L52_TONE_CTL, 0x00 },     /* r1F Tone Ctl */
-       { CS42L52_MASTERA_VOL, 0x88 },  /* r20 Master A Volume */
+       { CS42L52_MASTERA_VOL, 0x00 },  /* r20 Master A Volume */
        { CS42L52_MASTERB_VOL, 0x00 },  /* r21 Master B Volume */
        { CS42L52_HPA_VOL, 0x00 },      /* r22 Headphone A Volume */
        { CS42L52_HPB_VOL, 0x00 },      /* r23 Headphone B Volume */
@@ -225,7 +225,7 @@ static const char * const mic_bias_level_text[] = {
 };
 
 static const struct soc_enum mic_bias_level_enum =
-       SOC_ENUM_SINGLE(CS42L52_IFACE_CTL1, 0,
+       SOC_ENUM_SINGLE(CS42L52_IFACE_CTL2, 0,
                        ARRAY_SIZE(mic_bias_level_text), mic_bias_level_text);
 
 static const char * const cs42l52_mic_text[] = { "Single", "Differential" };
@@ -413,7 +413,7 @@ static const struct snd_kcontrol_new cs42l52_snd_controls[] = {
        SOC_ENUM("Headphone Analog Gain", hp_gain_enum),
 
        SOC_DOUBLE_R_SX_TLV("Speaker Volume", CS42L52_SPKA_VOL,
-                             CS42L52_SPKB_VOL, 7, 0x1, 0xff, hl_tlv),
+                             CS42L52_SPKB_VOL, 0, 0x1, 0xff, hl_tlv),
 
        SOC_DOUBLE_R_SX_TLV("Bypass Volume", CS42L52_PASSTHRUA_VOL,
                              CS42L52_PASSTHRUB_VOL, 6, 0x18, 0x90, pga_tlv),
@@ -441,7 +441,7 @@ static const struct snd_kcontrol_new cs42l52_snd_controls[] = {
 
        SOC_DOUBLE_R_SX_TLV("PCM Mixer Volume",
                            CS42L52_PCMA_MIXER_VOL, CS42L52_PCMB_MIXER_VOL,
-                               6, 0x7f, 0x19, hl_tlv),
+                               0, 0x7f, 0x19, hl_tlv),
        SOC_DOUBLE_R("PCM Mixer Switch",
                     CS42L52_PCMA_MIXER_VOL, CS42L52_PCMB_MIXER_VOL, 7, 1, 1),
 
index 60985c0..4277012 100644 (file)
 #define CS42L52_PB_CTL1_INV_PCMA               (1 << 2)
 #define CS42L52_PB_CTL1_MSTB_MUTE              (1 << 1)
 #define CS42L52_PB_CTL1_MSTA_MUTE              (1 << 0)
-#define CS42L52_PB_CTL1_MUTE_MASK              0xFFFD
+#define CS42L52_PB_CTL1_MUTE_MASK              0x03
 #define CS42L52_PB_CTL1_MUTE                   3
 #define CS42L52_PB_CTL1_UNMUTE                 0
 
index 41230ad..4a6f1da 100644 (file)
@@ -1488,17 +1488,17 @@ static int da7213_probe(struct snd_soc_codec *codec)
                                     DA7213_DMIC_DATA_SEL_SHIFT);
                        break;
                }
-               switch (pdata->dmic_data_sel) {
+               switch (pdata->dmic_samplephase) {
                case DA7213_DMIC_SAMPLE_ON_CLKEDGE:
                case DA7213_DMIC_SAMPLE_BETWEEN_CLKEDGE:
-                       dmic_cfg |= (pdata->dmic_data_sel <<
+                       dmic_cfg |= (pdata->dmic_samplephase <<
                                     DA7213_DMIC_SAMPLEPHASE_SHIFT);
                        break;
                }
-               switch (pdata->dmic_data_sel) {
+               switch (pdata->dmic_clk_rate) {
                case DA7213_DMIC_CLK_3_0MHZ:
                case DA7213_DMIC_CLK_1_5MHZ:
-                       dmic_cfg |= (pdata->dmic_data_sel <<
+                       dmic_cfg |= (pdata->dmic_clk_rate <<
                                     DA7213_DMIC_CLK_RATE_SHIFT);
                        break;
                }
index ce0d364..8d14a76 100644 (file)
@@ -2233,7 +2233,7 @@ static int max98090_probe(struct snd_soc_codec *codec)
        dev_dbg(codec->dev, "irq = %d\n", max98090->irq);
 
        ret = request_threaded_irq(max98090->irq, NULL,
-               max98090_interrupt, IRQF_TRIGGER_FALLING,
+               max98090_interrupt, IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
                "max98090_interrupt", codec);
        if (ret < 0) {
                dev_err(codec->dev, "request_irq failed: %d\n",
index 8df2b6e..370af0c 100644 (file)
@@ -667,6 +667,7 @@ static int wm0010_boot(struct snd_soc_codec *codec)
                /* On wm0010 only the CLKCTRL1 value is used */
                pll_rec.clkctrl1 = wm0010->pll_clkctrl1;
 
+               ret = -ENOMEM;
                len = pll_rec.length + 8;
                out = kzalloc(len, GFP_KERNEL);
                if (!out) {
index 731884e..ba38f06 100644 (file)
@@ -190,7 +190,7 @@ ARIZONA_MIXER_CONTROLS("DSP2R", ARIZONA_DSP2RMIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("DSP3L", ARIZONA_DSP3LMIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("DSP3R", ARIZONA_DSP3RMIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("DSP4L", ARIZONA_DSP4LMIX_INPUT_1_SOURCE),
-ARIZONA_MIXER_CONTROLS("DSP5R", ARIZONA_DSP4RMIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("DSP4R", ARIZONA_DSP4RMIX_INPUT_1_SOURCE),
 
 ARIZONA_MIXER_CONTROLS("Mic", ARIZONA_MICMIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("Noise", ARIZONA_NOISEMIX_INPUT_1_SOURCE),
@@ -976,6 +976,8 @@ static int wm5110_codec_probe(struct snd_soc_codec *codec)
        if (ret != 0)
                return ret;
 
+       arizona_init_spk(codec);
+
        snd_soc_dapm_disable_pin(&codec->dapm, "HAPTICS");
 
        priv->core.arizona->dapm = &codec->dapm;
index 1eb152c..dfd997a 100644 (file)
@@ -383,6 +383,8 @@ static int wm8994_get_drc_enum(struct snd_kcontrol *kcontrol,
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
        int drc = wm8994_get_drc(kcontrol->id.name);
 
+       if (drc < 0)
+               return drc;
        ucontrol->value.enumerated.item[0] = wm8994->drc_cfg[drc];
 
        return 0;
@@ -488,6 +490,9 @@ static int wm8994_get_retune_mobile_enum(struct snd_kcontrol *kcontrol,
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
        int block = wm8994_get_retune_mobile_block(kcontrol->id.name);
 
+       if (block < 0)
+               return block;
+
        ucontrol->value.enumerated.item[0] = wm8994->retune_mobile_cfg[block];
 
        return 0;
@@ -1031,7 +1036,7 @@ static int aif1clk_ev(struct snd_soc_dapm_widget *w,
 {
        struct snd_soc_codec *codec = w->codec;
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
-       struct wm8994 *control = codec->control_data;
+       struct wm8994 *control = wm8994->wm8994;
        int mask = WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA;
        int i;
        int dac;
@@ -3833,6 +3838,11 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data)
                        dev_dbg(codec->dev, "Ignoring removed jack\n");
                        return IRQ_HANDLED;
                }
+       } else if (!(reg & WM8958_MICD_STS)) {
+               snd_soc_jack_report(wm8994->micdet[0].jack, 0,
+                                   SND_JACK_MECHANICAL | SND_JACK_HEADSET |
+                                   wm8994->btn_mask);
+               goto out;
        }
 
        if (wm8994->mic_detecting)
index 56ecfc7..81490fe 100644 (file)
@@ -631,7 +631,8 @@ static int davinci_config_channel_size(struct davinci_audio_dev *dev,
                                       int word_length)
 {
        u32 fmt;
-       u32 rotate = (word_length / 4) & 0x7;
+       u32 tx_rotate = (word_length / 4) & 0x7;
+       u32 rx_rotate = (32 - word_length) / 4;
        u32 mask = (1ULL << word_length) - 1;
 
        /*
@@ -655,9 +656,9 @@ static int davinci_config_channel_size(struct davinci_audio_dev *dev,
                mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMT_REG,
                                TXSSZ(fmt), TXSSZ(0x0F));
                mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMT_REG,
-                               TXROT(rotate), TXROT(7));
+                               TXROT(tx_rotate), TXROT(7));
                mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMT_REG,
-                               RXROT(rotate), RXROT(7));
+                               RXROT(rx_rotate), RXROT(7));
                mcasp_set_reg(dev->base + DAVINCI_MCASP_RXMASK_REG,
                                mask);
        }
index 902fab0..c6fa03e 100644 (file)
@@ -540,11 +540,6 @@ static int imx_ssi_probe(struct platform_device *pdev)
        clk_prepare_enable(ssi->clk);
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               ret = -ENODEV;
-               goto failed_get_resource;
-       }
-
        ssi->base = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(ssi->base)) {
                ret = PTR_ERR(ssi->base);
@@ -633,7 +628,6 @@ failed_pdev_fiq_alloc:
        snd_soc_unregister_component(&pdev->dev);
 failed_register:
        release_mem_region(res->start, resource_size(res));
-failed_get_resource:
        clk_disable_unprepare(ssi->clk);
 failed_clk:
 
index befe68f..4c9dad3 100644 (file)
@@ -471,11 +471,6 @@ static int kirkwood_i2s_dev_probe(struct platform_device *pdev)
        dev_set_drvdata(&pdev->dev, priv);
 
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!mem) {
-               dev_err(&pdev->dev, "platform_get_resource failed\n");
-               return -ENXIO;
-       }
-
        priv->io = devm_ioremap_resource(&pdev->dev, mem);
        if (IS_ERR(priv->io))
                return PTR_ERR(priv->io);
index 3853f7e..06a8000 100644 (file)
@@ -220,8 +220,12 @@ static int soc_compr_set_params(struct snd_compr_stream *cstream,
                        goto err;
        }
 
-       snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK,
-                               SND_SOC_DAPM_STREAM_START);
+       if (cstream->direction == SND_COMPRESS_PLAYBACK)
+               snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK,
+                                       SND_SOC_DAPM_STREAM_START);
+       else
+               snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_CAPTURE,
+                                       SND_SOC_DAPM_STREAM_START);
 
        /* cancel any delayed stream shutdown that is pending */
        rtd->pop_wait = 0;
index a1d9b07..b9defcd 100644 (file)
@@ -42,8 +42,8 @@ static const u8 ep_w_max_packet_size[] = {
        0x94, 0x01, 0x5c, 0x02  /* alt 3: 404 EP2 and 604 EP6 (25 fpp) */
 };
 
-static const u8 known_fw_versions[][4] = {
-       { 0x03, 0x01, 0x0b, 0x00 }
+static const u8 known_fw_versions[][2] = {
+       { 0x03, 0x01 }
 };
 
 struct ihex_record {
@@ -343,7 +343,7 @@ static int usb6fire_fw_check(u8 *version)
        int i;
 
        for (i = 0; i < ARRAY_SIZE(known_fw_versions); i++)
-               if (!memcmp(version, known_fw_versions + i, 4))
+               if (!memcmp(version, known_fw_versions + i, 2))
                        return 0;
 
        snd_printk(KERN_ERR PREFIX "invalid fimware version in device: %*ph. "
index ca4739c..e5c7f9f 100644 (file)
@@ -886,6 +886,7 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval,
        case USB_ID(0x046d, 0x0808):
        case USB_ID(0x046d, 0x0809):
        case USB_ID(0x046d, 0x081d): /* HD Webcam c510 */
+       case USB_ID(0x046d, 0x0825): /* HD Webcam c270 */
        case USB_ID(0x046d, 0x0991):
        /* Most audio usb devices lie about volume resolution.
         * Most Logitech webcams have res = 384.
index 135c768..5f761ab 100644 (file)
@@ -116,21 +116,22 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s
 }
 
 static void proc_dump_ep_status(struct snd_usb_substream *subs,
-                               struct snd_usb_endpoint *ep,
+                               struct snd_usb_endpoint *data_ep,
+                               struct snd_usb_endpoint *sync_ep,
                                struct snd_info_buffer *buffer)
 {
-       if (!ep)
+       if (!data_ep)
                return;
-       snd_iprintf(buffer, "    Packet Size = %d\n", ep->curpacksize);
+       snd_iprintf(buffer, "    Packet Size = %d\n", data_ep->curpacksize);
        snd_iprintf(buffer, "    Momentary freq = %u Hz (%#x.%04x)\n",
                    subs->speed == USB_SPEED_FULL
-                   ? get_full_speed_hz(ep->freqm)
-                   : get_high_speed_hz(ep->freqm),
-                   ep->freqm >> 16, ep->freqm & 0xffff);
-       if (ep->freqshift != INT_MIN) {
-               int res = 16 - ep->freqshift;
+                   ? get_full_speed_hz(data_ep->freqm)
+                   : get_high_speed_hz(data_ep->freqm),
+                   data_ep->freqm >> 16, data_ep->freqm & 0xffff);
+       if (sync_ep && data_ep->freqshift != INT_MIN) {
+               int res = 16 - data_ep->freqshift;
                snd_iprintf(buffer, "    Feedback Format = %d.%d\n",
-                           (ep->syncmaxsize > 3 ? 32 : 24) - res, res);
+                           (sync_ep->syncmaxsize > 3 ? 32 : 24) - res, res);
        }
 }
 
@@ -140,8 +141,7 @@ static void proc_dump_substream_status(struct snd_usb_substream *subs, struct sn
                snd_iprintf(buffer, "  Status: Running\n");
                snd_iprintf(buffer, "    Interface = %d\n", subs->interface);
                snd_iprintf(buffer, "    Altset = %d\n", subs->altset_idx);
-               proc_dump_ep_status(subs, subs->data_endpoint, buffer);
-               proc_dump_ep_status(subs, subs->sync_endpoint, buffer);
+               proc_dump_ep_status(subs, subs->data_endpoint, subs->sync_endpoint, buffer);
        } else {
                snd_iprintf(buffer, "  Status: Stop\n");
        }
index 7f1722f..8b75bcf 100644 (file)
        .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL
 },
 {
-       USB_DEVICE(0x046d, 0x0990),
+       .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
+                      USB_DEVICE_ID_MATCH_INT_CLASS |
+                      USB_DEVICE_ID_MATCH_INT_SUBCLASS,
+       .idVendor = 0x046d,
+       .idProduct = 0x0990,
+       .bInterfaceClass = USB_CLASS_AUDIO,
+       .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL,
        .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
                .vendor_name = "Logitech, Inc.",
                .product_name = "QuickCam Pro 9000",
@@ -1792,7 +1798,11 @@ YAMAHA_DEVICE(0x7010, "UB99"),
        USB_DEVICE_VENDOR_SPEC(0x0582, 0x0108),
        .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
                .ifnum = 0,
-               .type = QUIRK_MIDI_STANDARD_INTERFACE
+               .type = QUIRK_MIDI_FIXED_ENDPOINT,
+               .data = & (const struct snd_usb_midi_endpoint_info) {
+                       .out_cables = 0x0007,
+                       .in_cables  = 0x0007
+               }
        }
 },
 {
index a4ffc95..b574059 100755 (executable)
@@ -15,35 +15,38 @@ kallsyms = []
 
 def get_kallsyms_table():
        global kallsyms
+
        try:
                f = open("/proc/kallsyms", "r")
-               linecount = 0
-               for line in f:
-                       linecount = linecount+1
-               f.seek(0)
        except:
                return
 
-
-       j = 0
        for line in f:
                loc = int(line.split()[0], 16)
                name = line.split()[2]
-               j = j +1
-               if ((j % 100) == 0):
-                       print "\r" + str(j) + "/" + str(linecount),
-               kallsyms.append({ 'loc': loc, 'name' : name})
-
-       print "\r" + str(j) + "/" + str(linecount)
+               kallsyms.append((loc, name))
        kallsyms.sort()
-       return
 
 def get_sym(sloc):
        loc = int(sloc)
-       for i in kallsyms:
-               if (i['loc'] >= loc):
-                       return (i['name'], i['loc']-loc)
-       return (None, 0)
+
+       # Invariant: kallsyms[i][0] <= loc for all 0 <= i <= start
+       #            kallsyms[i][0] > loc for all end <= i < len(kallsyms)
+       start, end = -1, len(kallsyms)
+       while end != start + 1:
+               pivot = (start + end) // 2
+               if loc < kallsyms[pivot][0]:
+                       end = pivot
+               else:
+                       start = pivot
+
+       # Now (start == -1 or kallsyms[start][0] <= loc)
+       # and (start == len(kallsyms) - 1 or loc < kallsyms[start + 1][0])
+       if start >= 0:
+               symloc, name = kallsyms[start]
+               return (name, loc - symloc)
+       else:
+               return (None, 0)
 
 def print_drop_table():
        print "%25s %25s %25s" % ("LOCATION", "OFFSET", "COUNT")
@@ -64,7 +67,7 @@ def trace_end():
 
 # called from perf, when it finds a correspoinding event
 def skb__kfree_skb(name, context, cpu, sec, nsec, pid, comm,
-                       skbaddr, protocol, location):
+                  skbaddr, location, protocol):
        slocation = str(location)
        try:
                drop_log[slocation] = drop_log[slocation] + 1
index 321e066..9e9d348 100644 (file)
@@ -46,6 +46,7 @@ unsigned int skip_c0;
 unsigned int skip_c1;
 unsigned int do_nhm_cstates;
 unsigned int do_snb_cstates;
+unsigned int do_c8_c9_c10;
 unsigned int has_aperf;
 unsigned int has_epb;
 unsigned int units = 1000000000;       /* Ghz etc */
@@ -120,6 +121,9 @@ struct pkg_data {
        unsigned long long pc3;
        unsigned long long pc6;
        unsigned long long pc7;
+       unsigned long long pc8;
+       unsigned long long pc9;
+       unsigned long long pc10;
        unsigned int package_id;
        unsigned int energy_pkg;        /* MSR_PKG_ENERGY_STATUS */
        unsigned int energy_dram;       /* MSR_DRAM_ENERGY_STATUS */
@@ -282,6 +286,11 @@ void print_header(void)
                outp += sprintf(outp, "   %%pc6");
        if (do_snb_cstates)
                outp += sprintf(outp, "   %%pc7");
+       if (do_c8_c9_c10) {
+               outp += sprintf(outp, "   %%pc8");
+               outp += sprintf(outp, "   %%pc9");
+               outp += sprintf(outp, "  %%pc10");
+       }
 
        if (do_rapl & RAPL_PKG)
                outp += sprintf(outp, "  Pkg_W");
@@ -336,6 +345,9 @@ int dump_counters(struct thread_data *t, struct core_data *c,
                fprintf(stderr, "pc3: %016llX\n", p->pc3);
                fprintf(stderr, "pc6: %016llX\n", p->pc6);
                fprintf(stderr, "pc7: %016llX\n", p->pc7);
+               fprintf(stderr, "pc8: %016llX\n", p->pc8);
+               fprintf(stderr, "pc9: %016llX\n", p->pc9);
+               fprintf(stderr, "pc10: %016llX\n", p->pc10);
                fprintf(stderr, "Joules PKG: %0X\n", p->energy_pkg);
                fprintf(stderr, "Joules COR: %0X\n", p->energy_cores);
                fprintf(stderr, "Joules GFX: %0X\n", p->energy_gfx);
@@ -493,6 +505,11 @@ int format_counters(struct thread_data *t, struct core_data *c,
                outp += sprintf(outp, " %6.2f", 100.0 * p->pc6/t->tsc);
        if (do_snb_cstates)
                outp += sprintf(outp, " %6.2f", 100.0 * p->pc7/t->tsc);
+       if (do_c8_c9_c10) {
+               outp += sprintf(outp, " %6.2f", 100.0 * p->pc8/t->tsc);
+               outp += sprintf(outp, " %6.2f", 100.0 * p->pc9/t->tsc);
+               outp += sprintf(outp, " %6.2f", 100.0 * p->pc10/t->tsc);
+       }
 
        /*
         * If measurement interval exceeds minimum RAPL Joule Counter range,
@@ -569,6 +586,9 @@ delta_package(struct pkg_data *new, struct pkg_data *old)
        old->pc3 = new->pc3 - old->pc3;
        old->pc6 = new->pc6 - old->pc6;
        old->pc7 = new->pc7 - old->pc7;
+       old->pc8 = new->pc8 - old->pc8;
+       old->pc9 = new->pc9 - old->pc9;
+       old->pc10 = new->pc10 - old->pc10;
        old->pkg_temp_c = new->pkg_temp_c;
 
        DELTA_WRAP32(new->energy_pkg, old->energy_pkg);
@@ -702,6 +722,9 @@ void clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data
        p->pc3 = 0;
        p->pc6 = 0;
        p->pc7 = 0;
+       p->pc8 = 0;
+       p->pc9 = 0;
+       p->pc10 = 0;
 
        p->energy_pkg = 0;
        p->energy_dram = 0;
@@ -740,6 +763,9 @@ int sum_counters(struct thread_data *t, struct core_data *c,
        average.packages.pc3 += p->pc3;
        average.packages.pc6 += p->pc6;
        average.packages.pc7 += p->pc7;
+       average.packages.pc8 += p->pc8;
+       average.packages.pc9 += p->pc9;
+       average.packages.pc10 += p->pc10;
 
        average.packages.energy_pkg += p->energy_pkg;
        average.packages.energy_dram += p->energy_dram;
@@ -781,6 +807,10 @@ void compute_average(struct thread_data *t, struct core_data *c,
        average.packages.pc3 /= topo.num_packages;
        average.packages.pc6 /= topo.num_packages;
        average.packages.pc7 /= topo.num_packages;
+
+       average.packages.pc8 /= topo.num_packages;
+       average.packages.pc9 /= topo.num_packages;
+       average.packages.pc10 /= topo.num_packages;
 }
 
 static unsigned long long rdtsc(void)
@@ -880,6 +910,14 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
                if (get_msr(cpu, MSR_PKG_C7_RESIDENCY, &p->pc7))
                        return -12;
        }
+       if (do_c8_c9_c10) {
+               if (get_msr(cpu, MSR_PKG_C8_RESIDENCY, &p->pc8))
+                       return -13;
+               if (get_msr(cpu, MSR_PKG_C9_RESIDENCY, &p->pc9))
+                       return -13;
+               if (get_msr(cpu, MSR_PKG_C10_RESIDENCY, &p->pc10))
+                       return -13;
+       }
        if (do_rapl & RAPL_PKG) {
                if (get_msr(cpu, MSR_PKG_ENERGY_STATUS, &msr))
                        return -13;
@@ -1762,6 +1800,19 @@ int is_snb(unsigned int family, unsigned int model)
        return 0;
 }
 
+int has_c8_c9_c10(unsigned int family, unsigned int model)
+{
+       if (!genuine_intel)
+               return 0;
+
+       switch (model) {
+       case 0x45:
+               return 1;
+       }
+       return 0;
+}
+
+
 double discover_bclk(unsigned int family, unsigned int model)
 {
        if (is_snb(family, model))
@@ -1918,6 +1969,7 @@ void check_cpuid()
        do_nhm_cstates = genuine_intel; /* all Intel w/ non-stop TSC have NHM counters */
        do_smi = do_nhm_cstates;
        do_snb_cstates = is_snb(family, model);
+       do_c8_c9_c10 = has_c8_c9_c10(family, model);
        bclk = discover_bclk(family, model);
 
        do_nehalem_turbo_ratio_limit = has_nehalem_turbo_ratio_limit(family, model);
@@ -2279,7 +2331,7 @@ int main(int argc, char **argv)
        cmdline(argc, argv);
 
        if (verbose)
-               fprintf(stderr, "turbostat v3.3 March 15, 2013"
+               fprintf(stderr, "turbostat v3.4 April 17, 2013"
                        " - Len Brown <lenb@kernel.org>\n");
 
        turbostat_init();
index d4abc59..0a63658 100644 (file)
@@ -6,7 +6,6 @@ TARGETS += memory-hotplug
 TARGETS += mqueue
 TARGETS += net
 TARGETS += ptrace
-TARGETS += soft-dirty
 TARGETS += vm
 
 all:
diff --git a/tools/testing/selftests/soft-dirty/Makefile b/tools/testing/selftests/soft-dirty/Makefile
deleted file mode 100644 (file)
index a9cdc82..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-CFLAGS += -iquote../../../../include/uapi -Wall
-soft-dirty: soft-dirty.c
-
-all: soft-dirty
-
-clean:
-       rm -f soft-dirty
-
-run_tests: all
-       @./soft-dirty || echo "soft-dirty selftests: [FAIL]"
diff --git a/tools/testing/selftests/soft-dirty/soft-dirty.c b/tools/testing/selftests/soft-dirty/soft-dirty.c
deleted file mode 100644 (file)
index aba4f87..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-#include <stdlib.h>
-#include <stdio.h>
-#include <sys/mman.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/types.h>
-
-typedef unsigned long long u64;
-
-#define PME_PRESENT    (1ULL << 63)
-#define PME_SOFT_DIRTY (1Ull << 55)
-
-#define PAGES_TO_TEST  3
-#ifndef PAGE_SIZE
-#define PAGE_SIZE      4096
-#endif
-
-static void get_pagemap2(char *mem, u64 *map)
-{
-       int fd;
-
-       fd = open("/proc/self/pagemap2", O_RDONLY);
-       if (fd < 0) {
-               perror("Can't open pagemap2");
-               exit(1);
-       }
-
-       lseek(fd, (unsigned long)mem / PAGE_SIZE * sizeof(u64), SEEK_SET);
-       read(fd, map, sizeof(u64) * PAGES_TO_TEST);
-       close(fd);
-}
-
-static inline char map_p(u64 map)
-{
-       return map & PME_PRESENT ? 'p' : '-';
-}
-
-static inline char map_sd(u64 map)
-{
-       return map & PME_SOFT_DIRTY ? 'd' : '-';
-}
-
-static int check_pte(int step, int page, u64 *map, u64 want)
-{
-       if ((map[page] & want) != want) {
-               printf("Step %d Page %d has %c%c, want %c%c\n",
-                               step, page,
-                               map_p(map[page]), map_sd(map[page]),
-                               map_p(want), map_sd(want));
-               return 1;
-       }
-
-       return 0;
-}
-
-static void clear_refs(void)
-{
-       int fd;
-       char *v = "4";
-
-       fd = open("/proc/self/clear_refs", O_WRONLY);
-       if (write(fd, v, 3) < 3) {
-               perror("Can't clear soft-dirty bit");
-               exit(1);
-       }
-       close(fd);
-}
-
-int main(void)
-{
-       char *mem, x;
-       u64 map[PAGES_TO_TEST];
-
-       mem = mmap(NULL, PAGES_TO_TEST * PAGE_SIZE,
-                       PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, 0, 0);
-
-       x = mem[0];
-       mem[2 * PAGE_SIZE] = 'c';
-       get_pagemap2(mem, map);
-
-       if (check_pte(1, 0, map, PME_PRESENT))
-               return 1;
-       if (check_pte(1, 1, map, 0))
-               return 1;
-       if (check_pte(1, 2, map, PME_PRESENT | PME_SOFT_DIRTY))
-               return 1;
-
-       clear_refs();
-       get_pagemap2(mem, map);
-
-       if (check_pte(2, 0, map, PME_PRESENT))
-               return 1;
-       if (check_pte(2, 1, map, 0))
-               return 1;
-       if (check_pte(2, 2, map, PME_PRESENT))
-               return 1;
-
-       mem[0] = 'a';
-       mem[PAGE_SIZE] = 'b';
-       x = mem[2 * PAGE_SIZE];
-       get_pagemap2(mem, map);
-
-       if (check_pte(3, 0, map, PME_PRESENT | PME_SOFT_DIRTY))
-               return 1;
-       if (check_pte(3, 1, map, PME_PRESENT | PME_SOFT_DIRTY))
-               return 1;
-       if (check_pte(3, 2, map, PME_PRESENT))
-               return 1;
-
-       (void)x; /* gcc warn */
-
-       printf("PASS\n");
-       return 0;
-}
index ae88b71..302681c 100644 (file)
@@ -3105,13 +3105,21 @@ int kvm_init(void *opaque, unsigned vcpu_size, unsigned vcpu_align,
        int r;
        int cpu;
 
-       r = kvm_irqfd_init();
-       if (r)
-               goto out_irqfd;
        r = kvm_arch_init(opaque);
        if (r)
                goto out_fail;
 
+       /*
+        * kvm_arch_init makes sure there's at most one caller
+        * for architectures that support multiple implementations,
+        * like intel and amd on x86.
+        * kvm_arch_init must be called before kvm_irqfd_init to avoid creating
+        * conflicts in case kvm is already setup for another implementation.
+        */
+       r = kvm_irqfd_init();
+       if (r)
+               goto out_irqfd;
+
        if (!zalloc_cpumask_var(&cpus_hardware_enabled, GFP_KERNEL)) {
                r = -ENOMEM;
                goto out_free_0;
@@ -3186,10 +3194,10 @@ out_free_1:
 out_free_0a:
        free_cpumask_var(cpus_hardware_enabled);
 out_free_0:
-       kvm_arch_exit();
-out_fail:
        kvm_irqfd_exit();
 out_irqfd:
+       kvm_arch_exit();
+out_fail:
        return r;
 }
 EXPORT_SYMBOL_GPL(kvm_init);