Merge remote-tracking branch 'asoc/topic/fsl' into asoc-next
authorMark Brown <broonie@opensource.wolfsonmicro.com>
Sun, 9 Dec 2012 15:22:09 +0000 (00:22 +0900)
committerMark Brown <broonie@opensource.wolfsonmicro.com>
Sun, 9 Dec 2012 15:22:09 +0000 (00:22 +0900)
1157 files changed:
CREDITS
Documentation/00-INDEX
Documentation/arm64/memory.txt
Documentation/cgroups/memory.txt
Documentation/devicetree/bindings/arm/atmel-at91.txt
Documentation/devicetree/bindings/input/touchscreen/egalax-ts.txt [new file with mode: 0644]
Documentation/devicetree/bindings/misc/atmel-ssc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/net/mdio-gpio.txt
Documentation/devicetree/bindings/pinctrl/nvidia,tegra20-pinmux.txt
Documentation/devicetree/bindings/pinctrl/nvidia,tegra30-pinmux.txt
Documentation/devicetree/bindings/sound/ak4104.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/atmel-at91sam9g20ek-wm8731-audio.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/cs4271.txt
Documentation/devicetree/bindings/sound/omap-abe-twl6040.txt
Documentation/filesystems/proc.txt
Documentation/firmware_class/README
Documentation/hwmon/fam15h_power
Documentation/networking/netdev-features.txt
Documentation/networking/vxlan.txt
Documentation/zh_CN/IRQ.txt [new file with mode: 0644]
Documentation/zh_CN/arm64/booting.txt [new file with mode: 0644]
Documentation/zh_CN/arm64/memory.txt [new file with mode: 0644]
MAINTAINERS
Makefile
arch/alpha/include/asm/thread_info.h
arch/alpha/kernel/osf_sys.c
arch/alpha/kernel/process.c
arch/alpha/kernel/traps.c
arch/arm/Kconfig
arch/arm/Makefile
arch/arm/boot/Makefile
arch/arm/boot/dts/at91sam9260.dtsi
arch/arm/boot/dts/at91sam9263.dtsi
arch/arm/boot/dts/at91sam9g20ek_common.dtsi
arch/arm/boot/dts/at91sam9g45.dtsi
arch/arm/boot/dts/at91sam9x5.dtsi
arch/arm/boot/dts/dbx5x0.dtsi
arch/arm/boot/dts/exynos4210-trats.dts
arch/arm/boot/dts/imx23.dtsi
arch/arm/boot/dts/imx28.dtsi
arch/arm/boot/dts/omap3.dtsi
arch/arm/boot/dts/tegra30.dtsi
arch/arm/configs/imx_v6_v7_defconfig
arch/arm/configs/mvebu_defconfig
arch/arm/configs/versatile_defconfig
arch/arm/include/asm/flat.h
arch/arm/include/asm/io.h
arch/arm/include/asm/sched_clock.h
arch/arm/include/asm/uaccess.h
arch/arm/include/asm/vfpmacros.h
arch/arm/include/asm/xen/interface.h
arch/arm/include/asm/xen/page.h
arch/arm/include/debug/8250_32.S [new file with mode: 0644]
arch/arm/include/debug/picoxcell.S
arch/arm/include/debug/socfpga.S
arch/arm/include/uapi/asm/hwcap.h
arch/arm/kernel/irq.c
arch/arm/kernel/kprobes-test-arm.c
arch/arm/kernel/machine_kexec.c
arch/arm/kernel/perf_event.c
arch/arm/kernel/sched_clock.c
arch/arm/kernel/smp.c
arch/arm/kernel/smp_twd.c
arch/arm/lib/delay.c
arch/arm/mach-at91/Kconfig
arch/arm/mach-at91/at91rm9200.c
arch/arm/mach-at91/at91rm9200_devices.c
arch/arm/mach-at91/at91sam9260.c
arch/arm/mach-at91/at91sam9260_devices.c
arch/arm/mach-at91/at91sam9261.c
arch/arm/mach-at91/at91sam9261_devices.c
arch/arm/mach-at91/at91sam9263.c
arch/arm/mach-at91/at91sam9263_devices.c
arch/arm/mach-at91/at91sam9g45.c
arch/arm/mach-at91/at91sam9g45_devices.c
arch/arm/mach-at91/at91sam9rl.c
arch/arm/mach-at91/at91sam9rl_devices.c
arch/arm/mach-at91/at91sam9x5.c
arch/arm/mach-at91/at91x40.c
arch/arm/mach-at91/board-neocore926.c
arch/arm/mach-at91/board-sam9261ek.c
arch/arm/mach-at91/board-sam9263ek.c
arch/arm/mach-at91/board-sam9g20ek.c
arch/arm/mach-at91/generic.h
arch/arm/mach-at91/irq.c
arch/arm/mach-at91/setup.c
arch/arm/mach-davinci/board-da850-evm.c
arch/arm/mach-davinci/dm644x.c
arch/arm/mach-exynos/common.c
arch/arm/mach-exynos/dma.c
arch/arm/mach-exynos/include/mach/map.h
arch/arm/mach-exynos/mach-exynos4-dt.c
arch/arm/mach-highbank/system.c
arch/arm/mach-imx/clk-busy.c
arch/arm/mach-imx/clk-gate2.c
arch/arm/mach-imx/clk-imx25.c
arch/arm/mach-imx/clk-imx27.c
arch/arm/mach-imx/ehci-imx25.c
arch/arm/mach-imx/ehci-imx35.c
arch/arm/mach-imx/mm-imx3.c
arch/arm/mach-omap2/Kconfig
arch/arm/mach-omap2/board-igep0020.c
arch/arm/mach-omap2/board-omap3beagle.c
arch/arm/mach-omap2/clock33xx_data.c
arch/arm/mach-omap2/clockdomains44xx_data.c
arch/arm/mach-omap2/common-board-devices.c
arch/arm/mach-omap2/devices.c
arch/arm/mach-omap2/mux34xx.c
arch/arm/mach-omap2/omap_hwmod.c
arch/arm/mach-omap2/omap_hwmod_44xx_data.c
arch/arm/mach-omap2/pm.h
arch/arm/mach-omap2/pm34xx.c
arch/arm/mach-omap2/serial.c
arch/arm/mach-omap2/twl-common.c
arch/arm/mach-omap2/vc.c
arch/arm/mach-pxa/hx4700.c
arch/arm/mach-pxa/spitz_pm.c
arch/arm/mach-s3c24xx/s3c2416.c
arch/arm/mach-s3c24xx/s3c2443.c
arch/arm/mach-s5p64x0/common.c
arch/arm/mach-s5pc100/common.c
arch/arm/mach-s5pv210/common.c
arch/arm/mach-shmobile/setup-r8a7779.c
arch/arm/mach-spear13xx/include/mach/spear1310_misc_regs.h [deleted file]
arch/arm/mach-spear13xx/include/mach/spear1340_misc_regs.h [deleted file]
arch/arm/mach-ux500/cpu.c
arch/arm/mm/alignment.c
arch/arm/mm/dma-mapping.c
arch/arm/mm/vmregion.h
arch/arm/plat-mxc/devices/platform-mxc-mmc.c
arch/arm/plat-omap/Kconfig
arch/arm/plat-omap/i2c.c
arch/arm/plat-omap/include/plat/omap-serial.h
arch/arm/plat-omap/include/plat/omap_hwmod.h
arch/arm/plat-samsung/include/plat/spi-core.h [new file with mode: 0644]
arch/arm/tools/Makefile
arch/arm/vfp/vfpmodule.c
arch/arm/xen/enlighten.c
arch/arm/xen/grant-table.c
arch/arm/xen/hypercall.S
arch/arm64/Kconfig
arch/arm64/include/asm/elf.h
arch/arm64/include/asm/fpsimd.h
arch/arm64/include/asm/io.h
arch/arm64/include/asm/pgtable-hwdef.h
arch/arm64/include/asm/pgtable.h
arch/arm64/include/asm/processor.h
arch/arm64/include/asm/unistd.h
arch/arm64/kernel/perf_event.c
arch/arm64/kernel/process.c
arch/arm64/kernel/smp.c
arch/arm64/mm/init.c
arch/frv/Kconfig
arch/frv/boot/Makefile
arch/frv/include/asm/unistd.h
arch/frv/kernel/entry.S
arch/frv/kernel/process.c
arch/frv/mb93090-mb00/pci-dma-nommu.c
arch/h8300/include/asm/cache.h
arch/ia64/include/asm/Kbuild
arch/ia64/include/asm/kvm_para.h [deleted file]
arch/ia64/mm/init.c
arch/m68k/include/asm/Kbuild
arch/m68k/include/asm/a.out.h [deleted file]
arch/m68k/include/asm/auxvec.h [deleted file]
arch/m68k/include/asm/byteorder.h [deleted file]
arch/m68k/include/asm/cachectl.h [deleted file]
arch/m68k/include/asm/fcntl.h [deleted file]
arch/m68k/include/asm/ioctls.h [deleted file]
arch/m68k/include/asm/msgbuf.h [deleted file]
arch/m68k/include/asm/param.h [deleted file]
arch/m68k/include/asm/poll.h [deleted file]
arch/m68k/include/asm/posix_types.h [deleted file]
arch/m68k/include/asm/ptrace.h
arch/m68k/include/asm/sembuf.h [deleted file]
arch/m68k/include/asm/setup.h
arch/m68k/include/asm/shmbuf.h [deleted file]
arch/m68k/include/asm/sigcontext.h [deleted file]
arch/m68k/include/asm/signal.h
arch/m68k/include/asm/socket.h [deleted file]
arch/m68k/include/asm/sockios.h [deleted file]
arch/m68k/include/asm/stat.h [deleted file]
arch/m68k/include/asm/swab.h [deleted file]
arch/m68k/include/asm/termbits.h [deleted file]
arch/m68k/include/asm/termios.h
arch/m68k/include/asm/unistd.h
arch/m68k/include/uapi/asm/Kbuild
arch/m68k/include/uapi/asm/a.out.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/auxvec.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/byteorder.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/cachectl.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/fcntl.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/ioctls.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/msgbuf.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/param.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/poll.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/posix_types.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/ptrace.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/sembuf.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/setup.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/shmbuf.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/sigcontext.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/signal.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/socket.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/sockios.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/stat.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/swab.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/termbits.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/termios.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/unistd.h [new file with mode: 0644]
arch/m68k/kernel/syscalltable.S
arch/mips/cavium-octeon/executive/cvmx-l2c.c
arch/mips/fw/arc/misc.c
arch/mips/include/asm/bitops.h
arch/mips/include/asm/compat.h
arch/mips/include/asm/io.h
arch/mips/include/asm/irqflags.h
arch/mips/include/asm/thread_info.h
arch/mips/kernel/setup.c
arch/mips/lib/Makefile
arch/mips/lib/bitops.c [new file with mode: 0644]
arch/mips/lib/mips-atomic.c [new file with mode: 0644]
arch/mips/mti-malta/malta-platform.c
arch/parisc/kernel/signal32.c
arch/parisc/kernel/sys_parisc.c
arch/powerpc/boot/dts/mpc5200b.dtsi
arch/powerpc/boot/dts/o2d.dtsi
arch/powerpc/boot/dts/pcm030.dts
arch/powerpc/platforms/52xx/mpc52xx_pic.c
arch/powerpc/platforms/pseries/eeh_pe.c
arch/powerpc/platforms/pseries/msi.c
arch/s390/Kconfig
arch/s390/boot/compressed/vmlinux.lds.S
arch/s390/include/asm/cio.h
arch/s390/include/asm/compat.h
arch/s390/include/asm/perf_event.h
arch/s390/include/asm/pgtable.h
arch/s390/include/asm/topology.h
arch/s390/include/uapi/asm/Kbuild
arch/s390/include/uapi/asm/chpid.h
arch/s390/include/uapi/asm/kvm_para.h [new file with mode: 0644]
arch/s390/include/uapi/asm/ptrace.h
arch/s390/kernel/cache.c
arch/s390/kernel/compat_signal.c
arch/s390/kernel/head_kdump.S
arch/s390/kernel/perf_cpum_cf.c
arch/s390/kernel/sclp.S
arch/s390/kernel/signal.c
arch/s390/kernel/topology.c
arch/s390/kernel/vmlinux.lds.S
arch/s390/lib/uaccess_pt.c
arch/s390/mm/gup.c
arch/sparc/Kconfig
arch/sparc/crypto/Makefile
arch/sparc/crypto/aes_glue.c
arch/sparc/crypto/camellia_glue.c
arch/sparc/crypto/crc32c_glue.c
arch/sparc/crypto/des_glue.c
arch/sparc/crypto/md5_glue.c
arch/sparc/crypto/sha1_glue.c
arch/sparc/crypto/sha256_glue.c
arch/sparc/crypto/sha512_glue.c
arch/sparc/include/asm/atomic_64.h
arch/sparc/include/asm/backoff.h
arch/sparc/include/asm/compat.h
arch/sparc/include/asm/processor_64.h
arch/sparc/include/asm/prom.h
arch/sparc/include/asm/thread_info_64.h
arch/sparc/include/asm/ttable.h
arch/sparc/include/uapi/asm/unistd.h
arch/sparc/kernel/entry.h
arch/sparc/kernel/leon_kernel.c
arch/sparc/kernel/perf_event.c
arch/sparc/kernel/process_64.c
arch/sparc/kernel/ptrace_64.c
arch/sparc/kernel/setup_64.c
arch/sparc/kernel/signal_64.c
arch/sparc/kernel/sys_sparc_64.c
arch/sparc/kernel/systbls_32.S
arch/sparc/kernel/systbls_64.S
arch/sparc/kernel/unaligned_64.c
arch/sparc/kernel/visemul.c
arch/sparc/kernel/vmlinux.lds.S
arch/sparc/kernel/winfixup.S
arch/sparc/lib/atomic_64.S
arch/sparc/lib/ksyms.c
arch/sparc/math-emu/math_64.c
arch/tile/Makefile
arch/tile/kernel/module.c
arch/unicore32/Kconfig
arch/unicore32/include/asm/Kbuild
arch/unicore32/include/asm/bug.h
arch/unicore32/include/asm/byteorder.h [deleted file]
arch/unicore32/include/asm/cmpxchg.h
arch/unicore32/include/asm/kvm_para.h [deleted file]
arch/unicore32/include/asm/processor.h
arch/unicore32/include/asm/ptrace.h
arch/unicore32/include/asm/sigcontext.h [deleted file]
arch/unicore32/include/asm/unistd.h [deleted file]
arch/unicore32/include/uapi/asm/Kbuild
arch/unicore32/include/uapi/asm/byteorder.h [new file with mode: 0644]
arch/unicore32/include/uapi/asm/ptrace.h [new file with mode: 0644]
arch/unicore32/include/uapi/asm/sigcontext.h [new file with mode: 0644]
arch/unicore32/include/uapi/asm/unistd.h [new file with mode: 0644]
arch/unicore32/kernel/entry.S
arch/unicore32/kernel/process.c
arch/unicore32/kernel/setup.h
arch/unicore32/kernel/sys.c
arch/unicore32/mm/fault.c
arch/x86/boot/compressed/eboot.c
arch/x86/boot/header.S
arch/x86/include/asm/efi.h
arch/x86/include/asm/ptrace.h
arch/x86/include/asm/xen/hypercall.h
arch/x86/include/asm/xen/hypervisor.h
arch/x86/include/asm/xen/interface.h
arch/x86/kernel/apic/io_apic.c
arch/x86/kernel/cpu/amd.c
arch/x86/kernel/cpu/mcheck/mce_amd.c
arch/x86/kernel/cpu/mcheck/mce_intel.c
arch/x86/kernel/cpu/perf_event.c
arch/x86/kernel/cpu/perf_event_intel_uncore.c
arch/x86/kernel/cpu/perf_event_knc.c
arch/x86/kernel/cpu/perf_event_p6.c
arch/x86/kernel/e820.c
arch/x86/kernel/entry_32.S
arch/x86/kernel/entry_64.S
arch/x86/kernel/kvm.c
arch/x86/kernel/microcode_amd.c
arch/x86/kernel/ptrace.c
arch/x86/kernel/setup.c
arch/x86/kernel/signal.c
arch/x86/kernel/uprobes.c
arch/x86/kvm/cpuid.h
arch/x86/kvm/lapic.c
arch/x86/kvm/mmu.c
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c
arch/x86/mm/init.c
arch/x86/mm/init_64.c
arch/x86/mm/tlb.c
arch/x86/oprofile/nmi_int.c
arch/x86/pci/ce4100.c
arch/x86/platform/ce4100/ce4100.c
arch/x86/platform/efi/efi.c
arch/x86/platform/efi/efi_64.c
arch/x86/xen/enlighten.c
arch/x86/xen/mmu.c
arch/xtensa/Kconfig
arch/xtensa/include/asm/io.h
arch/xtensa/include/asm/processor.h
arch/xtensa/include/asm/syscall.h
arch/xtensa/include/asm/unistd.h
arch/xtensa/include/uapi/asm/unistd.h
arch/xtensa/kernel/entry.S
arch/xtensa/kernel/process.c
arch/xtensa/kernel/syscall.c
arch/xtensa/kernel/xtensa_ksyms.c
block/Kconfig
block/blk-cgroup.c
block/blk-core.c
block/blk-exec.c
crypto/cryptd.c
drivers/acpi/glue.c
drivers/acpi/processor_driver.c
drivers/acpi/video.c
drivers/ata/ahci_platform.c
drivers/ata/libata-acpi.c
drivers/ata/libata-core.c
drivers/ata/libata-scsi.c
drivers/ata/pata_arasan_cf.c
drivers/ata/sata_highbank.c
drivers/ata/sata_svw.c
drivers/base/Kconfig
drivers/base/dma-coherent.c
drivers/base/dma-contiguous.c
drivers/base/firmware_class.c
drivers/base/platform.c
drivers/base/power/domain.c
drivers/base/power/qos.c
drivers/base/regmap/Kconfig
drivers/bcma/main.c
drivers/block/Kconfig
drivers/block/aoe/aoecmd.c
drivers/block/cciss.c
drivers/block/floppy.c
drivers/block/loop.c
drivers/block/mtip32xx/mtip32xx.c
drivers/block/mtip32xx/mtip32xx.h
drivers/block/xen-blkback/common.h
drivers/block/xen-blkback/xenbus.c
drivers/bluetooth/ath3k.c
drivers/bluetooth/btusb.c
drivers/bus/omap-ocp2scp.c
drivers/char/sonypi.c
drivers/clk/ux500/u8500_clk.c
drivers/cpufreq/cpufreq_stats.c
drivers/cpufreq/powernow-k8.c
drivers/dma/Kconfig
drivers/dma/dw_dmac_regs.h
drivers/dma/imx-dma.c
drivers/dma/sirf-dma.c
drivers/edac/amd64_edac.c
drivers/edac/amd64_edac.h
drivers/edac/edac_stub.c
drivers/edac/mce_amd_inj.c
drivers/extcon/extcon-adc-jack.c
drivers/extcon/extcon-class.c
drivers/extcon/extcon-gpio.c
drivers/extcon/extcon-max77693.c
drivers/extcon/extcon-max8997.c
drivers/firewire/sbp2.c
drivers/gpio/Kconfig
drivers/gpio/gpio-74x164.c
drivers/gpio/gpio-mcp23s08.c
drivers/gpio/gpio-mvebu.c
drivers/gpio/gpio-omap.c
drivers/gpio/gpio-timberdale.c
drivers/gpio/gpiolib.c
drivers/gpu/drm/drm_fb_cma_helper.c
drivers/gpu/drm/drm_fops.c
drivers/gpu/drm/drm_info.c
drivers/gpu/drm/drm_platform.c
drivers/gpu/drm/exynos/Kconfig
drivers/gpu/drm/exynos/exynos_drm_connector.c
drivers/gpu/drm/exynos/exynos_drm_encoder.c
drivers/gpu/drm/exynos/exynos_mixer.c
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/intel_crt.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_lvds.c
drivers/gpu/drm/i915/intel_overlay.c
drivers/gpu/drm/i915/intel_panel.c
drivers/gpu/drm/i915/intel_sdvo.c
drivers/gpu/drm/i915/intel_sdvo_regs.h
drivers/gpu/drm/nouveau/core/core/gpuobj.c
drivers/gpu/drm/nouveau/core/core/mm.c
drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
drivers/gpu/drm/nouveau/core/engine/graph/ctxnv40.c
drivers/gpu/drm/nouveau/core/engine/graph/nv40.c
drivers/gpu/drm/nouveau/core/engine/graph/nv40.h
drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c
drivers/gpu/drm/nouveau/core/include/core/mm.h
drivers/gpu/drm/nouveau/core/include/core/object.h
drivers/gpu/drm/nouveau/core/include/subdev/clock.h
drivers/gpu/drm/nouveau/core/subdev/bios/base.c
drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c
drivers/gpu/drm/nouveau/core/subdev/bios/pll.c
drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c
drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c
drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c
drivers/gpu/drm/nouveau/core/subdev/i2c/base.c
drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c
drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c
drivers/gpu/drm/nouveau/nouveau_abi16.c
drivers/gpu/drm/nouveau/nouveau_connector.c
drivers/gpu/drm/nouveau/nouveau_display.c
drivers/gpu/drm/nouveau/nouveau_drm.c
drivers/gpu/drm/nouveau/nouveau_drm.h
drivers/gpu/drm/nouveau/nouveau_irq.c
drivers/gpu/drm/nouveau/nv04_dac.c
drivers/gpu/drm/nouveau/nv04_dfp.c
drivers/gpu/drm/nouveau/nv04_tv.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_cs.c
drivers/gpu/drm/radeon/evergreend.h
drivers/gpu/drm/radeon/ni.c
drivers/gpu/drm/radeon/nid.h
drivers/gpu/drm/radeon/radeon_agp.c
drivers/gpu/drm/radeon/radeon_atpx_handler.c
drivers/gpu/drm/radeon/radeon_connectors.c
drivers/gpu/drm/radeon/radeon_device.c
drivers/gpu/drm/radeon/radeon_gart.c
drivers/gpu/drm/radeon/radeon_gem.c
drivers/gpu/drm/radeon/radeon_legacy_crtc.c
drivers/gpu/drm/radeon/radeon_legacy_encoders.c
drivers/gpu/drm/radeon/radeon_object.c
drivers/gpu/drm/radeon/si.c
drivers/gpu/drm/radeon/sid.h
drivers/gpu/drm/shmobile/shmob_drm_drv.c
drivers/gpu/drm/ttm/ttm_bo.c
drivers/gpu/drm/ttm/ttm_page_alloc.c
drivers/gpu/drm/ttm/ttm_tt.c
drivers/gpu/drm/udl/udl_drv.h
drivers/gpu/drm/udl/udl_fb.c
drivers/gpu/drm/udl/udl_transfer.c
drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
drivers/hid/hid-apple.c
drivers/hid/hid-core.c
drivers/hid/hid-ids.h
drivers/hid/hid-microsoft.c
drivers/hid/hid-multitouch.c
drivers/hid/hidraw.c
drivers/hv/channel.c
drivers/hwmon/asb100.c
drivers/hwmon/fam15h_power.c
drivers/hwmon/gpio-fan.c
drivers/hwmon/w83627ehf.c
drivers/hwmon/w83627hf.c
drivers/hwmon/w83781d.c
drivers/hwmon/w83791d.c
drivers/hwmon/w83792d.c
drivers/hwmon/w83l786ng.c
drivers/i2c/Makefile
drivers/i2c/busses/Kconfig
drivers/i2c/busses/Makefile
drivers/i2c/busses/i2c-at91.c
drivers/i2c/busses/i2c-i801.c
drivers/i2c/busses/i2c-mxs.c
drivers/i2c/busses/i2c-nomadik.c
drivers/i2c/busses/i2c-omap.c
drivers/i2c/busses/i2c-s3c2410.c
drivers/i2c/busses/i2c-stub.c [deleted file]
drivers/i2c/busses/i2c-tegra.c
drivers/i2c/i2c-stub.c [new file with mode: 0644]
drivers/i2c/muxes/i2c-mux-pinctrl.c
drivers/iio/Kconfig
drivers/iio/Makefile
drivers/infiniband/hw/cxgb4/mem.c
drivers/infiniband/hw/mlx4/alias_GUID.c
drivers/infiniband/hw/mlx4/mad.c
drivers/infiniband/hw/mlx4/mcg.c
drivers/input/evdev.c
drivers/input/input-mt.c
drivers/input/joydev.c
drivers/input/keyboard/Kconfig
drivers/input/keyboard/pxa27x_keypad.c
drivers/input/misc/Kconfig
drivers/input/misc/Makefile
drivers/input/misc/arizona-haptics.c [new file with mode: 0644]
drivers/input/misc/xen-kbdfront.c
drivers/input/mouse/bcm5974.c
drivers/input/mousedev.c
drivers/input/tablet/wacom_sys.c
drivers/input/tablet/wacom_wac.c
drivers/input/tablet/wacom_wac.h
drivers/input/touchscreen/Kconfig
drivers/input/touchscreen/ads7846.c
drivers/input/touchscreen/egalax_ts.c
drivers/input/touchscreen/tsc40.c
drivers/iommu/amd_iommu_init.c
drivers/iommu/intel-iommu.c
drivers/iommu/tegra-smmu.c
drivers/irqchip/irq-bcm2835.c
drivers/isdn/Kconfig
drivers/isdn/gigaset/bas-gigaset.c
drivers/isdn/i4l/Kconfig
drivers/isdn/i4l/isdn_common.c
drivers/leds/ledtrig-cpu.c
drivers/md/dm.c
drivers/md/faulty.c
drivers/md/md.c
drivers/md/raid1.c
drivers/md/raid10.c
drivers/md/raid5.c
drivers/mfd/arizona-core.c
drivers/misc/atmel-ssc.c
drivers/mmc/host/dw_mmc-exynos.c
drivers/mmc/host/dw_mmc-pltfm.c
drivers/mmc/host/dw_mmc-pltfm.h
drivers/mmc/host/dw_mmc.c
drivers/mmc/host/mxcmmc.c
drivers/mmc/host/omap_hsmmc.c
drivers/mmc/host/sdhci-dove.c
drivers/mmc/host/sdhci-of-esdhc.c
drivers/mmc/host/sdhci-pci.c
drivers/mmc/host/sdhci-pltfm.c
drivers/mmc/host/sdhci-s3c.c
drivers/mmc/host/sdhci.c
drivers/mmc/host/sdhci.h
drivers/mmc/host/sh_mmcif.c
drivers/mtd/devices/slram.c
drivers/mtd/nand/nand_base.c
drivers/mtd/ofpart.c
drivers/mtd/onenand/onenand_base.c
drivers/net/bonding/bond_main.c
drivers/net/bonding/bond_sysfs.c
drivers/net/can/flexcan.c
drivers/net/can/sja1000/peak_pci.c
drivers/net/ethernet/8390/ne.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
drivers/net/ethernet/freescale/gianfar.c
drivers/net/ethernet/freescale/gianfar_ptp.c
drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
drivers/net/ethernet/jme.c
drivers/net/ethernet/marvell/skge.c
drivers/net/ethernet/mellanox/mlx4/en_tx.c
drivers/net/ethernet/mellanox/mlx4/eq.c
drivers/net/ethernet/mellanox/mlx4/main.c
drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
drivers/net/ethernet/micrel/ksz884x.c
drivers/net/ethernet/nxp/lpc_eth.c
drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
drivers/net/ethernet/qlogic/qla3xxx.c
drivers/net/ethernet/realtek/8139cp.c
drivers/net/ethernet/realtek/r8169.c
drivers/net/ethernet/sis/sis900.c
drivers/net/ethernet/smsc/smsc911x.c
drivers/net/ethernet/ti/Kconfig
drivers/net/ethernet/tile/tilegx.c
drivers/net/ethernet/xilinx/xilinx_axienet_main.c
drivers/net/ethernet/xscale/ixp4xx_eth.c
drivers/net/irda/sir_dev.c
drivers/net/phy/Kconfig
drivers/net/phy/Makefile
drivers/net/phy/at803x.c [new file with mode: 0644]
drivers/net/phy/mdio-gpio.c
drivers/net/team/team_mode_broadcast.c
drivers/net/usb/cdc_eem.c
drivers/net/usb/cdc_ether.c
drivers/net/usb/cdc_ncm.c
drivers/net/usb/ipheth.c
drivers/net/usb/qmi_wwan.c
drivers/net/usb/smsc95xx.c
drivers/net/usb/usbnet.c
drivers/net/vmxnet3/vmxnet3_drv.c
drivers/net/vxlan.c
drivers/net/wan/ixp4xx_hss.c
drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
drivers/net/wireless/ath/ath9k/hif_usb.c
drivers/net/wireless/ath/ath9k/hw.c
drivers/net/wireless/ath/ath9k/xmit.c
drivers/net/wireless/b43/main.c
drivers/net/wireless/b43legacy/pio.c
drivers/net/wireless/brcm80211/brcmfmac/usb.c
drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
drivers/net/wireless/ipw2x00/ipw2200.c
drivers/net/wireless/iwlwifi/dvm/devices.c
drivers/net/wireless/iwlwifi/dvm/mac80211.c
drivers/net/wireless/iwlwifi/dvm/main.c
drivers/net/wireless/iwlwifi/pcie/rx.c
drivers/net/wireless/iwlwifi/pcie/tx.c
drivers/net/wireless/mwifiex/cfg80211.c
drivers/net/wireless/mwifiex/cmdevt.c
drivers/net/wireless/mwifiex/scan.c
drivers/net/wireless/mwifiex/sdio.c
drivers/net/wireless/rt2x00/rt2500usb.c
drivers/net/wireless/rt2x00/rt2800lib.c
drivers/net/wireless/rt2x00/rt2800usb.c
drivers/net/wireless/rt2x00/rt73usb.c
drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
drivers/net/wireless/rtlwifi/usb.c
drivers/net/xen-netfront.c
drivers/nfc/pn533.c
drivers/pci/bus.c
drivers/pci/pci-driver.c
drivers/pci/pci-sysfs.c
drivers/pci/pci.c
drivers/pci/pci.h
drivers/pci/pcie/aer/aerdrv_core.c
drivers/pci/pcie/portdrv_core.c
drivers/pci/proc.c
drivers/pinctrl/Kconfig
drivers/pinctrl/core.c
drivers/pinctrl/pinconf.c
drivers/pinctrl/pinctrl-nomadik.c
drivers/pinctrl/pinctrl-tegra.c
drivers/pinctrl/pinctrl-tegra30.c
drivers/pinctrl/spear/pinctrl-spear.c
drivers/pinctrl/spear/pinctrl-spear1310.c
drivers/pinctrl/spear/pinctrl-spear1340.c
drivers/pinctrl/spear/pinctrl-spear320.c
drivers/pinctrl/spear/pinctrl-spear3xx.h
drivers/rapidio/rio.c
drivers/regulator/core.c
drivers/rtc/rtc-imxdi.c
drivers/s390/char/con3215.c
drivers/s390/cio/css.c
drivers/s390/cio/css.h
drivers/s390/cio/device.c
drivers/s390/cio/idset.c
drivers/s390/cio/idset.h
drivers/s390/net/qeth_core_main.c
drivers/s390/net/qeth_l2_main.c
drivers/scsi/isci/request.c
drivers/scsi/qla2xxx/qla_mid.c
drivers/scsi/qla2xxx/qla_target.c
drivers/scsi/qla2xxx/qla_target.h
drivers/scsi/qla2xxx/tcm_qla2xxx.c
drivers/scsi/qla2xxx/tcm_qla2xxx.h
drivers/scsi/qlogicpti.c
drivers/scsi/scsi.c
drivers/scsi/scsi_lib.c
drivers/scsi/sd.c
drivers/scsi/sd.h
drivers/spi/spi-mxs.c
drivers/spi/spi-pl022.c
drivers/spi/spi-rspi.c
drivers/staging/android/android_alarm.h
drivers/staging/android/binder.c
drivers/staging/comedi/drivers/8255_pci.c
drivers/staging/comedi/drivers/amplc_dio200.c
drivers/staging/comedi/drivers/amplc_pc236.c
drivers/staging/comedi/drivers/amplc_pc263.c
drivers/staging/comedi/drivers/das08.c
drivers/staging/comedi/drivers/ni_daq_700.c
drivers/staging/comedi/drivers/ni_labpc.c
drivers/staging/iio/accel/adis16201_core.c
drivers/staging/iio/accel/adis16203_core.c
drivers/staging/iio/accel/adis16204_core.c
drivers/staging/iio/accel/adis16209_core.c
drivers/staging/iio/accel/adis16220_core.c
drivers/staging/iio/accel/adis16240_core.c
drivers/staging/iio/gyro/adis16260_core.c
drivers/staging/iio/imu/adis16400.h
drivers/staging/iio/imu/adis16400_core.c
drivers/staging/ipack/bridges/tpci200.c
drivers/staging/omapdrm/omap_gem.c
drivers/staging/ramster/Kconfig
drivers/staging/tidspbridge/core/tiomap3430.c
drivers/staging/tidspbridge/hw/hw_mmu.c
drivers/staging/tidspbridge/hw/hw_mmu.h
drivers/staging/tidspbridge/include/dspbridge/cfgdefs.h
drivers/staging/tidspbridge/include/dspbridge/host_os.h
drivers/staging/tidspbridge/rmgr/drv.c
drivers/staging/tidspbridge/rmgr/node.c
drivers/staging/zram/zram_drv.c
drivers/target/iscsi/iscsi_target.c
drivers/target/iscsi/iscsi_target_core.h
drivers/target/iscsi/iscsi_target_login.c
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_sbc.c
drivers/target/target_core_spc.c
drivers/target/target_core_tmr.c
drivers/target/target_core_transport.c
drivers/thermal/exynos_thermal.c
drivers/thermal/rcar_thermal.c
drivers/tty/hvc/hvc_console.c
drivers/tty/serial/max310x.c
drivers/tty/serial/omap-serial.c
drivers/usb/core/hcd.c
drivers/usb/core/hub.c
drivers/usb/early/ehci-dbgp.c
drivers/usb/gadget/net2272.c
drivers/usb/gadget/u_ether.c
drivers/usb/host/ehci-ls1x.c
drivers/usb/host/ohci-xls.c
drivers/usb/host/pci-quirks.c
drivers/usb/host/xhci-dbg.c
drivers/usb/host/xhci-hub.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.c
drivers/usb/misc/ezusb.c
drivers/usb/musb/musb_dsps.c
drivers/usb/musb/musb_gadget.c
drivers/usb/musb/ux500.c
drivers/usb/otg/Kconfig
drivers/usb/renesas_usbhs/fifo.c
drivers/usb/renesas_usbhs/mod_host.c
drivers/usb/serial/ch341.c
drivers/usb/serial/digi_acceleport.c
drivers/usb/serial/ipw.c
drivers/usb/serial/keyspan.c
drivers/usb/serial/keyspan.h
drivers/usb/serial/mct_u232.c
drivers/usb/serial/metro-usb.c
drivers/usb/serial/mos7720.c
drivers/usb/serial/mos7840.c
drivers/usb/serial/omninet.c
drivers/usb/serial/opticon.c
drivers/usb/serial/option.c
drivers/usb/serial/qcserial.c
drivers/usb/serial/quatech2.c
drivers/usb/serial/sierra.c
drivers/usb/serial/usb-wwan.h
drivers/usb/serial/usb_wwan.c
drivers/usb/serial/whiteheat.c
drivers/usb/storage/scsiglue.c
drivers/usb/storage/unusual_devs.h
drivers/vhost/net.c
drivers/video/backlight/Kconfig
drivers/video/omap2/dss/dsi.c
drivers/video/omap2/dss/dss.c
drivers/video/omap2/dss/hdmi.c
drivers/video/omap2/omapfb/omapfb-ioctl.c
drivers/video/xen-fbfront.c
drivers/virtio/virtio.c
drivers/xen/Kconfig
drivers/xen/Makefile
drivers/xen/balloon.c
drivers/xen/dbgp.c
drivers/xen/events.c
drivers/xen/fallback.c [new file with mode: 0644]
drivers/xen/gntdev.c
drivers/xen/grant-table.c
drivers/xen/privcmd.c
drivers/xen/sys-hypervisor.c
drivers/xen/xen-pciback/vpci.c
drivers/xen/xenbus/xenbus_dev_frontend.c
drivers/xen/xenbus/xenbus_xs.c
fs/bio.c
fs/block_dev.c
fs/btrfs/backref.c
fs/btrfs/backref.h
fs/btrfs/ctree.c
fs/btrfs/ctree.h
fs/btrfs/extent_io.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/qgroup.c
fs/btrfs/send.c
fs/btrfs/transaction.c
fs/btrfs/volumes.c
fs/ceph/export.c
fs/char_dev.c
fs/cifs/cifsacl.c
fs/cifs/dir.c
fs/compat_ioctl.c
fs/eventpoll.c
fs/exec.c
fs/ext3/balloc.c
fs/ext4/balloc.c
fs/ext4/bitmap.c
fs/ext4/ext4.h
fs/ext4/ext4_jbd2.c
fs/ext4/extents.c
fs/ext4/ialloc.c
fs/ext4/mballoc.c
fs/ext4/resize.c
fs/ext4/super.c
fs/file.c
fs/gfs2/file.c
fs/gfs2/lops.c
fs/gfs2/quota.c
fs/gfs2/rgrp.c
fs/gfs2/super.c
fs/gfs2/trans.c
fs/jffs2/file.c
fs/jfs/jfs_discard.c
fs/lockd/mon.c
fs/namei.c
fs/nfs/callback.c
fs/nfs/dns_resolve.c
fs/nfs/inode.c
fs/nfs/internal.h
fs/nfs/mount_clnt.c
fs/nfs/namespace.c
fs/nfs/nfs4filelayout.c
fs/nfs/nfs4filelayout.h
fs/nfs/nfs4filelayoutdev.c
fs/nfs/nfs4getroot.c
fs/nfs/nfs4namespace.c
fs/nfs/nfs4proc.c
fs/nfs/objlayout/objio_osd.c
fs/nfs/pnfs.c
fs/nfs/pnfs.h
fs/nfs/super.c
fs/nfs/unlink.c
fs/notify/fanotify/fanotify.c
fs/notify/fanotify/fanotify_user.c
fs/proc/base.c
fs/proc/stat.c
fs/pstore/platform.c
fs/reiserfs/inode.c
fs/reiserfs/stree.c
fs/reiserfs/super.c
fs/sysfs/dir.c
fs/ubifs/find.c
fs/ubifs/lprops.c
fs/ubifs/ubifs.h
fs/xfs/xfs_alloc.c
fs/xfs/xfs_alloc.h
fs/xfs/xfs_alloc_btree.c
fs/xfs/xfs_aops.c
fs/xfs/xfs_attr_leaf.c
fs/xfs/xfs_bmap.c
fs/xfs/xfs_bmap.h
fs/xfs/xfs_buf.c
fs/xfs/xfs_buf_item.c
fs/xfs/xfs_fsops.c
fs/xfs/xfs_ialloc.c
fs/xfs/xfs_inode.c
fs/xfs/xfs_ioctl.c
fs/xfs/xfs_iomap.c
fs/xfs/xfs_log.c
fs/xfs/xfs_log_recover.c
include/drm/drm_pciids.h
include/linux/atmel-ssc.h
include/linux/clk-provider.h
include/linux/dynamic_debug.h
include/linux/extcon.h
include/linux/hashtable.h [new file with mode: 0644]
include/linux/i2c-omap.h
include/linux/iio/iio.h
include/linux/kvm_host.h
include/linux/memblock.h
include/linux/mfd/arizona/core.h
include/linux/mfd/arizona/pdata.h
include/linux/mfd/max77693.h
include/linux/mm.h
include/linux/mmc/dw_mmc.h
include/linux/mmc/sdhci.h
include/linux/mmzone.h
include/linux/of_address.h
include/linux/percpu-rwsem.h
include/linux/perf_event.h
include/linux/platform_data/davinci_asp.h
include/linux/platform_data/omap_ocp2scp.h [new file with mode: 0644]
include/linux/ptp_clock_kernel.h
include/linux/raid/Kbuild
include/linux/raid/md_p.h [deleted file]
include/linux/raid/md_u.h
include/linux/rbtree_augmented.h
include/linux/rio.h
include/linux/spi/ads7846.h
include/linux/spi/tsc2005.h
include/linux/tcp.h
include/linux/uprobes.h
include/net/cfg80211.h
include/net/xfrm.h
include/scsi/scsi_device.h
include/sound/core.h
include/sound/cs4271.h
include/sound/sh_fsi.h
include/trace/events/xen.h
include/uapi/linux/eventpoll.h
include/uapi/linux/oom.h
include/uapi/linux/raid/Kbuild
include/uapi/linux/raid/md_p.h [new file with mode: 0644]
include/uapi/linux/raid/md_u.h [new file with mode: 0644]
include/uapi/linux/tcp.h
include/xen/grant_table.h
include/xen/hvm.h
include/xen/interface/grant_table.h
include/xen/interface/memory.h
init/main.c
kernel/Makefile
kernel/cgroup.c
kernel/events/uprobes.c
kernel/futex.c
kernel/module.c
kernel/module_signing.c
kernel/pid_namespace.c
kernel/trace/ring_buffer.c
kernel/workqueue.c
lib/genalloc.c
lib/mpi/longlong.h
mm/bootmem.c
mm/highmem.c
mm/memblock.c
mm/memcontrol.c
mm/memory.c
mm/memory_hotplug.c
mm/mmap.c
mm/mmu_notifier.c
mm/mmzone.c
mm/nobootmem.c
mm/page_alloc.c
mm/rmap.c
mm/shmem.c
mm/swapfile.c
mm/vmscan.c
net/8021q/vlan.c
net/batman-adv/bridge_loop_avoidance.c
net/batman-adv/routing.c
net/batman-adv/soft-interface.c
net/batman-adv/translation-table.c
net/batman-adv/types.h
net/bluetooth/hci_core.c
net/bluetooth/mgmt.c
net/bluetooth/smp.c
net/ceph/messenger.c
net/core/dev.c
net/core/dev_addr_lists.c
net/core/net-sysfs.c
net/core/rtnetlink.c
net/core/skbuff.c
net/ipv4/inet_diag.c
net/ipv4/ip_sockglue.c
net/ipv4/ip_vti.c
net/ipv4/netfilter/iptable_nat.c
net/ipv4/route.c
net/ipv4/tcp.c
net/ipv4/tcp_illinois.c
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_metrics.c
net/ipv4/tcp_minisocks.c
net/ipv4/tcp_output.c
net/ipv4/tcp_timer.c
net/ipv4/xfrm4_policy.c
net/ipv6/inet6_connection_sock.c
net/ipv6/ip6_gre.c
net/ipv6/ipv6_sockglue.c
net/ipv6/ndisc.c
net/ipv6/netfilter/ip6table_nat.c
net/ipv6/netfilter/nf_conntrack_reasm.c
net/ipv6/route.c
net/l2tp/l2tp_eth.c
net/mac80211/cfg.c
net/mac80211/ibss.c
net/mac80211/ieee80211_i.h
net/mac80211/iface.c
net/mac80211/main.c
net/mac80211/mlme.c
net/mac80211/rx.c
net/mac80211/scan.c
net/mac80211/sta_info.c
net/mac80211/status.c
net/mac80211/tx.c
net/mac80211/util.c
net/mac80211/wpa.c
net/netfilter/ipset/ip_set_hash_ip.c
net/netfilter/ipset/ip_set_hash_ipport.c
net/netfilter/ipset/ip_set_hash_ipportip.c
net/netfilter/ipset/ip_set_hash_ipportnet.c
net/netfilter/ipvs/ip_vs_ctl.c
net/netfilter/nf_conntrack_h323_main.c
net/netfilter/nfnetlink_cttimeout.c
net/netfilter/xt_CT.c
net/netfilter/xt_TEE.c
net/netfilter/xt_nat.c
net/netlink/af_netlink.c
net/nfc/llcp/llcp.c
net/sched/sch_qfq.c
net/sctp/proc.c
net/sctp/socket.c
net/sunrpc/backchannel_rqst.c
net/sunrpc/xprtsock.c
net/tipc/handler.c
net/wireless/core.c
net/wireless/mlme.c
net/wireless/reg.c
net/wireless/util.c
scripts/Makefile.modinst
scripts/checkpatch.pl
scripts/kconfig/expr.h
scripts/kconfig/list.h [new file with mode: 0644]
scripts/kconfig/lkc_proto.h
scripts/kconfig/mconf.c
scripts/kconfig/menu.c
scripts/sign-file
security/apparmor/policy.c
security/device_cgroup.c
security/selinux/netnode.c
sound/core/compress_offload.c
sound/core/control.c
sound/core/hwdep.c
sound/core/init.c
sound/core/oss/mixer_oss.c
sound/core/oss/pcm_oss.c
sound/core/pcm.c
sound/core/pcm_native.c
sound/core/rawmidi.c
sound/core/sound.c
sound/core/sound_oss.c
sound/i2c/other/ak4113.c
sound/i2c/other/ak4114.c
sound/i2c/other/ak4117.c
sound/isa/opti9xx/miro.c
sound/pci/als300.c
sound/pci/es1968.c
sound/pci/fm801.c
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_codec.h
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_analog.c
sound/pci/hda/patch_cirrus.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/pci/hda/patch_via.c
sound/pci/ice1712/ice1724.c
sound/pci/rme9652/hdspm.c
sound/soc/atmel/Kconfig
sound/soc/atmel/Makefile
sound/soc/atmel/atmel-pcm-dma.c [new file with mode: 0644]
sound/soc/atmel/atmel-pcm-pdc.c [new file with mode: 0644]
sound/soc/atmel/atmel-pcm.c
sound/soc/atmel/atmel-pcm.h
sound/soc/atmel/atmel_ssc_dai.c
sound/soc/atmel/atmel_ssc_dai.h
sound/soc/atmel/sam9g20_wm8731.c
sound/soc/codecs/Kconfig
sound/soc/codecs/Makefile
sound/soc/codecs/ab8500-codec.c
sound/soc/codecs/ak4104.c
sound/soc/codecs/ak4535.c
sound/soc/codecs/ak4642.c
sound/soc/codecs/arizona.c
sound/soc/codecs/arizona.h
sound/soc/codecs/cs4271.c
sound/soc/codecs/cs42l52.c
sound/soc/codecs/da7210.c
sound/soc/codecs/da9055.c
sound/soc/codecs/wm2200.c
sound/soc/codecs/wm5102.c
sound/soc/codecs/wm5110.c
sound/soc/codecs/wm8978.c
sound/soc/codecs/wm8994.c
sound/soc/codecs/wm8994.h
sound/soc/codecs/wm_adsp.c [new file with mode: 0644]
sound/soc/codecs/wm_adsp.h [new file with mode: 0644]
sound/soc/codecs/wmfw.h [new file with mode: 0644]
sound/soc/davinci/davinci-evm.c
sound/soc/davinci/davinci-mcasp.c
sound/soc/davinci/davinci-mcasp.h
sound/soc/davinci/davinci-pcm.c
sound/soc/davinci/davinci-pcm.h
sound/soc/fsl/Kconfig
sound/soc/fsl/Makefile
sound/soc/kirkwood/kirkwood-dma.c
sound/soc/kirkwood/kirkwood-i2s.c
sound/soc/mxs/mxs-saif.c
sound/soc/omap/mcbsp.c
sound/soc/omap/mcbsp.h
sound/soc/omap/omap-abe-twl6040.c
sound/soc/omap/omap-dmic.c
sound/soc/omap/omap-mcbsp.c
sound/soc/omap/zoom2.c
sound/soc/samsung/Kconfig
sound/soc/samsung/bells.c
sound/soc/sh/fsi.c
sound/soc/soc-core.c
sound/soc/soc-dapm.c
sound/soc/soc-dmaengine-pcm.c
sound/soc/ux500/mop500.c
sound/soc/ux500/ux500_msp_i2s.c
sound/usb/card.c
sound/usb/card.h
sound/usb/endpoint.c
sound/usb/endpoint.h
sound/usb/midi.c
sound/usb/mixer.c
sound/usb/mixer_quirks.c
sound/usb/pcm.c
sound/usb/proc.c
sound/usb/stream.c
sound/usb/usbaudio.h
tools/perf/builtin-help.c
tools/perf/builtin-trace.c
tools/perf/util/parse-events-test.c
tools/perf/util/thread.c
tools/power/x86/turbostat/turbostat.c
tools/testing/ktest/ktest.pl
tools/testing/selftests/Makefile
tools/testing/selftests/epoll/Makefile [deleted file]
tools/testing/selftests/epoll/test_epoll.c [deleted file]
tools/vm/page-types.c
usr/gen_init_cpio.c
virt/kvm/kvm_main.c

diff --git a/CREDITS b/CREDITS
index d8fe12a9421fa2a7145e7218cc7d664232d0d7ce..2346b09ca8bb9cfc3c4371eb5ad6058be818d990 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -1823,6 +1823,11 @@ S: Kattreinstr 38
 S: D-64295
 S: Germany
 
+N: Avi Kivity
+E: avi.kivity@gmail.com
+D: Kernel-based Virtual Machine (KVM)
+S: Ra'annana, Israel
+
 N: Andi Kleen
 E: andi@firstfloor.org
 U: http://www.halobates.de
index f54273e2ac979a386e27c0174e4a9524e60eae5e..ceb1ff735469995b560f0cdf07227407be682235 100644 (file)
@@ -210,6 +210,8 @@ local_ops.txt
        - semantics and behavior of local atomic operations.
 lockdep-design.txt
        - documentation on the runtime locking correctness validator.
+lockup-watchdogs.txt
+       - info on soft and hard lockup detectors (aka nmi_watchdog).
 logo.gif
        - full colour GIF image of Linux logo (penguin - Tux).
 logo.txt
@@ -240,8 +242,6 @@ netlabel/
        - directory with information on the NetLabel subsystem.
 networking/
        - directory with info on various aspects of networking with Linux.
-nmi_watchdog.txt
-       - info on NMI watchdog for SMP systems.
 nommu-mmap.txt
        - documentation about no-mmu memory mapping support.
 numastat.txt
index dbbdcbba75a34005ced4edea51e7a9a308aec1e6..4110cca96bd608f1b9d246d31fd482f503c2c5b4 100644 (file)
@@ -27,17 +27,17 @@ Start                       End                     Size            Use
 -----------------------------------------------------------------------
 0000000000000000       0000007fffffffff         512GB          user
 
-ffffff8000000000       ffffffbbfffcffff        ~240GB          vmalloc
+ffffff8000000000       ffffffbbfffeffff        ~240GB          vmalloc
 
-ffffffbbfffd0000       ffffffbcfffdffff          64KB          [guard page]
+ffffffbbffff0000       ffffffbbffffffff          64KB          [guard page]
 
-ffffffbbfffe0000       ffffffbcfffeffff          64KB          PCI I/O space
+ffffffbc00000000       ffffffbdffffffff           8GB          vmemmap
 
-ffffffbbffff0000       ffffffbcffffffff          64KB          [guard page]
+ffffffbe00000000       ffffffbffbbfffff          ~8GB          [guard, future vmmemap]
 
-ffffffbc00000000       ffffffbdffffffff           8GB          vmemmap
+ffffffbffbe00000       ffffffbffbe0ffff          64KB          PCI I/O space
 
-ffffffbe00000000       ffffffbffbffffff          ~8GB          [guard, future vmmemap]
+ffffffbbffff0000       ffffffbcffffffff          ~2MB          [guard]
 
 ffffffbffc000000       ffffffbfffffffff          64MB          modules
 
index c07f7b4fb88d162ad012e69a3d77aa90d62868ff..71c4da413444d969519ae464250774db5c05de63 100644 (file)
@@ -466,6 +466,10 @@ Note:
 5.3 swappiness
 
 Similar to /proc/sys/vm/swappiness, but affecting a hierarchy of groups only.
+Please note that unlike the global swappiness, memcg knob set to 0
+really prevents from any swapping even if there is a swap storage
+available. This might lead to memcg OOM killer if there are no file
+pages to reclaim.
 
 Following cgroups' swappiness can't be changed.
 - root cgroup (uses /proc/sys/vm/swappiness).
index ecc81e3687153689337859f910cecb33627e8f49..d187e9f7cf1cf8b7fcd5bda6c6507558360a9237 100644 (file)
@@ -8,7 +8,7 @@ PIT Timer required properties:
   shared across all System Controller members.
 
 TC/TCLIB Timer required properties:
-- compatible: Should be "atmel,<chip>-pit".
+- compatible: Should be "atmel,<chip>-tcb".
   <chip> can be "at91rm9200" or "at91sam9x5"
 - reg: Should contain registers location and length
 - interrupts: Should contain all interrupts for the TC block
diff --git a/Documentation/devicetree/bindings/input/touchscreen/egalax-ts.txt b/Documentation/devicetree/bindings/input/touchscreen/egalax-ts.txt
new file mode 100644 (file)
index 0000000..df70318
--- /dev/null
@@ -0,0 +1,19 @@
+* EETI eGalax Multiple Touch Controller
+
+Required properties:
+- compatible: must be "eeti,egalax_ts"
+- reg: i2c slave address
+- interrupt-parent: the phandle for the interrupt controller
+- interrupts: touch controller interrupt
+- wakeup-gpios: the gpio pin to be used for waking up the controller
+  as well as uased as irq pin
+
+Example:
+
+       egalax_ts@04 {
+               compatible = "eeti,egalax_ts";
+               reg = <0x04>;
+               interrupt-parent = <&gpio1>;
+               interrupts = <9 2>;
+               wakeup-gpios = <&gpio1 9 0>;
+       };
diff --git a/Documentation/devicetree/bindings/misc/atmel-ssc.txt b/Documentation/devicetree/bindings/misc/atmel-ssc.txt
new file mode 100644 (file)
index 0000000..38e51ad
--- /dev/null
@@ -0,0 +1,15 @@
+* Atmel SSC driver.
+
+Required properties:
+- compatible: "atmel,at91rm9200-ssc" or "atmel,at91sam9g45-ssc"
+       - atmel,at91rm9200-ssc: support pdc transfer
+       - atmel,at91sam9g45-ssc: support dma transfer
+- reg: Should contain SSC registers location and length
+- interrupts: Should contain SSC interrupt
+
+Example:
+ssc0: ssc@fffbc000 {
+       compatible = "atmel,at91rm9200-ssc";
+       reg = <0xfffbc000 0x4000>;
+       interrupts = <14 4 5>;
+};
index bc9549529014730bc6abd0cefba2d82824370e5e..c79bab025369af4bb6320ba0e90f7fb386942cc1 100644 (file)
@@ -8,9 +8,16 @@ gpios property as described in section VIII.1 in the following order:
 
 MDC, MDIO.
 
+Note: Each gpio-mdio bus should have an alias correctly numbered in "aliases"
+node.
+
 Example:
 
-mdio {
+aliases {
+       mdio-gpio0 = <&mdio0>;
+};
+
+mdio0: mdio {
        compatible = "virtual,mdio-gpio";
        #address-cells = <1>;
        #size-cells = <0>;
index c8e578263ce2654251aacde50bc1a55fe514e264..683fde93c4fb1ab9dac7d9472f1ad808202d7cf4 100644 (file)
@@ -93,7 +93,7 @@ Valid values for pin and group names are:
 
     With some exceptions, these support nvidia,high-speed-mode,
     nvidia,schmitt, nvidia,low-power-mode, nvidia,pull-down-strength,
-    nvidia,pull-up-strength, nvidia,slew_rate-rising, nvidia,slew_rate-falling.
+    nvidia,pull-up-strength, nvidia,slew-rate-rising, nvidia,slew-rate-falling.
 
     drive_ao1, drive_ao2, drive_at1, drive_at2, drive_cdev1, drive_cdev2,
     drive_csus, drive_dap1, drive_dap2, drive_dap3, drive_dap4, drive_dbg,
index c275b70349c11aedb4e8db6a1982c57bfbfcb619..6f426ed7009e5e43461770787225b398fe68e67f 100644 (file)
@@ -83,7 +83,7 @@ Valid values for pin and group names are:
   drive groups:
 
     These all support nvidia,pull-down-strength, nvidia,pull-up-strength,
-    nvidia,slew_rate-rising, nvidia,slew_rate-falling. Most but not all
+    nvidia,slew-rate-rising, nvidia,slew-rate-falling. Most but not all
     support nvidia,high-speed-mode, nvidia,schmitt, nvidia,low-power-mode.
 
     ao1, ao2, at1, at2, at3, at4, at5, cdev1, cdev2, cec, crt, csus, dap1,
diff --git a/Documentation/devicetree/bindings/sound/ak4104.txt b/Documentation/devicetree/bindings/sound/ak4104.txt
new file mode 100644 (file)
index 0000000..b902ee3
--- /dev/null
@@ -0,0 +1,22 @@
+AK4104 S/PDIF transmitter
+
+This device supports SPI mode only.
+
+Required properties:
+
+  - compatible : "asahi-kasei,ak4104"
+
+  - reg : The chip select number on the SPI bus
+
+Optional properties:
+
+  - reset-gpio : a GPIO spec for the reset pin. If specified, it will be
+                deasserted before communication to the device starts.
+
+Example:
+
+spdif: ak4104@0 {
+       compatible = "asahi-kasei,ak4104";
+       reg = <0>;
+       spi-max-frequency = <5000000>;
+};
diff --git a/Documentation/devicetree/bindings/sound/atmel-at91sam9g20ek-wm8731-audio.txt b/Documentation/devicetree/bindings/sound/atmel-at91sam9g20ek-wm8731-audio.txt
new file mode 100644 (file)
index 0000000..9c5a994
--- /dev/null
@@ -0,0 +1,26 @@
+* Atmel at91sam9g20ek wm8731 audio complex
+
+Required properties:
+  - compatible: "atmel,at91sam9g20ek-wm8731-audio"
+  - atmel,model: The user-visible name of this sound complex.
+  - atmel,audio-routing: A list of the connections between audio components.
+  - atmel,ssc-controller: The phandle of the SSC controller
+  - atmel,audio-codec: The phandle of the WM8731 audio codec
+Optional properties:
+  - pinctrl-names, pinctrl-0: Please refer to pinctrl-bindings.txt
+
+Example:
+sound {
+       compatible = "atmel,at91sam9g20ek-wm8731-audio";
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_pck0_as_mck>;
+
+       atmel,model = "wm8731 @ AT91SAMG20EK";
+
+       atmel,audio-routing =
+               "Ext Spk", "LHPOUT",
+               "Int MIC", "MICIN";
+
+       atmel,ssc-controller = <&ssc0>;
+       atmel,audio-codec = <&wm8731>;
+};
index c81b5fd5a5bc80459a1b2d626c9f20b5a86bfbe9..a850fb9c88eab2156ec89f0c76d8ca59073540f8 100644 (file)
@@ -18,6 +18,8 @@ Optional properties:
 
  - reset-gpio:         a GPIO spec to define which pin is connected to the chip's
                !RESET pin
+ - cirrus,amuteb-eq-bmutec:    When given, the Codec's AMUTEB=BMUTEC flag
+                               is enabled.
 
 Examples:
 
index 65dec876cb2d792813abc050833950ef48b53a66..fd40c852d7c7e18c12e5fabc49f0b141614267ac 100644 (file)
@@ -12,7 +12,7 @@ Required properties:
 
 Optional properties:
 - ti,dmic: phandle for the OMAP dmic node if the machine have it connected
-- ti,jack_detection: Need to be set to <1> if the board capable to detect jack
+- ti,jack_detection: Need to be present if the board capable to detect jack
   insertion, removal.
 
 Available audio endpoints for the audio-routing table:
@@ -59,7 +59,7 @@ sound {
        compatible = "ti,abe-twl6040";
        ti,model = "SDP4430";
 
-       ti,jack-detection = <1>;
+       ti,jack-detection;
        ti,mclk-freq = <38400000>;
 
        ti,mcpdm = <&mcpdm>;
index a1793d670cd01bd374eddf54ffdfc768504291ff..3844d21d6ca32223838b7856a2f353bf56ef2417 100644 (file)
@@ -33,7 +33,7 @@ Table of Contents
   2    Modifying System Parameters
 
   3    Per-Process Parameters
-  3.1  /proc/<pid>/oom_score_adj - Adjust the oom-killer
+  3.1  /proc/<pid>/oom_adj & /proc/<pid>/oom_score_adj - Adjust the oom-killer
                                                                score
   3.2  /proc/<pid>/oom_score - Display current oom-killer score
   3.3  /proc/<pid>/io - Display the IO accounting fields
@@ -1320,10 +1320,10 @@ of the kernel.
 CHAPTER 3: PER-PROCESS PARAMETERS
 ------------------------------------------------------------------------------
 
-3.1 /proc/<pid>/oom_score_adj- Adjust the oom-killer score
+3.1 /proc/<pid>/oom_adj & /proc/<pid>/oom_score_adj- Adjust the oom-killer score
 --------------------------------------------------------------------------------
 
-This file can be used to adjust the badness heuristic used to select which
+These file can be used to adjust the badness heuristic used to select which
 process gets killed in out of memory conditions.
 
 The badness heuristic assigns a value to each candidate task ranging from 0
@@ -1361,6 +1361,12 @@ same system, cpuset, mempolicy, or memory controller resources to use at least
 equivalent to discounting 50% of the task's allowed memory from being considered
 as scoring against the task.
 
+For backwards compatibility with previous kernels, /proc/<pid>/oom_adj may also
+be used to tune the badness score.  Its acceptable values range from -16
+(OOM_ADJUST_MIN) to +15 (OOM_ADJUST_MAX) and a special value of -17
+(OOM_DISABLE) to disable oom killing entirely for that task.  Its value is
+scaled linearly with /proc/<pid>/oom_score_adj.
+
 The value of /proc/<pid>/oom_score_adj may be reduced no lower than the last
 value set by a CAP_SYS_RESOURCE process. To reduce the value any lower
 requires CAP_SYS_RESOURCE.
@@ -1375,7 +1381,9 @@ minimal amount of work.
 -------------------------------------------------------------
 
 This file can be used to check the current score used by the oom-killer is for
-any given <pid>.
+any given <pid>. Use it together with /proc/<pid>/oom_score_adj to tune which
+process should be killed in an out-of-memory situation.
+
 
 3.3  /proc/<pid>/io - Display the IO accounting fields
 -------------------------------------------------------
index 7eceaff63f5ffb8f45748d0cb1f46b864652b69a..815b711bcd85007569918048b2d3e36fe20fea19 100644 (file)
  High level behavior (mixed):
  ============================
 
- kernel(driver): calls request_firmware(&fw_entry, $FIRMWARE, device)
-
- userspace:
+ 1), kernel(driver):
+       - calls request_firmware(&fw_entry, $FIRMWARE, device)
+       - kernel searchs the fimware image with name $FIRMWARE directly
+       in the below search path of root filesystem:
+               "/lib/firmware/updates/" UTS_RELEASE,
+               "/lib/firmware/updates",
+               "/lib/firmware/" UTS_RELEASE,
+               "/lib/firmware"
+       - If found, goto 7), else goto 2)
+
+ 2), userspace:
        - /sys/class/firmware/xxx/{loading,data} appear.
        - hotplug gets called with a firmware identifier in $FIRMWARE
          and the usual hotplug environment.
                - hotplug: echo 1 > /sys/class/firmware/xxx/loading
 
- kernel: Discard any previous partial load.
3), kernel: Discard any previous partial load.
 
- userspace:
4), userspace:
                - hotplug: cat appropriate_firmware_image > \
                                        /sys/class/firmware/xxx/data
 
- kernel: grows a buffer in PAGE_SIZE increments to hold the image as it
5), kernel: grows a buffer in PAGE_SIZE increments to hold the image as it
         comes in.
 
- userspace:
6), userspace:
                - hotplug: echo 0 > /sys/class/firmware/xxx/loading
 
- kernel: request_firmware() returns and the driver has the firmware
7), kernel: request_firmware() returns and the driver has the firmware
         image in fw_entry->{data,size}. If something went wrong
         request_firmware() returns non-zero and fw_entry is set to
         NULL.
 
- kernel(driver): Driver code calls release_firmware(fw_entry) releasing
8), kernel(driver): Driver code calls release_firmware(fw_entry) releasing
                 the firmware image and any related resource.
 
  High level behavior (driver code):
index a92918e0bd6946f760af42cd984a28ee0e2db642..80654813d04afdf1e76d8388c8c51a1fb31ae825 100644 (file)
@@ -10,7 +10,7 @@ Supported chips:
   BIOS and Kernel Developer's Guide (BKDG) For AMD Family 15h Processors
     (not yet published)
 
-Author: Andreas Herrmann <andreas.herrmann3@amd.com>
+Author: Andreas Herrmann <herrmann.der.user@googlemail.com>
 
 Description
 -----------
index 4164f5c02e4bbdf406956818fc34b8306610ba55..f310edec8a776f0a8ffb4a943a386ea45990b1a6 100644 (file)
@@ -164,4 +164,4 @@ read the CRC recorded by the NIC on receipt of the packet.
 This requests that the NIC receive all possible frames, including errored
 frames (such as bad FCS, etc).  This can be helpful when sniffing a link with
 bad packets on it.  Some NICs may receive more packets if also put into normal
-PROMISC mdoe.
+PROMISC mode.
index 5b34b762d7d5139a8cf0a9a8eacf739cae279a5b..6d993510f091c2088877ccfc1edf15474c5c723f 100644 (file)
@@ -32,7 +32,7 @@ no entry is in the forwarding table.
   # ip link delete vxlan0
 
 3. Show vxlan info
-  # ip -d show vxlan0
+  # ip -d link show vxlan0
 
 It is possible to create, destroy and display the vxlan
 forwarding table using the new bridge command.
@@ -41,7 +41,7 @@ forwarding table using the new bridge command.
   # bridge fdb add to 00:17:42:8a:b4:05 dst 192.19.0.2 dev vxlan0
 
 2. Delete forwarding table entry
-  # bridge fdb delete 00:17:42:8a:b4:05
+  # bridge fdb delete 00:17:42:8a:b4:05 dev vxlan0
 
 3. Show forwarding table
   # bridge fdb show dev vxlan0
diff --git a/Documentation/zh_CN/IRQ.txt b/Documentation/zh_CN/IRQ.txt
new file mode 100644 (file)
index 0000000..956026d
--- /dev/null
@@ -0,0 +1,39 @@
+Chinese translated version of Documentation/IRQ.txt
+
+If you have any comment or update to the content, please contact the
+original document maintainer directly.  However, if you have a problem
+communicating in English you can also ask the Chinese maintainer for
+help.  Contact the Chinese maintainer if this translation is outdated
+or if there is a problem with the translation.
+
+Maintainer: Eric W. Biederman <ebiederman@xmission.com>
+Chinese maintainer: Fu Wei <tekkamanninja@gmail.com>
+---------------------------------------------------------------------
+Documentation/IRQ.txt 的中文翻译
+
+如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文
+交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻
+译存在问题,请联系中文版维护者。
+英文版维护者: Eric W. Biederman <ebiederman@xmission.com>
+中文版维护者: 傅炜 Fu Wei <tekkamanninja@gmail.com>
+中文版翻译者: 傅炜 Fu Wei <tekkamanninja@gmail.com>
+中文版校译者: 傅炜 Fu Wei <tekkamanninja@gmail.com>
+
+
+以下为正文
+---------------------------------------------------------------------
+何为 IRQ?
+
+一个 IRQ 是来自某个设备的一个中断请求。目前,它们可以来自一个硬件引脚,
+或来自一个数据包。多个设备可能连接到同个硬件引脚,从而共享一个 IRQ。
+
+一个 IRQ 编号是用于告知硬件中断源的内核标识。通常情况下,这是一个
+全局 irq_desc 数组的索引,但是除了在 linux/interrupt.h 中的实现,
+具体的细节是体系结构特定的。
+
+一个 IRQ 编号是设备上某个可能的中断源的枚举。通常情况下,枚举的编号是
+该引脚在系统内中断控制器的所有输入引脚中的编号。对于 ISA 总线中的情况,
+枚举的是在两个 i8259 中断控制器中 16 个输入引脚。
+
+架构可以对 IRQ 编号指定额外的含义,在硬件涉及任何手工配置的情况下,
+是被提倡的。ISA 的 IRQ 是一个分配这类额外含义的典型例子。
diff --git a/Documentation/zh_CN/arm64/booting.txt b/Documentation/zh_CN/arm64/booting.txt
new file mode 100644 (file)
index 0000000..28fa325
--- /dev/null
@@ -0,0 +1,156 @@
+Chinese translated version of Documentation/arm64/booting.txt
+
+If you have any comment or update to the content, please contact the
+original document maintainer directly.  However, if you have a problem
+communicating in English you can also ask the Chinese maintainer for
+help.  Contact the Chinese maintainer if this translation is outdated
+or if there is a problem with the translation.
+
+Maintainer: Will Deacon <will.deacon@arm.com>
+Chinese maintainer: Fu Wei <tekkamanninja@gmail.com>
+---------------------------------------------------------------------
+Documentation/arm64/booting.txt 的中文翻译
+
+如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文
+交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻
+译存在问题,请联系中文版维护者。
+
+英文版维护者: Will Deacon <will.deacon@arm.com>
+中文版维护者: 傅炜  Fu Wei <tekkamanninja@gmail.com>
+中文版翻译者: 傅炜  Fu Wei <tekkamanninja@gmail.com>
+中文版校译者: 傅炜  Fu Wei <tekkamanninja@gmail.com>
+
+以下为正文
+---------------------------------------------------------------------
+                       启动 AArch64 Linux
+                       ==================
+
+作者: Will Deacon <will.deacon@arm.com>
+日期: 2012 年 09 月 07 日
+
+本文档基于 Russell King 的 ARM 启动文档,且适用于所有公开发布的
+AArch64 Linux 内核代码。
+
+AArch64 异常模型由多个异常级别(EL0 - EL3)组成,对于 EL0 和 EL1
+异常级有对应的安全和非安全模式。EL2 是系统管理级,且仅存在于
+非安全模式下。EL3 是最高特权级,且仅存在于安全模式下。
+
+基于本文档的目的,我们将简单地使用‘引导装载程序’(‘boot loader’)
+这个术语来定义在将控制权交给 Linux 内核前 CPU 上执行的所有软件。
+这可能包含安全监控和系统管理代码,或者它可能只是一些用于准备最小启动
+环境的指令。
+
+基本上,引导装载程序(至少)应实现以下操作:
+
+1、设置和初始化 RAM
+2、设置设备树数据
+3、解压内核映像
+4、调用内核映像
+
+
+1、设置和初始化 RAM
+-----------------
+
+必要性: 强制
+
+引导装载程序应该找到并初始化系统中所有内核用于保持系统变量数据的 RAM。
+这个操作的执行是设备依赖的。(它可能使用内部算法来自动定位和计算所有
+RAM,或可能使用对这个设备已知的 RAM 信息,还可能使用任何引导装载程序
+设计者想到的匹配方法。)
+
+
+2、设置设备树数据
+---------------
+
+必要性: 强制
+
+设备树数据块(dtb)大小必须不大于 2 MB,且位于从内核映像起始算起第一个
+512MB 内的 2MB 边界上。这使得内核可以通过初始页表中的单个节描述符来
+映射此数据块。
+
+
+3、解压内核映像
+-------------
+
+必要性: 可选
+
+AArch64 内核当前没有提供自解压代码,因此如果使用了压缩内核映像文件
+(比如 Image.gz),则需要通过引导装载程序(使用 gzip 等)来进行解压。
+若引导装载程序没有实现这个需求,就要使用非压缩内核映像文件。
+
+
+4、调用内核映像
+-------------
+
+必要性: 强制
+
+已解压的内核映像包含一个 32 字节的头,内容如下:
+
+  u32 magic    = 0x14000008;   /* 跳转到 stext, 小端 */
+  u32 res0     = 0;            /* 保留 */
+  u64 text_offset;             /* 映像装载偏移 */
+  u64 res1     = 0;            /* 保留 */
+  u64 res2     = 0;            /* 保留 */
+
+映像必须位于系统 RAM 起始处的特定偏移(当前是 0x80000)。系统 RAM
+的起始地址必须是以 2MB 对齐的。
+
+在跳转入内核前,必须符合以下状态:
+
+- 停止所有 DMA 设备,这样内存数据就不会因为虚假网络包或磁盘数据而
+  被破坏。这可能可以节省你许多的调试时间。
+
+- 主 CPU 通用寄存器设置
+  x0 = 系统 RAM 中设备树数据块(dtb)的物理地址。
+  x1 = 0 (保留,将来可能使用)
+  x2 = 0 (保留,将来可能使用)
+  x3 = 0 (保留,将来可能使用)
+
+- CPU 模式
+  所有形式的中断必须在 PSTATE.DAIF 中被屏蔽(Debug、SError、IRQ
+  和 FIQ)。
+  CPU 必须处于 EL2(推荐,可访问虚拟化扩展)或非安全 EL1 模式下。
+
+- 高速缓存、MMU
+  MMU 必须关闭。
+  指令缓存开启或关闭都可以。
+  数据缓存必须关闭且无效。
+  外部高速缓存(如果存在)必须配置并禁用。
+
+- 架构计时器
+  CNTFRQ 必须设定为计时器的频率。
+  如果在 EL1 模式下进入内核,则 CNTHCTL_EL2 中的 EL1PCTEN (bit 0)
+  必须置位。
+
+- 一致性
+  通过内核启动的所有 CPU 在内核入口地址上必须处于相同的一致性域中。
+  这可能要根据具体实现来定义初始化过程,以使能每个CPU上对维护操作的
+  接收。
+
+- 系统寄存器
+  在进入内核映像的异常级中,所有构架中可写的系统寄存器必须通过软件
+  在一个更高的异常级别下初始化,以防止在 未知 状态下运行。
+
+引导装载程序必须在每个 CPU 处于以下状态时跳入内核入口:
+
+- 主 CPU 必须直接跳入内核映像的第一条指令。通过此 CPU 传递的设备树
+  数据块必须在每个 CPU 节点中包含以下内容:
+
+    1、‘enable-method’属性。目前,此字段支持的值仅为字符串“spin-table”。
+
+    2、‘cpu-release-addr’标识一个 64-bit、初始化为零的内存位置。
+
+  引导装载程序必须生成这些设备树属性,并在跳入内核入口之前将其插入
+  数据块。
+
+- 任何辅助 CPU 必须在内存保留区(通过设备树中的 /memreserve/ 域传递
+  给内核)中自旋于内核之外,轮询它们的 cpu-release-addr 位置(必须
+  包含在保留区中)。可通过插入 wfe 指令来降低忙循环开销,而主 CPU 将
+  发出 sev 指令。当对 cpu-release-addr 所指位置的读取操作返回非零值
+  时,CPU 必须直接跳入此值所指向的地址。
+
+- 辅助 CPU 通用寄存器设置
+  x0 = 0 (保留,将来可能使用)
+  x1 = 0 (保留,将来可能使用)
+  x2 = 0 (保留,将来可能使用)
+  x3 = 0 (保留,将来可能使用)
diff --git a/Documentation/zh_CN/arm64/memory.txt b/Documentation/zh_CN/arm64/memory.txt
new file mode 100644 (file)
index 0000000..83b5193
--- /dev/null
@@ -0,0 +1,93 @@
+Chinese translated version of Documentation/arm64/memory.txt
+
+If you have any comment or update to the content, please contact the
+original document maintainer directly.  However, if you have a problem
+communicating in English you can also ask the Chinese maintainer for
+help.  Contact the Chinese maintainer if this translation is outdated
+or if there is a problem with the translation.
+
+Maintainer: Catalin Marinas <catalin.marinas@arm.com>
+Chinese maintainer: Fu Wei <tekkamanninja@gmail.com>
+---------------------------------------------------------------------
+Documentation/arm64/memory.txt 的中文翻译
+
+如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文
+交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻
+译存在问题,请联系中文版维护者。
+
+英文版维护者: Catalin Marinas <catalin.marinas@arm.com>
+中文版维护者: 傅炜  Fu Wei <tekkamanninja@gmail.com>
+中文版翻译者: 傅炜  Fu Wei <tekkamanninja@gmail.com>
+中文版校译者: 傅炜  Fu Wei <tekkamanninja@gmail.com>
+
+以下为正文
+---------------------------------------------------------------------
+                    Linux 在 AArch64 中的内存布局
+                    ===========================
+
+作者: Catalin Marinas <catalin.marinas@arm.com>
+日期: 2012 年 02 月 20 日
+
+本文档描述 AArch64 Linux 内核所使用的虚拟内存布局。此构架可以实现
+页大小为 4KB 的 4 级转换表和页大小为 64KB 的 3 级转换表。
+
+AArch64 Linux 使用页大小为 4KB 的 3 级转换表配置,对于用户和内核
+都有 39-bit (512GB) 的虚拟地址空间。对于页大小为 64KB的配置,仅
+使用 2 级转换表,但内存布局相同。
+
+用户地址空间的 63:39 位为 0,而内核地址空间的相应位为 1。TTBRx 的
+选择由虚拟地址的 63 位给出。swapper_pg_dir 仅包含内核(全局)映射,
+而用户 pgd 仅包含用户(非全局)映射。swapper_pgd_dir 地址被写入
+TTBR1 中,且从不写入 TTBR0。
+
+
+AArch64 Linux 内存布局:
+
+起始地址                   结束地址                    大小          用途
+-----------------------------------------------------------------------
+0000000000000000       0000007fffffffff         512GB          用户空间
+
+ffffff8000000000       ffffffbbfffcffff        ~240GB          vmalloc
+
+ffffffbbfffd0000       ffffffbcfffdffff          64KB          [防护页]
+
+ffffffbbfffe0000       ffffffbcfffeffff          64KB          PCI I/O 空间
+
+ffffffbbffff0000       ffffffbcffffffff          64KB          [防护页]
+
+ffffffbc00000000       ffffffbdffffffff           8GB          vmemmap
+
+ffffffbe00000000       ffffffbffbffffff          ~8GB          [防护页,未来用于 vmmemap]
+
+ffffffbffc000000       ffffffbfffffffff          64MB          模块
+
+ffffffc000000000       ffffffffffffffff         256GB          内存空间
+
+
+4KB 页大小的转换表查找:
+
++--------+--------+--------+--------+--------+--------+--------+--------+
+|63    56|55    48|47    40|39    32|31    24|23    16|15     8|7      0|
++--------+--------+--------+--------+--------+--------+--------+--------+
+ |                 |         |         |         |         |
+ |                 |         |         |         |         v
+ |                 |         |         |         |   [11:0]  页内偏移
+ |                 |         |         |         +-> [20:12] L3 索引
+ |                 |         |         +-----------> [29:21] L2 索引
+ |                 |         +---------------------> [38:30] L1 索引
+ |                 +-------------------------------> [47:39] L0 索引 (未使用)
+ +-------------------------------------------------> [63] TTBR0/1
+
+
+64KB 页大小的转换表查找:
+
++--------+--------+--------+--------+--------+--------+--------+--------+
+|63    56|55    48|47    40|39    32|31    24|23    16|15     8|7      0|
++--------+--------+--------+--------+--------+--------+--------+--------+
+ |                 |    |               |              |
+ |                 |    |               |              v
+ |                 |    |               |            [15:0]  页内偏移
+ |                 |    |               +----------> [28:16] L3 索引
+ |                 |    +--------------------------> [41:29] L2 索引 (仅使用 38:29 )
+ |                 +-------------------------------> [47:42] L1 索引 (未使用)
+ +-------------------------------------------------> [63] TTBR0/1
index 027ec2bfa135d4f5af20801b020c52d1f66a3f3f..9386a63ea8f63b653b683379ea54c7bd91eb72ec 100644 (file)
@@ -503,7 +503,7 @@ F:  include/linux/altera_uart.h
 F:     include/linux/altera_jtaguart.h
 
 AMD FAM15H PROCESSOR POWER MONITORING DRIVER
-M:     Andreas Herrmann <andreas.herrmann3@amd.com>
+M:     Andreas Herrmann <herrmann.der.user@googlemail.com>
 L:     lm-sensors@lm-sensors.org
 S:     Maintained
 F:     Documentation/hwmon/fam15h_power
@@ -526,17 +526,17 @@ F:        drivers/video/geode/
 F:     arch/x86/include/asm/geode.h
 
 AMD IOMMU (AMD-VI)
-M:     Joerg Roedel <joerg.roedel@amd.com>
+M:     Joerg Roedel <joro@8bytes.org>
 L:     iommu@lists.linux-foundation.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git
-S:     Supported
+S:     Maintained
 F:     drivers/iommu/amd_iommu*.[ch]
 F:     include/linux/amd-iommu.h
 
 AMD MICROCODE UPDATE SUPPORT
-M:     Andreas Herrmann <andreas.herrmann3@amd.com>
+M:     Andreas Herrmann <herrmann.der.user@googlemail.com>
 L:     amd64-microcode@amd64.org
-S:     Supported
+S:     Maintained
 F:     arch/x86/kernel/microcode_amd.c
 
 AMS (Apple Motion Sensor) DRIVER
@@ -637,6 +637,13 @@ W: http://www.arm.linux.org.uk/
 S:     Maintained
 F:     arch/arm/
 
+ARM SUB-ARCHITECTURES
+L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S:     MAINTAINED
+F:     arch/arm/mach-*/
+F:     arch/arm/plat-*/
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc.git
+
 ARM PRIMECELL AACI PL041 DRIVER
 M:     Russell King <linux@arm.linux.org.uk>
 S:     Maintained
@@ -834,6 +841,14 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/kristoffer/linux-hpc.git
 F:     arch/arm/mach-sa1100/jornada720.c
 F:     arch/arm/mach-sa1100/include/mach/jornada720.h
 
+ARM/IGEP MACHINE SUPPORT
+M:     Enric Balletbo i Serra <eballetbo@gmail.com>
+M:     Javier Martinez Canillas <javier@dowhile0.org>
+L:     linux-omap@vger.kernel.org
+L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S:     Maintained
+F:     arch/arm/mach-omap2/board-igep0020.c
+
 ARM/INCOME PXA270 SUPPORT
 M:     Marek Vasut <marek.vasut@gmail.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -2500,6 +2515,7 @@ M:        Joonyoung Shim <jy0922.shim@samsung.com>
 M:     Seung-Woo Kim <sw0312.kim@samsung.com>
 M:     Kyungmin Park <kyungmin.park@samsung.com>
 L:     dri-devel@lists.freedesktop.org
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos.git
 S:     Supported
 F:     drivers/gpu/drm/exynos
 F:     include/drm/exynos*
@@ -2700,10 +2716,10 @@ F:      include/linux/edac.h
 
 EDAC-AMD64
 M:     Doug Thompson <dougthompson@xmission.com>
-M:     Borislav Petkov <borislav.petkov@amd.com>
+M:     Borislav Petkov <bp@alien8.de>
 L:     linux-edac@vger.kernel.org
 W:     bluesmoke.sourceforge.net
-S:     Supported
+S:     Maintained
 F:     drivers/edac/amd64_edac*
 
 EDAC-E752X
@@ -2802,6 +2818,7 @@ F:        sound/usb/misc/ua101.c
 EXTENSIBLE FIRMWARE INTERFACE (EFI)
 M:     Matt Fleming <matt.fleming@intel.com>
 L:     linux-efi@vger.kernel.org
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mfleming/efi.git
 S:     Maintained
 F:     Documentation/x86/efi-stub.txt
 F:     arch/ia64/kernel/efi.c
@@ -3589,6 +3606,49 @@ F:       drivers/hid/hid-hyperv.c
 F:     drivers/net/hyperv/
 F:     drivers/staging/hv/
 
+I2C OVER PARALLEL PORT
+M:     Jean Delvare <khali@linux-fr.org>
+L:     linux-i2c@vger.kernel.org
+S:     Maintained
+F:     Documentation/i2c/busses/i2c-parport
+F:     Documentation/i2c/busses/i2c-parport-light
+F:     drivers/i2c/busses/i2c-parport.c
+F:     drivers/i2c/busses/i2c-parport-light.c
+
+I2C/SMBUS CONTROLLER DRIVERS FOR PC
+M:     Jean Delvare <khali@linux-fr.org>
+L:     linux-i2c@vger.kernel.org
+S:     Maintained
+F:     Documentation/i2c/busses/i2c-ali1535
+F:     Documentation/i2c/busses/i2c-ali1563
+F:     Documentation/i2c/busses/i2c-ali15x3
+F:     Documentation/i2c/busses/i2c-amd756
+F:     Documentation/i2c/busses/i2c-amd8111
+F:     Documentation/i2c/busses/i2c-i801
+F:     Documentation/i2c/busses/i2c-nforce2
+F:     Documentation/i2c/busses/i2c-piix4
+F:     Documentation/i2c/busses/i2c-sis5595
+F:     Documentation/i2c/busses/i2c-sis630
+F:     Documentation/i2c/busses/i2c-sis96x
+F:     Documentation/i2c/busses/i2c-via
+F:     Documentation/i2c/busses/i2c-viapro
+F:     drivers/i2c/busses/i2c-ali1535.c
+F:     drivers/i2c/busses/i2c-ali1563.c
+F:     drivers/i2c/busses/i2c-ali15x3.c
+F:     drivers/i2c/busses/i2c-amd756.c
+F:     drivers/i2c/busses/i2c-amd756-s4882.c
+F:     drivers/i2c/busses/i2c-amd8111.c
+F:     drivers/i2c/busses/i2c-i801.c
+F:     drivers/i2c/busses/i2c-isch.c
+F:     drivers/i2c/busses/i2c-nforce2.c
+F:     drivers/i2c/busses/i2c-nforce2-s4985.c
+F:     drivers/i2c/busses/i2c-piix4.c
+F:     drivers/i2c/busses/i2c-sis5595.c
+F:     drivers/i2c/busses/i2c-sis630.c
+F:     drivers/i2c/busses/i2c-sis96x.c
+F:     drivers/i2c/busses/i2c-via.c
+F:     drivers/i2c/busses/i2c-viapro.c
+
 I2C/SMBUS STUB DRIVER
 M:     "Mark M. Hoffman" <mhoffman@lightlink.com>
 L:     linux-i2c@vger.kernel.org
@@ -3596,9 +3656,8 @@ S:        Maintained
 F:     drivers/i2c/busses/i2c-stub.c
 
 I2C SUBSYSTEM
-M:     "Jean Delvare (PC drivers, core)" <khali@linux-fr.org>
+M:     Wolfram Sang <w.sang@pengutronix.de>
 M:     "Ben Dooks (embedded platforms)" <ben-linux@fluff.org>
-M:     "Wolfram Sang (embedded platforms)" <w.sang@pengutronix.de>
 L:     linux-i2c@vger.kernel.org
 W:     http://i2c.wiki.kernel.org/
 T:     quilt kernel.org/pub/linux/kernel/people/jdelvare/linux-2.6/jdelvare-i2c/
@@ -3609,6 +3668,13 @@ F:       drivers/i2c/
 F:     include/linux/i2c.h
 F:     include/linux/i2c-*.h
 
+I2C-TAOS-EVM DRIVER
+M:     Jean Delvare <khali@linux-fr.org>
+L:     linux-i2c@vger.kernel.org
+S:     Maintained
+F:     Documentation/i2c/busses/i2c-taos-evm
+F:     drivers/i2c/busses/i2c-taos-evm.c
+
 I2C-TINY-USB DRIVER
 M:     Till Harbaum <till@harbaum.org>
 L:     linux-i2c@vger.kernel.org
@@ -3695,7 +3761,7 @@ S:        Maintained
 F:     drivers/platform/x86/ideapad-laptop.c
 
 IDE/ATAPI DRIVERS
-M:     Borislav Petkov <petkovbb@gmail.com>
+M:     Borislav Petkov <bp@alien8.de>
 L:     linux-ide@vger.kernel.org
 S:     Maintained
 F:     Documentation/cdrom/ide-cd
@@ -4222,8 +4288,8 @@ F:        include/linux/lockd/
 F:     include/linux/sunrpc/
 
 KERNEL VIRTUAL MACHINE (KVM)
-M:     Avi Kivity <avi@redhat.com>
 M:     Marcelo Tosatti <mtosatti@redhat.com>
+M:     Gleb Natapov <gleb@redhat.com>
 L:     kvm@vger.kernel.org
 W:     http://kvm.qumranet.com
 S:     Supported
@@ -5061,7 +5127,13 @@ T:       git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git
 S:     Odd Fixes
 F:     drivers/net/
 F:     include/linux/if_*
-F:     include/linux/*device.h
+F:     include/linux/netdevice.h
+F:     include/linux/arcdevice.h
+F:     include/linux/etherdevice.h
+F:     include/linux/fcdevice.h
+F:     include/linux/fddidevice.h
+F:     include/linux/hippidevice.h
+F:     include/linux/inetdevice.h
 
 NETXEN (1/10) GbE SUPPORT
 M:     Sony Chacko <sony.chacko@qlogic.com>
@@ -5349,7 +5421,7 @@ S:        Maintained
 F:     sound/drivers/opl4/
 
 OPROFILE
-M:     Robert Richter <robert.richter@amd.com>
+M:     Robert Richter <rric@kernel.org>
 L:     oprofile-list@lists.sf.net
 S:     Maintained
 F:     arch/*/include/asm/oprofile*.h
@@ -5633,7 +5705,7 @@ S:        Maintained
 F:     drivers/pinctrl/spear/
 
 PKTCDVD DRIVER
-M:     Peter Osterlund <petero2@telia.com>
+M:     Jiri Kosina <jkosina@suse.cz>
 S:     Maintained
 F:     drivers/block/pktcdvd.c
 F:     include/linux/pktcdvd.h
@@ -7195,6 +7267,14 @@ L:       linux-xtensa@linux-xtensa.org
 S:     Maintained
 F:     arch/xtensa/
 
+THERMAL
+M:      Zhang Rui <rui.zhang@intel.com>
+L:      linux-pm@vger.kernel.org
+T:      git git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux.git
+S:      Supported
+F:      drivers/thermal/
+F:      include/linux/thermal.h
+
 THINKPAD ACPI EXTRAS DRIVER
 M:     Henrique de Moraes Holschuh <ibm-acpi@hmh.eng.br>
 L:     ibm-acpi-devel@lists.sourceforge.net
@@ -7872,13 +7952,6 @@ M:       Roger Luethi <rl@hellgate.ch>
 S:     Maintained
 F:     drivers/net/ethernet/via/via-rhine.c
 
-VIAPRO SMBUS DRIVER
-M:     Jean Delvare <khali@linux-fr.org>
-L:     linux-i2c@vger.kernel.org
-S:     Maintained
-F:     Documentation/i2c/busses/i2c-viapro
-F:     drivers/i2c/busses/i2c-viapro.c
-
 VIA SD/MMC CARD CONTROLLER DRIVER
 M:     Bruce Chang <brucechang@via.com.tw>
 M:     Harald Welte <HaraldWelte@viatech.com>
@@ -8133,7 +8206,7 @@ F:        drivers/platform/x86
 
 X86 MCE INFRASTRUCTURE
 M:     Tony Luck <tony.luck@intel.com>
-M:     Borislav Petkov <bp@amd64.org>
+M:     Borislav Petkov <bp@alien8.de>
 L:     linux-edac@vger.kernel.org
 S:     Maintained
 F:     arch/x86/kernel/cpu/mcheck/*
index 14c93b39b9291a45d07bd6c4afe8fe792ede241f..3d2fc460b22f38b6d37ba31016a96c6926bdc0b1 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 3
 PATCHLEVEL = 7
 SUBLEVEL = 0
-EXTRAVERSION = -rc2
+EXTRAVERSION = -rc7
 NAME = Terrified Chipmunk
 
 # *DOCUMENTATION*
index 4554ecbff7c6527be35fea7d20e255cc0770b653..1f8c72959fb6c7a1a9891833ae8d9b037cb179d5 100644 (file)
@@ -7,6 +7,7 @@
 #include <asm/processor.h>
 #include <asm/types.h>
 #include <asm/hwrpb.h>
+#include <asm/sysinfo.h>
 #endif
 
 #ifndef __ASSEMBLY__
@@ -21,6 +22,7 @@ struct thread_info {
        mm_segment_t            addr_limit;     /* thread address space */
        unsigned                cpu;            /* current CPU */
        int                     preempt_count; /* 0 => preemptable, <0 => BUG */
+       unsigned int            status;         /* thread-synchronous flags */
 
        int bpt_nsaved;
        unsigned long bpt_addr[2];              /* breakpoint handling  */
@@ -63,8 +65,6 @@ register struct thread_info *__current_thread_info __asm__("$8");
  * - these are process state flags and used from assembly
  * - pending work-to-be-done flags come first and must be assigned to be
  *   within bits 0 to 7 to fit in and immediate operand.
- * - ALPHA_UAC_SHIFT below must be kept consistent with the unaligned
- *   control flags.
  *
  * TIF_SYSCALL_TRACE is known to be 0 via blbs.
  */
@@ -72,18 +72,12 @@ register struct thread_info *__current_thread_info __asm__("$8");
 #define TIF_NOTIFY_RESUME      1       /* callback before returning to user */
 #define TIF_SIGPENDING         2       /* signal pending */
 #define TIF_NEED_RESCHED       3       /* rescheduling necessary */
-#define TIF_POLLING_NRFLAG     8       /* poll_idle is polling NEED_RESCHED */
 #define TIF_DIE_IF_KERNEL      9       /* dik recursion lock */
-#define TIF_UAC_NOPRINT                10      /* ! Preserve sequence of following */
-#define TIF_UAC_NOFIX          11      /* ! flags as they match            */
-#define TIF_UAC_SIGBUS         12      /* ! userspace part of 'osf_sysinfo' */
 #define TIF_MEMDIE             13      /* is terminating due to OOM killer */
-#define TIF_RESTORE_SIGMASK    14      /* restore signal mask in do_signal */
 
 #define _TIF_SYSCALL_TRACE     (1<<TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING                (1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED      (1<<TIF_NEED_RESCHED)
-#define _TIF_POLLING_NRFLAG    (1<<TIF_POLLING_NRFLAG)
 #define _TIF_NOTIFY_RESUME     (1<<TIF_NOTIFY_RESUME)
 
 /* Work to do on interrupt/exception return.  */
@@ -94,29 +88,63 @@ register struct thread_info *__current_thread_info __asm__("$8");
 #define _TIF_ALLWORK_MASK      (_TIF_WORK_MASK         \
                                 | _TIF_SYSCALL_TRACE)
 
-#define ALPHA_UAC_SHIFT                TIF_UAC_NOPRINT
-#define ALPHA_UAC_MASK         (1 << TIF_UAC_NOPRINT | 1 << TIF_UAC_NOFIX | \
-                                1 << TIF_UAC_SIGBUS)
+#define TS_UAC_NOPRINT         0x0001  /* ! Preserve the following three */
+#define TS_UAC_NOFIX           0x0002  /* ! flags as they match          */
+#define TS_UAC_SIGBUS          0x0004  /* ! userspace part of 'osf_sysinfo' */
+#define TS_RESTORE_SIGMASK     0x0008  /* restore signal mask in do_signal() */
+#define TS_POLLING             0x0010  /* idle task polling need_resched,
+                                          skip sending interrupt */
 
-#define SET_UNALIGN_CTL(task,value)    ({                                   \
-       task_thread_info(task)->flags = ((task_thread_info(task)->flags &    \
-               ~ALPHA_UAC_MASK)                                             \
-               | (((value) << ALPHA_UAC_SHIFT)       & (1<<TIF_UAC_NOPRINT))\
-               | (((value) << (ALPHA_UAC_SHIFT + 1)) & (1<<TIF_UAC_SIGBUS)) \
-               | (((value) << (ALPHA_UAC_SHIFT - 1)) & (1<<TIF_UAC_NOFIX)));\
+#define tsk_is_polling(t) (task_thread_info(t)->status & TS_POLLING)
+
+#ifndef __ASSEMBLY__
+#define HAVE_SET_RESTORE_SIGMASK       1
+static inline void set_restore_sigmask(void)
+{
+       struct thread_info *ti = current_thread_info();
+       ti->status |= TS_RESTORE_SIGMASK;
+       WARN_ON(!test_bit(TIF_SIGPENDING, (unsigned long *)&ti->flags));
+}
+static inline void clear_restore_sigmask(void)
+{
+       current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
+}
+static inline bool test_restore_sigmask(void)
+{
+       return current_thread_info()->status & TS_RESTORE_SIGMASK;
+}
+static inline bool test_and_clear_restore_sigmask(void)
+{
+       struct thread_info *ti = current_thread_info();
+       if (!(ti->status & TS_RESTORE_SIGMASK))
+               return false;
+       ti->status &= ~TS_RESTORE_SIGMASK;
+       return true;
+}
+#endif
+
+#define SET_UNALIGN_CTL(task,value)    ({                              \
+       __u32 status = task_thread_info(task)->status & ~UAC_BITMASK;   \
+       if (value & PR_UNALIGN_NOPRINT)                                 \
+               status |= TS_UAC_NOPRINT;                               \
+       if (value & PR_UNALIGN_SIGBUS)                                  \
+               status |= TS_UAC_SIGBUS;                                \
+       if (value & 4)  /* alpha-specific */                            \
+               status |= TS_UAC_NOFIX;                                 \
+       task_thread_info(task)->status = status;                        \
        0; })
 
 #define GET_UNALIGN_CTL(task,value)    ({                              \
-       put_user((task_thread_info(task)->flags & (1 << TIF_UAC_NOPRINT))\
-                 >> ALPHA_UAC_SHIFT                                    \
-                | (task_thread_info(task)->flags & (1 << TIF_UAC_SIGBUS))\
-                >> (ALPHA_UAC_SHIFT + 1)                               \
-                | (task_thread_info(task)->flags & (1 << TIF_UAC_NOFIX))\
-                >> (ALPHA_UAC_SHIFT - 1),                              \
-                (int __user *)(value));                                \
+       __u32 status = task_thread_info(task)->status & ~UAC_BITMASK;   \
+       __u32 res = 0;                                                  \
+       if (status & TS_UAC_NOPRINT)                                    \
+               res |= PR_UNALIGN_NOPRINT;                              \
+       if (status & TS_UAC_SIGBUS)                                     \
+               res |= PR_UNALIGN_SIGBUS;                               \
+       if (status & TS_UAC_NOFIX)                                      \
+               res |= 4;                                               \
+       put_user(res, (int __user *)(value));                           \
        })
 
-#define tsk_is_polling(t) test_tsk_thread_flag(t, TIF_POLLING_NRFLAG)
-
 #endif /* __KERNEL__ */
 #endif /* _ALPHA_THREAD_INFO_H */
index 9eb090582cf1eb2c557e03025bafc73846fde02f..14db93e4c8a83662d459a6ff1a818318dbc61eeb 100644 (file)
@@ -445,7 +445,7 @@ struct procfs_args {
  * unhappy with OSF UFS. [CHECKME]
  */
 static int
-osf_ufs_mount(char *dirname, struct ufs_args __user *args, int flags)
+osf_ufs_mount(const char *dirname, struct ufs_args __user *args, int flags)
 {
        int retval;
        struct cdfs_args tmp;
@@ -465,7 +465,7 @@ osf_ufs_mount(char *dirname, struct ufs_args __user *args, int flags)
 }
 
 static int
-osf_cdfs_mount(char *dirname, struct cdfs_args __user *args, int flags)
+osf_cdfs_mount(const char *dirname, struct cdfs_args __user *args, int flags)
 {
        int retval;
        struct cdfs_args tmp;
@@ -485,7 +485,7 @@ osf_cdfs_mount(char *dirname, struct cdfs_args __user *args, int flags)
 }
 
 static int
-osf_procfs_mount(char *dirname, struct procfs_args __user *args, int flags)
+osf_procfs_mount(const char *dirname, struct procfs_args __user *args, int flags)
 {
        struct procfs_args tmp;
 
@@ -793,8 +793,7 @@ SYSCALL_DEFINE5(osf_getsysinfo, unsigned long, op, void __user *, buffer,
        case GSI_UACPROC:
                if (nbytes < sizeof(unsigned int))
                        return -EINVAL;
-               w = (current_thread_info()->flags >> ALPHA_UAC_SHIFT) &
-                       UAC_BITMASK;
+               w = current_thread_info()->status & UAC_BITMASK;
                if (put_user(w, (unsigned int __user *)buffer))
                        return -EFAULT;
                return 1;
@@ -904,24 +903,20 @@ SYSCALL_DEFINE5(osf_setsysinfo, unsigned long, op, void __user *, buffer,
                break;
 
        case SSI_NVPAIRS: {
-               unsigned long v, w, i;
-               unsigned int old, new;
+               unsigned __user *p = buffer;
+               unsigned i;
                
-               for (i = 0; i < nbytes; ++i) {
+               for (i = 0, p = buffer; i < nbytes; ++i, p += 2) {
+                       unsigned v, w, status;
 
-                       if (get_user(v, 2*i + (unsigned int __user *)buffer))
-                               return -EFAULT;
-                       if (get_user(w, 2*i + 1 + (unsigned int __user *)buffer))
+                       if (get_user(v, p) || get_user(w, p + 1))
                                return -EFAULT;
                        switch (v) {
                        case SSIN_UACPROC:
-                       again:
-                               old = current_thread_info()->flags;
-                               new = old & ~(UAC_BITMASK << ALPHA_UAC_SHIFT);
-                               new = new | (w & UAC_BITMASK) << ALPHA_UAC_SHIFT;
-                               if (cmpxchg(&current_thread_info()->flags,
-                                           old, new) != old)
-                                       goto again;
+                               w &= UAC_BITMASK;
+                               status = current_thread_info()->status;
+                               status = (status & ~UAC_BITMASK) | w;
+                               current_thread_info()->status = status;
                                break;
  
                        default:
index 4054e0ffe2b25a1055deb3946167755dc73fb201..51987dcf79b83904bd6d5d564db39abe7b7c73f3 100644 (file)
@@ -49,7 +49,7 @@ EXPORT_SYMBOL(pm_power_off);
 void
 cpu_idle(void)
 {
-       set_thread_flag(TIF_POLLING_NRFLAG);
+       current_thread_info()->status |= TS_POLLING;
 
        while (1) {
                /* FIXME -- EV6 and LCA45 know how to power down
index 80d987c0e9aa55889aa3b8ed5d8a25fe9309b1c2..272666d006df1ddd67635caf229221c9b92244c6 100644 (file)
@@ -780,17 +780,17 @@ do_entUnaUser(void __user * va, unsigned long opcode,
        /* Check the UAC bits to decide what the user wants us to do
           with the unaliged access.  */
 
-       if (!test_thread_flag (TIF_UAC_NOPRINT)) {
+       if (!(current_thread_info()->status & TS_UAC_NOPRINT)) {
                if (__ratelimit(&ratelimit)) {
                        printk("%s(%d): unaligned trap at %016lx: %p %lx %ld\n",
                               current->comm, task_pid_nr(current),
                               regs->pc - 4, va, opcode, reg);
                }
        }
-       if (test_thread_flag (TIF_UAC_SIGBUS))
+       if ((current_thread_info()->status & TS_UAC_SIGBUS))
                goto give_sigbus;
        /* Not sure why you'd want to use this, but... */
-       if (test_thread_flag (TIF_UAC_NOFIX))
+       if ((current_thread_info()->status & TS_UAC_NOFIX))
                return;
 
        /* Don't bother reading ds in the access check since we already
index 73067efd484530d4021a220fecce329b4752b3c0..ade7e924bef5faaf00de76c0354e025ed4371b35 100644 (file)
@@ -1603,8 +1603,8 @@ config NR_CPUS
        default "4"
 
 config HOTPLUG_CPU
-       bool "Support for hot-pluggable CPUs (EXPERIMENTAL)"
-       depends on SMP && HOTPLUG && EXPERIMENTAL
+       bool "Support for hot-pluggable CPUs"
+       depends on SMP && HOTPLUG
        help
          Say Y here to experiment with turning CPUs off and on.  CPUs
          can be controlled through /sys/devices/system/cpu.
@@ -1645,8 +1645,8 @@ config HZ
        default 100
 
 config THUMB2_KERNEL
-       bool "Compile the kernel in Thumb-2 mode (EXPERIMENTAL)"
-       depends on CPU_V7 && !CPU_V6 && !CPU_V6K && EXPERIMENTAL
+       bool "Compile the kernel in Thumb-2 mode"
+       depends on CPU_V7 && !CPU_V6 && !CPU_V6K
        select AEABI
        select ARM_ASM_UNIFIED
        select ARM_UNWIND
@@ -1850,6 +1850,7 @@ config XEN_DOM0
 config XEN
        bool "Xen guest support on ARM (EXPERIMENTAL)"
        depends on EXPERIMENTAL && ARM && OF
+       depends on CPU_V7 && !CPU_V6
        help
          Say Y if you want to run Linux in a Virtual Machine on Xen on ARM.
 
index f023e3acdfbd8c7c17335cfa9518df05119f4ab7..5f914fca911b77b747dd43569b84a76883abcef7 100644 (file)
@@ -21,8 +21,6 @@ endif
 OBJCOPYFLAGS   :=-O binary -R .comment -S
 GZFLAGS                :=-9
 #KBUILD_CFLAGS +=-pipe
-# Explicitly specifiy 32-bit ARM ISA since toolchain default can be -mthumb:
-KBUILD_CFLAGS  +=$(call cc-option,-marm,)
 
 # Never generate .eh_frame
 KBUILD_CFLAGS  += $(call cc-option,-fno-dwarf2-cfi-asm)
@@ -105,17 +103,20 @@ endif
 ifeq ($(CONFIG_THUMB2_KERNEL),y)
 AFLAGS_AUTOIT  :=$(call as-option,-Wa$(comma)-mimplicit-it=always,-Wa$(comma)-mauto-it)
 AFLAGS_NOWARN  :=$(call as-option,-Wa$(comma)-mno-warn-deprecated,-Wa$(comma)-W)
-CFLAGS_THUMB2  :=-mthumb $(AFLAGS_AUTOIT) $(AFLAGS_NOWARN)
-AFLAGS_THUMB2  :=$(CFLAGS_THUMB2) -Wa$(comma)-mthumb
+CFLAGS_ISA     :=-mthumb $(AFLAGS_AUTOIT) $(AFLAGS_NOWARN)
+AFLAGS_ISA     :=$(CFLAGS_ISA) -Wa$(comma)-mthumb
 # Work around buggy relocation from gas if requested:
 ifeq ($(CONFIG_THUMB2_AVOID_R_ARM_THM_JUMP11),y)
 CFLAGS_MODULE  +=-fno-optimize-sibling-calls
 endif
+else
+CFLAGS_ISA     :=$(call cc-option,-marm,)
+AFLAGS_ISA     :=$(CFLAGS_ISA)
 endif
 
 # Need -Uarm for gcc < 3.x
-KBUILD_CFLAGS  +=$(CFLAGS_ABI) $(CFLAGS_THUMB2) $(arch-y) $(tune-y) $(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,)) -msoft-float -Uarm
-KBUILD_AFLAGS  +=$(CFLAGS_ABI) $(AFLAGS_THUMB2) $(arch-y) $(tune-y) -include asm/unified.h -msoft-float
+KBUILD_CFLAGS  +=$(CFLAGS_ABI) $(CFLAGS_ISA) $(arch-y) $(tune-y) $(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,)) -msoft-float -Uarm
+KBUILD_AFLAGS  +=$(CFLAGS_ABI) $(AFLAGS_ISA) $(arch-y) $(tune-y) -include asm/unified.h -msoft-float
 
 CHECKFLAGS     += -D__arm__
 
index 3fdab016aa5cfdc9132813f4c5be44348fb1c539..9137df539b61c649b218e26d8f56365f289a5c84 100644 (file)
@@ -33,7 +33,7 @@ ifeq ($(CONFIG_XIP_KERNEL),y)
 
 $(obj)/xipImage: vmlinux FORCE
        $(call if_changed,objcopy)
-       @echo '  Kernel: $@ is ready (physical address: $(CONFIG_XIP_PHYS_ADDR))'
+       @$(kecho) '  Kernel: $@ is ready (physical address: $(CONFIG_XIP_PHYS_ADDR))'
 
 $(obj)/Image $(obj)/zImage: FORCE
        @echo 'Kernel configured for XIP (CONFIG_XIP_KERNEL=y)'
@@ -48,14 +48,14 @@ $(obj)/xipImage: FORCE
 
 $(obj)/Image: vmlinux FORCE
        $(call if_changed,objcopy)
-       @echo '  Kernel: $@ is ready'
+       @$(kecho) '  Kernel: $@ is ready'
 
 $(obj)/compressed/vmlinux: $(obj)/Image FORCE
        $(Q)$(MAKE) $(build)=$(obj)/compressed $@
 
 $(obj)/zImage: $(obj)/compressed/vmlinux FORCE
        $(call if_changed,objcopy)
-       @echo '  Kernel: $@ is ready'
+       @$(kecho) '  Kernel: $@ is ready'
 
 endif
 
@@ -90,7 +90,7 @@ fi
 $(obj)/uImage: $(obj)/zImage FORCE
        @$(check_for_multiple_loadaddr)
        $(call if_changed,uimage)
-       @echo '  Image $@ is ready'
+       @$(kecho) '  Image $@ is ready'
 
 $(obj)/bootp/bootp: $(obj)/zImage initrd FORCE
        $(Q)$(MAKE) $(build)=$(obj)/bootp $@
@@ -98,7 +98,7 @@ $(obj)/bootp/bootp: $(obj)/zImage initrd FORCE
 
 $(obj)/bootpImage: $(obj)/bootp/bootp FORCE
        $(call if_changed,objcopy)
-       @echo '  Kernel: $@ is ready'
+       @$(kecho) '  Kernel: $@ is ready'
 
 PHONY += initrd FORCE
 initrd:
index d410581a5a859901b32a49a1f037356c9f22e294..aaa42d8d4f8895233bdaddc00b3bdf69775e0379 100644 (file)
@@ -29,6 +29,7 @@
                tcb0 = &tcb0;
                tcb1 = &tcb1;
                i2c0 = &i2c0;
+               ssc0 = &ssc0;
        };
        cpus {
                cpu@0 {
                                status = "disabled";
                        };
 
+                       ssc0: ssc@fffbc000 {
+                               compatible = "atmel,at91rm9200-ssc";
+                               reg = <0xfffbc000 0x4000>;
+                               interrupts = <14 4 5>;
+                               status = "disable";
+                       };
+
                        adc0: adc@fffe0000 {
                                compatible = "atmel,at91sam9260-adc";
                                reg = <0xfffe0000 0x100>;
index 3e6e5c1abbf37184a44237e464080a52f4312e9f..3b721ee59b109500b688bebff12e098f0aaf05ce 100644 (file)
@@ -25,6 +25,8 @@
                gpio4 = &pioE;
                tcb0 = &tcb0;
                i2c0 = &i2c0;
+               ssc0 = &ssc0;
+               ssc1 = &ssc1;
        };
        cpus {
                cpu@0 {
                                status = "disabled";
                        };
 
+                       ssc0: ssc@fff98000 {
+                               compatible = "atmel,at91rm9200-ssc";
+                               reg = <0xfff98000 0x4000>;
+                               interrupts = <16 4 5>;
+                               status = "disable";
+                       };
+
+                       ssc1: ssc@fff9c000 {
+                               compatible = "atmel,at91rm9200-ssc";
+                               reg = <0xfff9c000 0x4000>;
+                               interrupts = <17 4 5>;
+                               status = "disable";
+                       };
+
                        macb0: ethernet@fffbc000 {
                                compatible = "cdns,at32ap7000-macb", "cdns,macb";
                                reg = <0xfffbc000 0x100>;
index b06c0db273b1fff820543d692b2a0470efe6b8f2..2dcec8de759f97c31780027614f99866bb0c8a58 100644 (file)
 
        ahb {
                apb {
+                       pinctrl@fffff400 {
+                               board {
+                                       pinctrl_pck0_as_mck: pck0_as_mck {
+                                               atmel,pins =
+                                                       <2 1 0x2 0x0>;  /* PC1 periph B */
+                                       };
+
+                               };
+                       };
+
                        dbgu: serial@fffff200 {
                                status = "okay";
                        };
                                atmel,vbus-gpio = <&pioC 5 0>;
                                status = "okay";
                        };
+
+                       ssc0: ssc@fffbc000 {
+                               status = "okay";
+                               pinctrl-0 = <&pinctrl_ssc0_tx>;
+                       };
                };
 
                nand0: nand@40000000 {
                        reg = <0x50>;
                };
 
-               wm8731@1b {
+               wm8731: wm8731@1b {
                        compatible = "wm8731";
                        reg = <0x1b>;
                };
                #size-cells = <0>;
 
                btn3 {
-                       label = "Buttin 3";
+                       label = "Button 3";
                        gpios = <&pioA 30 1>;
                        linux,code = <0x103>;
                        gpio-key,wakeup;
                };
 
                btn4 {
-                       label = "Buttin 4";
+                       label = "Button 4";
                        gpios = <&pioA 31 1>;
                        linux,code = <0x104>;
                        gpio-key,wakeup;
                };
        };
+
+       sound {
+               compatible = "atmel,at91sam9g20ek-wm8731-audio";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_pck0_as_mck>;
+
+               atmel,model = "wm8731 @ AT91SAMG20EK";
+
+               atmel,audio-routing =
+                       "Ext Spk", "LHPOUT",
+                       "Int Mic", "MICIN";
+
+               atmel,ssc-controller = <&ssc0>;
+               atmel,audio-codec = <&wm8731>;
+       };
 };
index 3add030d61f8651fcf5a0476b11423897de71560..acfa207162ff581eaaf063c4d3154a6f658ea177 100644 (file)
@@ -31,6 +31,8 @@
                tcb1 = &tcb1;
                i2c0 = &i2c0;
                i2c1 = &i2c1;
+               ssc0 = &ssc0;
+               ssc1 = &ssc1;
        };
        cpus {
                cpu@0 {
                                status = "disabled";
                        };
 
+                       ssc0: ssc@fff9c000 {
+                               compatible = "atmel,at91sam9g45-ssc";
+                               reg = <0xfff9c000 0x4000>;
+                               interrupts = <16 4 5>;
+                               status = "disable";
+                       };
+
+                       ssc1: ssc@fffa0000 {
+                               compatible = "atmel,at91sam9g45-ssc";
+                               reg = <0xfffa0000 0x4000>;
+                               interrupts = <17 4 5>;
+                               status = "disable";
+                       };
+
                        adc0: adc@fffb0000 {
                                compatible = "atmel,at91sam9260-adc";
                                reg = <0xfffb0000 0x100>;
index 03fc136421c5e31b01649c9caacdaf134bef4560..69667d0ac347f142a51c5acc704e731763ec2144 100644 (file)
@@ -30,6 +30,7 @@
                i2c0 = &i2c0;
                i2c1 = &i2c1;
                i2c2 = &i2c2;
+               ssc0 = &ssc0;
        };
        cpus {
                cpu@0 {
                                interrupts = <1 4 7>;
                        };
 
+                       ssc0: ssc@f0010000 {
+                               compatible = "atmel,at91sam9g45-ssc";
+                               reg = <0xf0010000 0x4000>;
+                               interrupts = <28 4 5>;
+                               status = "disable";
+                       };
+
                        tcb0: timer@f8008000 {
                                compatible = "atmel,at91sam9x5-tcb";
                                reg = <0xf8008000 0x100>;
index 748ba7aa746cde3e14b8f04105f2dbd86fc6b214..4b0e0ca08f40d3d81b90be09b8cce47b9b225fac 100644 (file)
                        compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell";
                        reg = <0x80004000 0x1000>;
                        interrupts = <0 21 0x4>;
+                       arm,primecell-periphid = <0x180024>;
+
                        #address-cells = <1>;
                        #size-cells = <0>;
                        v-i2c-supply = <&db8500_vape_reg>;
                        compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell";
                        reg = <0x80122000 0x1000>;
                        interrupts = <0 22 0x4>;
+                       arm,primecell-periphid = <0x180024>;
+
                        #address-cells = <1>;
                        #size-cells = <0>;
                        v-i2c-supply = <&db8500_vape_reg>;
                        compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell";
                        reg = <0x80128000 0x1000>;
                        interrupts = <0 55 0x4>;
+                       arm,primecell-periphid = <0x180024>;
+
                        #address-cells = <1>;
                        #size-cells = <0>;
                        v-i2c-supply = <&db8500_vape_reg>;
                        compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell";
                        reg = <0x80110000 0x1000>;
                        interrupts = <0 12 0x4>;
+                       arm,primecell-periphid = <0x180024>;
+
                        #address-cells = <1>;
                        #size-cells = <0>;
                        v-i2c-supply = <&db8500_vape_reg>;
                        compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell";
                        reg = <0x8012a000 0x1000>;
                        interrupts = <0 51 0x4>;
+                       arm,primecell-periphid = <0x180024>;
+
                        #address-cells = <1>;
                        #size-cells = <0>;
                        v-i2c-supply = <&db8500_vape_reg>;
                        interrupts = <0 60 0x4>;
                        status = "disabled";
                };
+
                sdi@80118000 {
                        compatible = "arm,pl18x", "arm,primecell";
                        reg = <0x80118000 0x1000>;
                        interrupts = <0 50 0x4>;
                        status = "disabled";
                };
+
                sdi@80005000 {
                        compatible = "arm,pl18x", "arm,primecell";
                        reg = <0x80005000 0x1000>;
                        interrupts = <0 41 0x4>;
                        status = "disabled";
                };
+
                sdi@80119000 {
                        compatible = "arm,pl18x", "arm,primecell";
                        reg = <0x80119000 0x1000>;
                        interrupts = <0 59 0x4>;
                        status = "disabled";
                };
+
                sdi@80114000 {
                        compatible = "arm,pl18x", "arm,primecell";
                        reg = <0x80114000 0x1000>;
                        interrupts = <0 99 0x4>;
                        status = "disabled";
                };
+
                sdi@80008000 {
                        compatible = "arm,pl18x", "arm,primecell";
-                       reg = <0x80114000 0x1000>;
+                       reg = <0x80008000 0x1000>;
                        interrupts = <0 100 0x4>;
                        status = "disabled";
                };
index 73567b843e72ae28e9ba4e721c8607a6135bf288..a21511c140712e24c4759293ac66248bbb8ae309 100644 (file)
        compatible = "samsung,trats", "samsung,exynos4210";
 
        memory {
-               reg =  <0x40000000 0x20000000
-                       0x60000000 0x20000000>;
+               reg =  <0x40000000 0x10000000
+                       0x50000000 0x10000000
+                       0x60000000 0x10000000
+                       0x70000000 0x10000000>;
        };
 
        chosen {
index 9ca4ca70c1bcb8f680fde33b924045eb6666839d..6d31aa3834608d41d84d848ec954f00a064a4659 100644 (file)
@@ -69,6 +69,7 @@
                                interrupts = <13>, <56>;
                                interrupt-names = "gpmi-dma", "bch";
                                clocks = <&clks 34>;
+                               clock-names = "gpmi_io";
                                fsl,gpmi-dma-channel = <4>;
                                status = "disabled";
                        };
index e16d631554802f73227de6bcab58368d9e049227..55c57ea6169e02ec9dc81bb8e38407c608678bbd 100644 (file)
@@ -85,6 +85,7 @@
                                interrupts = <88>, <41>;
                                interrupt-names = "gpmi-dma", "bch";
                                clocks = <&clks 50>;
+                               clock-names = "gpmi_io";
                                fsl,gpmi-dma-channel = <4>;
                                status = "disabled";
                        };
index f38ea8771b44fb1b1ffe71830e74bed6d628ef66..696e929d0304ff72580e83510771c1ba0048b91f 100644 (file)
                        interrupt-names = "common", "tx", "rx", "sidetone";
                        interrupt-parent = <&intc>;
                        ti,buffer-size = <1280>;
-                       ti,hwmods = "mcbsp2";
+                       ti,hwmods = "mcbsp2", "mcbsp2_sidetone";
                };
 
                mcbsp3: mcbsp@49024000 {
                        interrupt-names = "common", "tx", "rx", "sidetone";
                        interrupt-parent = <&intc>;
                        ti,buffer-size = <128>;
-                       ti,hwmods = "mcbsp3";
+                       ti,hwmods = "mcbsp3", "mcbsp3_sidetone";
                };
 
                mcbsp4: mcbsp@49026000 {
index b1497c7d7d6851db3753c1210e974cb9e47888c2..df7f2270fc91a4f98d0d7dd067817bb2ce8b62c0 100644 (file)
@@ -73,8 +73,8 @@
 
        pinmux: pinmux {
                compatible = "nvidia,tegra30-pinmux";
-               reg = <0x70000868 0xd0    /* Pad control registers */
-                      0x70003000 0x3e0>; /* Mux registers */
+               reg = <0x70000868 0xd4    /* Pad control registers */
+                      0x70003000 0x3e4>; /* Mux registers */
        };
 
        serial@70006000 {
index 66aa7a6db884c14668be9f20a6d27166c85a8c1f..394ded624e375a8e1e36b04ee5b85cefbf5c9391 100644 (file)
@@ -139,6 +139,7 @@ CONFIG_I2C_IMX=y
 CONFIG_SPI=y
 CONFIG_SPI_IMX=y
 CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_MC9S08DZ60=y
 # CONFIG_HWMON is not set
 CONFIG_WATCHDOG=y
 CONFIG_IMX2_WDT=y
@@ -155,6 +156,7 @@ CONFIG_SOC_CAMERA=y
 CONFIG_SOC_CAMERA_OV2640=y
 CONFIG_VIDEO_MX3=y
 CONFIG_FB=y
+CONFIG_LCD_PLATFORM=y
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
 CONFIG_LCD_CLASS_DEVICE=y
 CONFIG_LCD_L4F00242T03=y
index 7bcf850eddcd7f2c843c0b297eda1f24125cc03c..3458752c4bb277da7d3574e050f847add462cc0a 100644 (file)
@@ -1,6 +1,6 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
-CONFIG_NO_HZ=y
+CONFIG_IRQ_DOMAIN_DEBUG=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
@@ -9,10 +9,12 @@ CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_ARCH_MVEBU=y
-CONFIG_MACH_ARMADA_370_XP=y
+CONFIG_MACH_ARMADA_370=y
+CONFIG_MACH_ARMADA_XP=y
+# CONFIG_CACHE_L2X0 is not set
 CONFIG_AEABI=y
 CONFIG_HIGHMEM=y
-CONFIG_USE_OF=y
+# CONFIG_COMPACTION is not set
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
 CONFIG_ARM_APPENDED_DTB=y
@@ -23,6 +25,8 @@ CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_OF_PLATFORM=y
 CONFIG_GPIOLIB=y
 CONFIG_GPIO_SYSFS=y
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_IOMMU_SUPPORT is not set
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_FS_XATTR is not set
index cdd4d2bd39620bf97bfecfdc8c0bcc35e0ee0356..2ba9e63d0f177142699a56e4a4b3408cee10df43 100644 (file)
@@ -1,3 +1,4 @@
+CONFIG_ARCH_VERSATILE=y
 CONFIG_EXPERIMENTAL=y
 # CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_SYSVIPC=y
index 59426a4595c9cb90bcb765843f89295bd20f6797..e847d23351eda71ada1bc200476ee7f427a4e8ac 100644 (file)
@@ -8,7 +8,7 @@
 #define        flat_argvp_envp_on_stack()              1
 #define        flat_old_ram_flag(flags)                (flags)
 #define        flat_reloc_valid(reloc, size)           ((reloc) <= (size))
-#define        flat_get_addr_from_rp(rp, relval, flags, persistent) get_unaligned(rp)
+#define        flat_get_addr_from_rp(rp, relval, flags, persistent) ((void)persistent,get_unaligned(rp))
 #define        flat_put_addr_at_rp(rp, val, relval)    put_unaligned(val,rp)
 #define        flat_get_relocate_addr(rel)             (rel)
 #define        flat_set_persistent(relval, p)          0
index 35c1ed89b93652688dc99ede919b55b0d5051b1d..42f042ee4ada2563aac52e7449c062011042839c 100644 (file)
@@ -64,7 +64,7 @@ extern void __raw_readsl(const void __iomem *addr, void *data, int longlen);
 static inline void __raw_writew(u16 val, volatile void __iomem *addr)
 {
        asm volatile("strh %1, %0"
-                    : "+Qo" (*(volatile u16 __force *)addr)
+                    : "+Q" (*(volatile u16 __force *)addr)
                     : "r" (val));
 }
 
@@ -72,7 +72,7 @@ static inline u16 __raw_readw(const volatile void __iomem *addr)
 {
        u16 val;
        asm volatile("ldrh %1, %0"
-                    : "+Qo" (*(volatile u16 __force *)addr),
+                    : "+Q" (*(volatile u16 __force *)addr),
                       "=r" (val));
        return val;
 }
index 05b8e82ec9f5b66744305de1094df1115fc92798..e3f7572634381bd28fbf3225eb375788431ee3fc 100644 (file)
@@ -10,7 +10,5 @@
 
 extern void sched_clock_postinit(void);
 extern void setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate);
-extern void setup_sched_clock_needs_suspend(u32 (*read)(void), int bits,
-               unsigned long rate);
 
 #endif
index 77bd79f2ffdbd0344d096ca7fb2db809fb52d387..7e1f76027f666e252c35bd320d4518e110548c47 100644 (file)
@@ -200,8 +200,8 @@ extern int __put_user_8(void *, unsigned long long);
 #define USER_DS                        KERNEL_DS
 
 #define segment_eq(a,b)                (1)
-#define __addr_ok(addr)                (1)
-#define __range_ok(addr,size)  (0)
+#define __addr_ok(addr)                ((void)(addr),1)
+#define __range_ok(addr,size)  ((void)(addr),0)
 #define get_fs()               (KERNEL_DS)
 
 static inline void set_fs(mm_segment_t fs)
index 6a6f1e485f41a2b9402534c435b79c183cb5cdb2..301c1db3e99b13e95a6e8882013e7c518b6011c7 100644 (file)
@@ -27,9 +27,9 @@
 #if __LINUX_ARM_ARCH__ <= 6
        ldr     \tmp, =elf_hwcap                    @ may not have MVFR regs
        ldr     \tmp, [\tmp, #0]
-       tst     \tmp, #HWCAP_VFPv3D16
-       ldceql  p11, cr0, [\base],#32*4             @ FLDMIAD \base!, {d16-d31}
-       addne   \base, \base, #32*4                 @ step over unused register space
+       tst     \tmp, #HWCAP_VFPD32
+       ldcnel  p11, cr0, [\base],#32*4             @ FLDMIAD \base!, {d16-d31}
+       addeq   \base, \base, #32*4                 @ step over unused register space
 #else
        VFPFMRX \tmp, MVFR0                         @ Media and VFP Feature Register 0
        and     \tmp, \tmp, #MVFR0_A_SIMD_MASK      @ A_SIMD field
@@ -51,9 +51,9 @@
 #if __LINUX_ARM_ARCH__ <= 6
        ldr     \tmp, =elf_hwcap                    @ may not have MVFR regs
        ldr     \tmp, [\tmp, #0]
-       tst     \tmp, #HWCAP_VFPv3D16
-       stceql  p11, cr0, [\base],#32*4             @ FSTMIAD \base!, {d16-d31}
-       addne   \base, \base, #32*4                 @ step over unused register space
+       tst     \tmp, #HWCAP_VFPD32
+       stcnel  p11, cr0, [\base],#32*4             @ FSTMIAD \base!, {d16-d31}
+       addeq   \base, \base, #32*4                 @ step over unused register space
 #else
        VFPFMRX \tmp, MVFR0                         @ Media and VFP Feature Register 0
        and     \tmp, \tmp, #MVFR0_A_SIMD_MASK      @ A_SIMD field
index ae05e56dd17d6eb2e270117172dbc327f27b82d2..5000397134b4e5ceb06521ecf1d22622a0918a82 100644 (file)
 
 #ifndef __ASSEMBLY__
 /* Explicitly size integers that represent pfns in the interface with
- * Xen so that we can have one ABI that works for 32 and 64 bit guests. */
+ * Xen so that we can have one ABI that works for 32 and 64 bit guests.
+ * Note that this means that the xen_pfn_t type may be capable of
+ * representing pfn's which the guest cannot represent in its own pfn
+ * type. However since pfn space is controlled by the guest this is
+ * fine since it simply wouldn't be able to create any sure pfns in
+ * the first place.
+ */
 typedef uint64_t xen_pfn_t;
+#define PRI_xen_pfn "llx"
 typedef uint64_t xen_ulong_t;
+#define PRI_xen_ulong "llx"
 /* Guest handles for primitive C types. */
 __DEFINE_GUEST_HANDLE(uchar, unsigned char);
 __DEFINE_GUEST_HANDLE(uint,  unsigned int);
-__DEFINE_GUEST_HANDLE(ulong, unsigned long);
 DEFINE_GUEST_HANDLE(char);
 DEFINE_GUEST_HANDLE(int);
-DEFINE_GUEST_HANDLE(long);
 DEFINE_GUEST_HANDLE(void);
 DEFINE_GUEST_HANDLE(uint64_t);
 DEFINE_GUEST_HANDLE(uint32_t);
index 174202318dfff2779ece119e7b45949b82f429e0..c6b9096cef9593fe6508f13768802e1fba98d64c 100644 (file)
@@ -10,7 +10,7 @@
 #include <xen/interface/grant_table.h>
 
 #define pfn_to_mfn(pfn)                        (pfn)
-#define phys_to_machine_mapping_valid  (1)
+#define phys_to_machine_mapping_valid(pfn) (1)
 #define mfn_to_pfn(mfn)                        (mfn)
 #define mfn_to_virt(m)                 (__va(mfn_to_pfn(m) << PAGE_SHIFT))
 
@@ -30,6 +30,8 @@ typedef struct xpaddr {
 #define XMADDR(x)      ((xmaddr_t) { .maddr = (x) })
 #define XPADDR(x)      ((xpaddr_t) { .paddr = (x) })
 
+#define INVALID_P2M_ENTRY      (~0UL)
+
 static inline xmaddr_t phys_to_machine(xpaddr_t phys)
 {
        unsigned offset = phys.paddr & ~PAGE_MASK;
@@ -74,9 +76,14 @@ static inline int m2p_remove_override(struct page *page, bool clear_pte)
        return 0;
 }
 
+static inline bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn)
+{
+       BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY);
+       return true;
+}
+
 static inline bool set_phys_to_machine(unsigned long pfn, unsigned long mfn)
 {
-       BUG();
-       return false;
+       return __set_phys_to_machine(pfn, mfn);
 }
 #endif /* _ASM_ARM_XEN_PAGE_H */
diff --git a/arch/arm/include/debug/8250_32.S b/arch/arm/include/debug/8250_32.S
new file mode 100644 (file)
index 0000000..8db01ee
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * 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.
+ *
+ * Derived from arch/arm/mach-davinci/include/mach/debug-macro.S to use 32-bit
+ * accesses to the 8250.
+ */
+
+#include <linux/serial_reg.h>
+
+               .macro  senduart,rd,rx
+               str     \rd, [\rx, #UART_TX << UART_SHIFT]
+               .endm
+
+               .macro  busyuart,rd,rx
+1002:          ldr     \rd, [\rx, #UART_LSR << UART_SHIFT]
+               and     \rd, \rd, #UART_LSR_TEMT | UART_LSR_THRE
+               teq     \rd, #UART_LSR_TEMT | UART_LSR_THRE
+               bne     1002b
+               .endm
+
+               /* The UART's don't have any flow control IO's wired up. */
+               .macro  waituart,rd,rx
+               .endm
index 7419deb1b948f1b8954a6579db72b951b30880bb..bc1f07c49cd4a5628a9e7c2957597589b2d42f2a 100644 (file)
@@ -5,10 +5,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  *
- * Derived from arch/arm/mach-davinci/include/mach/debug-macro.S to use 32-bit
- * accesses to the 8250.
  */
-#include <linux/serial_reg.h>
 
 #define UART_SHIFT 2
 #define PICOXCELL_UART1_BASE           0x80230000
                ldr     \rp, =PICOXCELL_UART1_BASE
                .endm
 
-               .macro  senduart,rd,rx
-               str     \rd, [\rx, #UART_TX << UART_SHIFT]
-               .endm
-
-               .macro  busyuart,rd,rx
-1002:          ldr     \rd, [\rx, #UART_LSR << UART_SHIFT]
-               and     \rd, \rd, #UART_LSR_TEMT | UART_LSR_THRE
-               teq     \rd, #UART_LSR_TEMT | UART_LSR_THRE
-               bne     1002b
-               .endm
-
-               /* The UART's don't have any flow control IO's wired up. */
-               .macro  waituart,rd,rx
-               .endm
+#include "8250_32.S"
index d6f26d23374fbe9e224c7f65e0a0fc6bac85b81b..966b2f994946daf901631bfa690f86535eb70f1b 100644 (file)
@@ -7,6 +7,9 @@
  * published by the Free Software Foundation.
  */
 
+#define UART_SHIFT 2
+#define DEBUG_LL_UART_OFFSET   0x00002000
+
                .macro  addruart, rp, rv, tmp
                mov     \rp, #DEBUG_LL_UART_OFFSET
                orr     \rp, \rp, #0x00c00000
@@ -14,3 +17,5 @@
                orr     \rp, \rp, #0xff000000   @ physical base
                .endm
 
+#include "8250_32.S"
+
index f254f6503cce7df8aedc3104db344417913d44c1..3688fd15a32dd5a5e5f81aef148cf397022fc2d7 100644 (file)
 #define HWCAP_THUMBEE  (1 << 11)
 #define HWCAP_NEON     (1 << 12)
 #define HWCAP_VFPv3    (1 << 13)
-#define HWCAP_VFPv3D16 (1 << 14)
+#define HWCAP_VFPv3D16 (1 << 14)       /* also set for VFPv4-D16 */
 #define HWCAP_TLS      (1 << 15)
 #define HWCAP_VFPv4    (1 << 16)
 #define HWCAP_IDIVA    (1 << 17)
 #define HWCAP_IDIVT    (1 << 18)
+#define HWCAP_VFPD32   (1 << 19)       /* set if VFP has 32 regs (not 16) */
 #define HWCAP_IDIV     (HWCAP_IDIVA | HWCAP_IDIVT)
 
 
index 16cedb42c0c39c0169008e45488b279cd9b32821..896165096d6a936572bdcfd0d21cc23f01cb9ea2 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/list.h>
 #include <linux/kallsyms.h>
 #include <linux/proc_fs.h>
+#include <linux/export.h>
 
 #include <asm/exception.h>
 #include <asm/mach/arch.h>
@@ -109,6 +110,7 @@ void set_irq_flags(unsigned int irq, unsigned int iflags)
        /* Order is clear bits in "clr" then set bits in "set" */
        irq_modify_status(irq, clr, set & ~clr);
 }
+EXPORT_SYMBOL_GPL(set_irq_flags);
 
 void __init init_IRQ(void)
 {
index 38c1a3b103a0684b5b579bb74ca07f38bb91eb13..83931290506704ad226e8a8cb2a15b52a33d4494 100644 (file)
@@ -366,7 +366,9 @@ void kprobe_arm_test_cases(void)
        TEST_UNSUPPORTED(".word 0xe04f0392 @ umaal r0, pc, r2, r3")
        TEST_UNSUPPORTED(".word 0xe0500090 @ undef")
        TEST_UNSUPPORTED(".word 0xe05fff9f @ undef")
+#endif
 
+#if __LINUX_ARM_ARCH__ >= 7
        TEST_RRR(  "mls         r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
        TEST_RRR(  "mlshi       r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
        TEST_RR(   "mls         lr, r",1, VAL2,", r",2, VAL3,", r13")
@@ -456,6 +458,8 @@ void kprobe_arm_test_cases(void)
        TEST_UNSUPPORTED(".word 0xe1700090") /* Unallocated space */
 #if __LINUX_ARM_ARCH__ >= 6
        TEST_UNSUPPORTED("ldrex r2, [sp]")
+#endif
+#if (__LINUX_ARM_ARCH__ >= 7) || defined(CONFIG_CPU_32v6K)
        TEST_UNSUPPORTED("strexd        r0, r2, r3, [sp]")
        TEST_UNSUPPORTED("ldrexd        r2, r3, [sp]")
        TEST_UNSUPPORTED("strexb        r0, r2, [sp]")
index e29c3337ca8142aeb6f4bb755e3947d6aecd4fbe..8ef8c9337809cbe5ccb91b33525c38a379e9e986 100644 (file)
@@ -45,10 +45,9 @@ int machine_kexec_prepare(struct kimage *image)
        for (i = 0; i < image->nr_segments; i++) {
                current_segment = &image->segment[i];
 
-               err = memblock_is_region_memory(current_segment->mem,
-                                               current_segment->memsz);
-               if (err)
-                       return - EINVAL;
+               if (!memblock_is_region_memory(current_segment->mem,
+                                              current_segment->memsz))
+                       return -EINVAL;
 
                err = get_user(header, (__be32*)current_segment->buf);
                if (err)
index 93971b1a4f0bb0d38eebd573f8618e994273b079..53c0304b734a4e6ad7b1806b147baa3d2d43986f 100644 (file)
@@ -96,6 +96,10 @@ armpmu_event_set_period(struct perf_event *event,
        s64 period = hwc->sample_period;
        int ret = 0;
 
+       /* The period may have been changed by PERF_EVENT_IOC_PERIOD */
+       if (unlikely(period != hwc->last_period))
+               left = period - (hwc->last_period - left);
+
        if (unlikely(left <= -period)) {
                left = period;
                local64_set(&hwc->period_left, left);
index e21bac20d90da1558000125586623bdb9cbe328c..fc6692e2b603b747553835f04a85bf3b1f9c5f3b 100644 (file)
@@ -107,13 +107,6 @@ static void sched_clock_poll(unsigned long wrap_ticks)
        update_sched_clock();
 }
 
-void __init setup_sched_clock_needs_suspend(u32 (*read)(void), int bits,
-               unsigned long rate)
-{
-       setup_sched_clock(read, bits, rate);
-       cd.needs_suspend = true;
-}
-
 void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate)
 {
        unsigned long r, w;
@@ -189,18 +182,15 @@ void __init sched_clock_postinit(void)
 static int sched_clock_suspend(void)
 {
        sched_clock_poll(sched_clock_timer.data);
-       if (cd.needs_suspend)
-               cd.suspended = true;
+       cd.suspended = true;
        return 0;
 }
 
 static void sched_clock_resume(void)
 {
-       if (cd.needs_suspend) {
-               cd.epoch_cyc = read_sched_clock();
-               cd.epoch_cyc_copy = cd.epoch_cyc;
-               cd.suspended = false;
-       }
+       cd.epoch_cyc = read_sched_clock();
+       cd.epoch_cyc_copy = cd.epoch_cyc;
+       cd.suspended = false;
 }
 
 static struct syscore_ops sched_clock_ops = {
index 8e20754dd31d5946f5297aae2023ae2c8d5cd572..fbc8b2623d82f08c8c2926375a7b8a31f943361b 100644 (file)
@@ -294,18 +294,24 @@ static void percpu_timer_setup(void);
 asmlinkage void __cpuinit secondary_start_kernel(void)
 {
        struct mm_struct *mm = &init_mm;
-       unsigned int cpu = smp_processor_id();
+       unsigned int cpu;
+
+       /*
+        * The identity mapping is uncached (strongly ordered), so
+        * switch away from it before attempting any exclusive accesses.
+        */
+       cpu_switch_mm(mm->pgd, mm);
+       enter_lazy_tlb(mm, current);
+       local_flush_tlb_all();
 
        /*
         * All kernel threads share the same mm context; grab a
         * reference and switch to it.
         */
+       cpu = smp_processor_id();
        atomic_inc(&mm->mm_count);
        current->active_mm = mm;
        cpumask_set_cpu(cpu, mm_cpumask(mm));
-       cpu_switch_mm(mm->pgd, mm);
-       enter_lazy_tlb(mm, current);
-       local_flush_tlb_all();
 
        printk("CPU%u: Booted secondary processor\n", cpu);
 
index e1f906989bb8161963d8a714073a8d84a8e2c2e6..b22d700fea2751c60b5dbad689ee0b18305108b3 100644 (file)
@@ -42,10 +42,10 @@ static void twd_set_mode(enum clock_event_mode mode,
 
        switch (mode) {
        case CLOCK_EVT_MODE_PERIODIC:
-               /* timer load already set up */
                ctrl = TWD_TIMER_CONTROL_ENABLE | TWD_TIMER_CONTROL_IT_ENABLE
                        | TWD_TIMER_CONTROL_PERIODIC;
-               __raw_writel(twd_timer_rate / HZ, twd_base + TWD_TIMER_LOAD);
+               __raw_writel(DIV_ROUND_CLOSEST(twd_timer_rate, HZ),
+                       twd_base + TWD_TIMER_LOAD);
                break;
        case CLOCK_EVT_MODE_ONESHOT:
                /* period set, and timer enabled in 'next_event' hook */
index 9d0a30032d7f0f2ae50f0cbe9eebb80d6da827a3..0dc53854a5d8eb423e468fe255cb0f7c1fa30e15 100644 (file)
@@ -45,6 +45,7 @@ int read_current_timer(unsigned long *timer_val)
        *timer_val = delay_timer->read_current_timer();
        return 0;
 }
+EXPORT_SYMBOL_GPL(read_current_timer);
 
 static void __timer_delay(unsigned long cycles)
 {
index b14207101938adb03c852a708a2261e4a58d6f3d..043624219b55a25ebdc50c86a7399dda604392a3 100644 (file)
@@ -21,19 +21,13 @@ config SOC_AT91SAM9
        bool
        select CPU_ARM926T
        select GENERIC_CLOCKEVENTS
+       select MULTI_IRQ_HANDLER
+       select SPARSE_IRQ
 
 menu "Atmel AT91 System-on-Chip"
 
 comment "Atmel AT91 Processor"
 
-config SOC_AT91SAM9
-       bool
-       select AT91_SAM9_SMC
-       select AT91_SAM9_TIME
-       select CPU_ARM926T
-       select MULTI_IRQ_HANDLER
-       select SPARSE_IRQ
-
 config SOC_AT91RM9200
        bool "AT91RM9200"
        select CPU_ARM920T
index b4f0565aff638af135c7797b430bbfeb2a29b439..af47c75db513b58a88be84e52f2e681ec863908c 100644 (file)
@@ -184,10 +184,13 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.1", &tc3_clk),
        CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.1", &tc4_clk),
        CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.1", &tc5_clk),
-       CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
-       CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
-       CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk),
-       CLKDEV_CON_DEV_ID(NULL, "i2c-at91rm9200", &twi_clk),
+       CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.0", &ssc0_clk),
+       CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.1", &ssc1_clk),
+       CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.2", &ssc2_clk),
+       CLKDEV_CON_DEV_ID("pclk", "fffd0000.ssc", &ssc0_clk),
+       CLKDEV_CON_DEV_ID("pclk", "fffd4000.ssc", &ssc1_clk),
+       CLKDEV_CON_DEV_ID("pclk", "fffd8000.ssc", &ssc2_clk),
+       CLKDEV_CON_DEV_ID(NULL, "i2c-at91rm9200.0", &twi_clk),
        /* fake hclk clock */
        CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
        CLKDEV_CON_ID("pioA", &pioA_clk),
index a563189cdfc3e1bfd4bdc2e71049073de01cd712..9e76427aaec29a0065963e8633196f598bc9d2bc 100644 (file)
@@ -68,7 +68,7 @@ void __init at91_add_device_usbh(struct at91_usbh_data *data)
 
        /* Enable overcurrent notification */
        for (i = 0; i < data->ports; i++) {
-               if (data->overcurrent_pin[i])
+               if (gpio_is_valid(data->overcurrent_pin[i]))
                        at91_set_gpio_input(data->overcurrent_pin[i], 1);
        }
 
@@ -479,7 +479,7 @@ static struct i2c_gpio_platform_data pdata = {
 
 static struct platform_device at91rm9200_twi_device = {
        .name                   = "i2c-gpio",
-       .id                     = -1,
+       .id                     = 0,
        .dev.platform_data      = &pdata,
 };
 
@@ -512,7 +512,7 @@ static struct resource twi_resources[] = {
 
 static struct platform_device at91rm9200_twi_device = {
        .name           = "i2c-at91rm9200",
-       .id             = -1,
+       .id             = 0,
        .resource       = twi_resources,
        .num_resources  = ARRAY_SIZE(twi_resources),
 };
@@ -752,7 +752,7 @@ static struct resource ssc0_resources[] = {
 };
 
 static struct platform_device at91rm9200_ssc0_device = {
-       .name   = "ssc",
+       .name   = "at91rm9200_ssc",
        .id     = 0,
        .dev    = {
                .dma_mask               = &ssc0_dmamask,
@@ -794,7 +794,7 @@ static struct resource ssc1_resources[] = {
 };
 
 static struct platform_device at91rm9200_ssc1_device = {
-       .name   = "ssc",
+       .name   = "at91rm9200_ssc",
        .id     = 1,
        .dev    = {
                .dma_mask               = &ssc1_dmamask,
@@ -836,7 +836,7 @@ static struct resource ssc2_resources[] = {
 };
 
 static struct platform_device at91rm9200_ssc2_device = {
-       .name   = "ssc",
+       .name   = "at91rm9200_ssc",
        .id     = 2,
        .dev    = {
                .dma_mask               = &ssc2_dmamask,
index ad29f93f20cab175555cd2a8c2974deff0fe31fd..a41eb3d23f68dc282cc51117427ea446db7b97e5 100644 (file)
@@ -210,9 +210,10 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.1", &tc3_clk),
        CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.1", &tc4_clk),
        CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.1", &tc5_clk),
-       CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc_clk),
-       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260", &twi_clk),
-       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g20", &twi_clk),
+       CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.0", &ssc_clk),
+       CLKDEV_CON_DEV_ID("pclk", "fffbc000.ssc", &ssc_clk),
+       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260.0", &twi_clk),
+       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g20.0", &twi_clk),
        /* more usart lookup table for DT entries */
        CLKDEV_CON_DEV_ID("usart", "fffff200.serial", &mck),
        CLKDEV_CON_DEV_ID("usart", "fffb0000.serial", &usart0_clk),
index a76b8684f52d07328fcfe2f4a08726124b643f5a..e67cfa2acbe00d05fe773630113b3331cc4661eb 100644 (file)
@@ -72,7 +72,7 @@ void __init at91_add_device_usbh(struct at91_usbh_data *data)
 
        /* Enable overcurrent notification */
        for (i = 0; i < data->ports; i++) {
-               if (data->overcurrent_pin[i])
+               if (gpio_is_valid(data->overcurrent_pin[i]))
                        at91_set_gpio_input(data->overcurrent_pin[i], 1);
        }
 
@@ -389,7 +389,7 @@ static struct i2c_gpio_platform_data pdata = {
 
 static struct platform_device at91sam9260_twi_device = {
        .name                   = "i2c-gpio",
-       .id                     = -1,
+       .id                     = 0,
        .dev.platform_data      = &pdata,
 };
 
@@ -421,7 +421,7 @@ static struct resource twi_resources[] = {
 };
 
 static struct platform_device at91sam9260_twi_device = {
-       .id             = -1,
+       .id             = 0,
        .resource       = twi_resources,
        .num_resources  = ARRAY_SIZE(twi_resources),
 };
@@ -742,7 +742,7 @@ static struct resource ssc_resources[] = {
 };
 
 static struct platform_device at91sam9260_ssc_device = {
-       .name   = "ssc",
+       .name   = "at91rm9200_ssc",
        .id     = 0,
        .dev    = {
                .dma_mask               = &ssc_dmamask,
index 8d999eb1a137f1ed72529d296774c084d17da1a4..7fcbe05833426b7b648a145b796619f4e47d7d5b 100644 (file)
@@ -174,12 +174,15 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tc0_clk),
        CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.0", &tc1_clk),
        CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.0", &tc2_clk),
-       CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
-       CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
-       CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk),
+       CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.0", &ssc0_clk),
+       CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.1", &ssc1_clk),
+       CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.2", &ssc2_clk),
+       CLKDEV_CON_DEV_ID("pclk", "fffbc000.ssc", &ssc0_clk),
+       CLKDEV_CON_DEV_ID("pclk", "fffc0000.ssc", &ssc1_clk),
+       CLKDEV_CON_DEV_ID("pclk", "fffc4000.ssc", &ssc2_clk),
        CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &hck0),
-       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9261", &twi_clk),
-       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g10", &twi_clk),
+       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9261.0", &twi_clk),
+       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g10.0", &twi_clk),
        CLKDEV_CON_ID("pioA", &pioA_clk),
        CLKDEV_CON_ID("pioB", &pioB_clk),
        CLKDEV_CON_ID("pioC", &pioC_clk),
index 9752f17efba9926501a23b8e5209fbabcdfedc6d..a27d9dd0faa4a99b9a07e5416c7f0cc96ee18f73 100644 (file)
@@ -72,7 +72,7 @@ void __init at91_add_device_usbh(struct at91_usbh_data *data)
 
        /* Enable overcurrent notification */
        for (i = 0; i < data->ports; i++) {
-               if (data->overcurrent_pin[i])
+               if (gpio_is_valid(data->overcurrent_pin[i]))
                        at91_set_gpio_input(data->overcurrent_pin[i], 1);
        }
 
@@ -285,7 +285,7 @@ static struct i2c_gpio_platform_data pdata = {
 
 static struct platform_device at91sam9261_twi_device = {
        .name                   = "i2c-gpio",
-       .id                     = -1,
+       .id                     = 0,
        .dev.platform_data      = &pdata,
 };
 
@@ -317,7 +317,7 @@ static struct resource twi_resources[] = {
 };
 
 static struct platform_device at91sam9261_twi_device = {
-       .id             = -1,
+       .id             = 0,
        .resource       = twi_resources,
        .num_resources  = ARRAY_SIZE(twi_resources),
 };
@@ -706,7 +706,7 @@ static struct resource ssc0_resources[] = {
 };
 
 static struct platform_device at91sam9261_ssc0_device = {
-       .name   = "ssc",
+       .name   = "at91rm9200_ssc",
        .id     = 0,
        .dev    = {
                .dma_mask               = &ssc0_dmamask,
@@ -748,7 +748,7 @@ static struct resource ssc1_resources[] = {
 };
 
 static struct platform_device at91sam9261_ssc1_device = {
-       .name   = "ssc",
+       .name   = "at91rm9200_ssc",
        .id     = 1,
        .dev    = {
                .dma_mask               = &ssc1_dmamask,
@@ -790,7 +790,7 @@ static struct resource ssc2_resources[] = {
 };
 
 static struct platform_device at91sam9261_ssc2_device = {
-       .name   = "ssc",
+       .name   = "at91rm9200_ssc",
        .id     = 2,
        .dev    = {
                .dma_mask               = &ssc2_dmamask,
index 6a01d0360dfb8940cbaaa2affc9bb58f88d702d9..c0f4c8c1f4ed59ad31cd004a317e7f436181285c 100644 (file)
@@ -186,14 +186,16 @@ static struct clk *periph_clocks[] __initdata = {
 static struct clk_lookup periph_clocks_lookups[] = {
        /* One additional fake clock for macb_hclk */
        CLKDEV_CON_ID("hclk", &macb_clk),
-       CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
-       CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
+       CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.0", &ssc0_clk),
+       CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.1", &ssc1_clk),
+       CLKDEV_CON_DEV_ID("pclk", "fff98000.ssc", &ssc0_clk),
+       CLKDEV_CON_DEV_ID("pclk", "fff9c000.ssc", &ssc1_clk),
        CLKDEV_CON_DEV_ID("mci_clk", "atmel_mci.0", &mmc0_clk),
        CLKDEV_CON_DEV_ID("mci_clk", "atmel_mci.1", &mmc1_clk),
        CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.0", &spi0_clk),
        CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.1", &spi1_clk),
        CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tcb_clk),
-       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260", &twi_clk),
+       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260.0", &twi_clk),
        /* fake hclk clock */
        CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
        CLKDEV_CON_ID("pioA", &pioA_clk),
index 8dde220b42b69c785c70118a16e48a1aa20acb95..8215839f2d540a46db98a83eeddf4228122c75b8 100644 (file)
@@ -78,7 +78,7 @@ void __init at91_add_device_usbh(struct at91_usbh_data *data)
 
        /* Enable overcurrent notification */
        for (i = 0; i < data->ports; i++) {
-               if (data->overcurrent_pin[i])
+               if (gpio_is_valid(data->overcurrent_pin[i]))
                        at91_set_gpio_input(data->overcurrent_pin[i], 1);
        }
 
@@ -567,7 +567,7 @@ static struct i2c_gpio_platform_data pdata = {
 
 static struct platform_device at91sam9263_twi_device = {
        .name                   = "i2c-gpio",
-       .id                     = -1,
+       .id                     = 0,
        .dev.platform_data      = &pdata,
 };
 
@@ -600,7 +600,7 @@ static struct resource twi_resources[] = {
 
 static struct platform_device at91sam9263_twi_device = {
        .name           = "i2c-at91sam9260",
-       .id             = -1,
+       .id             = 0,
        .resource       = twi_resources,
        .num_resources  = ARRAY_SIZE(twi_resources),
 };
@@ -1199,7 +1199,7 @@ static struct resource ssc0_resources[] = {
 };
 
 static struct platform_device at91sam9263_ssc0_device = {
-       .name   = "ssc",
+       .name   = "at91rm9200_ssc",
        .id     = 0,
        .dev    = {
                .dma_mask               = &ssc0_dmamask,
@@ -1241,7 +1241,7 @@ static struct resource ssc1_resources[] = {
 };
 
 static struct platform_device at91sam9263_ssc1_device = {
-       .name   = "ssc",
+       .name   = "at91rm9200_ssc",
        .id     = 1,
        .dev    = {
                .dma_mask               = &ssc1_dmamask,
index 84af1b506d92a0b1e9e88c885b1d57be95fbf40b..a4282d3742bf11098fed3a8101285b94eafeddbe 100644 (file)
@@ -239,8 +239,10 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.1", &tcb0_clk),
        CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g10.0", &twi0_clk),
        CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g10.1", &twi1_clk),
-       CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
-       CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
+       CLKDEV_CON_DEV_ID("pclk", "at91sam9g45_ssc.0", &ssc0_clk),
+       CLKDEV_CON_DEV_ID("pclk", "at91sam9g45_ssc.1", &ssc1_clk),
+       CLKDEV_CON_DEV_ID("pclk", "fff9c000.ssc", &ssc0_clk),
+       CLKDEV_CON_DEV_ID("pclk", "fffa0000.ssc", &ssc1_clk),
        CLKDEV_CON_DEV_ID(NULL, "atmel-trng", &trng_clk),
        CLKDEV_CON_DEV_ID(NULL, "atmel_sha", &aestdessha_clk),
        CLKDEV_CON_DEV_ID(NULL, "atmel_tdes", &aestdessha_clk),
index b1596072dcc23cd1414a8449eb4c25a35ed11222..d26474a97fec884e1ef0338400cbf68b00d0ceae 100644 (file)
@@ -1459,7 +1459,7 @@ static struct resource ssc0_resources[] = {
 };
 
 static struct platform_device at91sam9g45_ssc0_device = {
-       .name   = "ssc",
+       .name   = "at91sam9g45_ssc",
        .id     = 0,
        .dev    = {
                .dma_mask               = &ssc0_dmamask,
@@ -1501,7 +1501,7 @@ static struct resource ssc1_resources[] = {
 };
 
 static struct platform_device at91sam9g45_ssc1_device = {
-       .name   = "ssc",
+       .name   = "at91sam9g45_ssc",
        .id     = 1,
        .dev    = {
                .dma_mask               = &ssc1_dmamask,
@@ -1841,8 +1841,8 @@ static struct resource sha_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_AESTDESSHA,
-               .end    = AT91SAM9G45_ID_AESTDESSHA,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1874,8 +1874,8 @@ static struct resource tdes_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_AESTDESSHA,
-               .end    = AT91SAM9G45_ID_AESTDESSHA,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1910,8 +1910,8 @@ static struct resource aes_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_AESTDESSHA,
-               .end    = AT91SAM9G45_ID_AESTDESSHA,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA,
                .flags  = IORESOURCE_IRQ,
        },
 };
index 72e908412222615134fc0530cc339348093f76be..b683fdc699f12e1a97dc3c60fdf07f9abd7a02f1 100644 (file)
@@ -184,8 +184,10 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tc0_clk),
        CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.0", &tc1_clk),
        CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.0", &tc2_clk),
-       CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
-       CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
+       CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.0", &ssc0_clk),
+       CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.1", &ssc1_clk),
+       CLKDEV_CON_DEV_ID("pclk", "fffc0000.ssc", &ssc0_clk),
+       CLKDEV_CON_DEV_ID("pclk", "fffc4000.ssc", &ssc1_clk),
        CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g20.0", &twi0_clk),
        CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g20.1", &twi1_clk),
        CLKDEV_CON_ID("pioA", &pioA_clk),
index d6ca0543ce8d7f1054d8f25614cd17369efe283d..b656110e8afe6fec0a55fa15edc3084301f54409 100644 (file)
@@ -314,7 +314,7 @@ static struct i2c_gpio_platform_data pdata = {
 
 static struct platform_device at91sam9rl_twi_device = {
        .name                   = "i2c-gpio",
-       .id                     = -1,
+       .id                     = 0,
        .dev.platform_data      = &pdata,
 };
 
@@ -347,7 +347,7 @@ static struct resource twi_resources[] = {
 
 static struct platform_device at91sam9rl_twi_device = {
        .name           = "i2c-at91sam9g20",
-       .id             = -1,
+       .id             = 0,
        .resource       = twi_resources,
        .num_resources  = ARRAY_SIZE(twi_resources),
 };
@@ -832,7 +832,7 @@ static struct resource ssc0_resources[] = {
 };
 
 static struct platform_device at91sam9rl_ssc0_device = {
-       .name   = "ssc",
+       .name   = "at91rm9200_ssc",
        .id     = 0,
        .dev    = {
                .dma_mask               = &ssc0_dmamask,
@@ -874,7 +874,7 @@ static struct resource ssc1_resources[] = {
 };
 
 static struct platform_device at91sam9rl_ssc1_device = {
-       .name   = "ssc",
+       .name   = "at91rm9200_ssc",
        .id     = 1,
        .dev    = {
                .dma_mask               = &ssc1_dmamask,
index e5035380dcbce16e806fb460625fd73d9a3c1153..18fbbb27f97fcbb7a191867af7edaa0c2c1f4e8a 100644 (file)
@@ -231,6 +231,7 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID("t0_clk", "f800c000.timer", &tcb0_clk),
        CLKDEV_CON_DEV_ID("dma_clk", "ffffec00.dma-controller", &dma0_clk),
        CLKDEV_CON_DEV_ID("dma_clk", "ffffee00.dma-controller", &dma1_clk),
+       CLKDEV_CON_DEV_ID("pclk", "f0010000.ssc", &ssc_clk),
        CLKDEV_CON_DEV_ID(NULL, "f8010000.i2c", &twi0_clk),
        CLKDEV_CON_DEV_ID(NULL, "f8014000.i2c", &twi1_clk),
        CLKDEV_CON_DEV_ID(NULL, "f8018000.i2c", &twi2_clk),
index 6bd7300a2bc507855f28153e5871a4fcb6c4d5ed..bb7f54474b92e7f7fef65e1c504dbf4544c84992 100644 (file)
@@ -88,6 +88,6 @@ void __init at91x40_init_interrupts(unsigned int priority[NR_AIC_IRQS])
        if (!priority)
                priority = at91x40_default_irq_priority;
 
-       at91_aic_init(priority);
+       at91_aic_init(priority, at91_extern_irq);
 }
 
index 9cda3fd346ae3e4657cf415b6dbe1e4040c20db5..6960778af4c2c07eae98b998962c327d4af1632c 100644 (file)
@@ -129,7 +129,7 @@ static struct spi_board_info neocore926_spi_devices[] = {
                .max_speed_hz   = 125000 * 16,
                .bus_num        = 0,
                .platform_data  = &ads_info,
-               .irq            = AT91SAM9263_ID_IRQ1,
+               .irq            = NR_IRQS_LEGACY + AT91SAM9263_ID_IRQ1,
        },
 #endif
 };
index 27b3af1a3047e4bcf209e602f1fcc23a1561de0d..a9167dd45f96b68af3e216d90ececba5150b5f32 100644 (file)
@@ -309,7 +309,7 @@ static struct spi_board_info ek_spi_devices[] = {
                .max_speed_hz   = 125000 * 26,  /* (max sample rate @ 3V) * (cmd + data + overhead) */
                .bus_num        = 0,
                .platform_data  = &ads_info,
-               .irq            = AT91SAM9261_ID_IRQ0,
+               .irq            = NR_IRQS_LEGACY + AT91SAM9261_ID_IRQ0,
                .controller_data = (void *) AT91_PIN_PA28,      /* CS pin */
        },
 #endif
index 073e17403d982dad660126f0323754d0b36532c4..b87dbe2be0d63e71a700e116df0a3f06a389a8b3 100644 (file)
@@ -132,7 +132,7 @@ static struct spi_board_info ek_spi_devices[] = {
                .max_speed_hz   = 125000 * 26,  /* (max sample rate @ 3V) * (cmd + data + overhead) */
                .bus_num        = 0,
                .platform_data  = &ads_info,
-               .irq            = AT91SAM9263_ID_IRQ1,
+               .irq            = NR_IRQS_LEGACY + AT91SAM9263_ID_IRQ1,
        },
 #endif
 };
index 3ab2b86a3762a67da9b808386d39c51fb8cd2544..ebdbf42c02c19db171239a3d84add8da572135af 100644 (file)
@@ -353,6 +353,16 @@ static struct i2c_board_info __initdata ek_i2c_devices[] = {
         },
 };
 
+static struct platform_device sam9g20ek_audio_device = {
+       .name   = "at91sam9g20ek-audio",
+       .id     = -1,
+};
+
+static void __init ek_add_device_audio(void)
+{
+       platform_device_register(&sam9g20ek_audio_device);
+}
+
 
 static void __init ek_board_init(void)
 {
@@ -394,6 +404,7 @@ static void __init ek_board_init(void)
        at91_set_B_periph(AT91_PIN_PC1, 0);
        /* SSC (for WM8731) */
        at91_add_device_ssc(AT91SAM9260_ID_SSC, ATMEL_SSC_TX);
+       ek_add_device_audio();
 }
 
 MACHINE_START(AT91SAM9G20EK, "Atmel AT91SAM9G20-EK")
index f49650677653a0f0488e6c64346fcf07e46ae555..b62f560e6c75fbe838200cb03b3347a8c3a15241 100644 (file)
@@ -26,7 +26,8 @@ extern void __init at91_dt_initialize(void);
 extern void __init at91_init_irq_default(void);
 extern void __init at91_init_interrupts(unsigned int priority[]);
 extern void __init at91x40_init_interrupts(unsigned int priority[]);
-extern void __init at91_aic_init(unsigned int priority[]);
+extern void __init at91_aic_init(unsigned int priority[],
+                                unsigned int ext_irq_mask);
 extern int  __init at91_aic_of_init(struct device_node *node,
                                    struct device_node *parent);
 extern int  __init at91_aic5_of_init(struct device_node *node,
index 1e02c0e49dccb76949be0fc9d855a5a3bb3504bc..febc2ee901a544458a9a47c0e55473263a7c54a6 100644 (file)
@@ -502,14 +502,19 @@ int __init at91_aic5_of_init(struct device_node *node,
 /*
  * Initialize the AIC interrupt controller.
  */
-void __init at91_aic_init(unsigned int *priority)
+void __init at91_aic_init(unsigned int *priority, unsigned int ext_irq_mask)
 {
        unsigned int i;
        int irq_base;
 
-       if (at91_aic_pm_init())
+       at91_extern_irq = kzalloc(BITS_TO_LONGS(n_irqs)
+                                 * sizeof(*at91_extern_irq), GFP_KERNEL);
+
+       if (at91_aic_pm_init() || at91_extern_irq == NULL)
                panic("Unable to allocate bit maps\n");
 
+       *at91_extern_irq = ext_irq_mask;
+
        at91_aic_base = ioremap(AT91_AIC, 512);
        if (!at91_aic_base)
                panic("Unable to ioremap AIC registers\n");
index da9881b161e1e15dc0693a74c2ce2716a0ebd5d3..0b32c81730a571484a600577e3037aa5d1573c65 100644 (file)
@@ -47,7 +47,7 @@ void __init at91_init_irq_default(void)
 void __init at91_init_interrupts(unsigned int *priority)
 {
        /* Initialize the AIC interrupt controller */
-       at91_aic_init(priority);
+       at91_aic_init(priority, at91_extern_irq);
 
        /* Enable GPIO interrupts */
        at91_gpio_irq_setup();
@@ -151,7 +151,7 @@ static void __init soc_detect(u32 dbgu_base)
        }
 
        /* at91sam9g10 */
-       if ((cidr & ~AT91_CIDR_EXT) == ARCH_ID_AT91SAM9G10) {
+       if ((socid & ~AT91_CIDR_EXT) == ARCH_ID_AT91SAM9G10) {
                at91_soc_initdata.type = AT91_SOC_SAM9G10;
                at91_boot_soc = at91sam9261_soc;
        }
index 32ee3f89596738d988a00105c0358d4ff1a61f1b..d9bc3fa7bb228a8c9e7f2feca9bac83b88ac16f5 100644 (file)
@@ -762,16 +762,19 @@ static u8 da850_iis_serializer_direction[] = {
 };
 
 static struct snd_platform_data da850_evm_snd_data = {
-       .tx_dma_offset  = 0x2000,
-       .rx_dma_offset  = 0x2000,
-       .op_mode        = DAVINCI_MCASP_IIS_MODE,
-       .num_serializer = ARRAY_SIZE(da850_iis_serializer_direction),
-       .tdm_slots      = 2,
-       .serial_dir     = da850_iis_serializer_direction,
-       .asp_chan_q     = EVENTQ_0,
-       .version        = MCASP_VERSION_2,
-       .txnumevt       = 1,
-       .rxnumevt       = 1,
+       .tx_dma_offset          = 0x2000,
+       .rx_dma_offset          = 0x2000,
+       .op_mode                = DAVINCI_MCASP_IIS_MODE,
+       .num_serializer         = ARRAY_SIZE(da850_iis_serializer_direction),
+       .tdm_slots              = 2,
+       .serial_dir             = da850_iis_serializer_direction,
+       .asp_chan_q             = EVENTQ_0,
+       .ram_chan_q             = EVENTQ_1,
+       .version                = MCASP_VERSION_2,
+       .txnumevt               = 1,
+       .rxnumevt               = 1,
+       .sram_size_playback     = SZ_8K,
+       .sram_size_capture      = SZ_8K,
 };
 
 static const short da850_evm_mcasp_pins[] __initconst = {
@@ -1509,6 +1512,7 @@ static __init void da850_evm_init(void)
                pr_warning("da850_evm_init: mcasp mux setup failed: %d\n",
                                ret);
 
+       da850_evm_snd_data.sram_pool = sram_get_gen_pool();
        da8xx_register_mcasp(0, &da850_evm_snd_data);
 
        ret = davinci_cfg_reg_list(da850_lcdcntl_pins);
index cd0c8b1e1ecfad4a868b9aae3f6180a1b1794ed1..14e9947bad6e028bc9c41aecb5e1f36b045fe79a 100644 (file)
@@ -713,8 +713,7 @@ static int dm644x_venc_setup_clock(enum vpbe_enc_timings_type type,
                break;
        case VPBE_ENC_CUSTOM_TIMINGS:
                if (pclock <= 27000000) {
-                       v |= DM644X_VPSS_MUXSEL_PLL2_MODE |
-                            DM644X_VPSS_DACCLKEN;
+                       v |= DM644X_VPSS_DACCLKEN;
                        writel(v, DAVINCI_SYSMOD_VIRT(SYSMOD_VPSS_CLKCTL));
                } else {
                        /*
index 715b690e5009608c9d9bfa42b1bb6e2d595b79ee..1947be8e5f5bffec59d1542e8ebbbc6bbce36970 100644 (file)
@@ -47,6 +47,7 @@
 #include <plat/fimc-core.h>
 #include <plat/iic-core.h>
 #include <plat/tv-core.h>
+#include <plat/spi-core.h>
 #include <plat/regs-serial.h>
 
 #include "common.h"
@@ -346,6 +347,8 @@ static void __init exynos4_map_io(void)
 
        s5p_fb_setname(0, "exynos4-fb");
        s5p_hdmi_setname("exynos4-hdmi");
+
+       s3c64xx_spi_setname("exynos4210-spi");
 }
 
 static void __init exynos5_map_io(void)
@@ -366,6 +369,8 @@ static void __init exynos5_map_io(void)
        s3c_i2c0_setname("s3c2440-i2c");
        s3c_i2c1_setname("s3c2440-i2c");
        s3c_i2c2_setname("s3c2440-i2c");
+
+       s3c64xx_spi_setname("exynos4210-spi");
 }
 
 static void __init exynos4_init_clocks(int xtal)
index 21d568b3b1497c90bb79eb841f45595020351db9..87e07d6fc615769df8edfe0af8be1569859d5422 100644 (file)
@@ -275,6 +275,9 @@ static int __init exynos_dma_init(void)
                exynos_pdma1_pdata.nr_valid_peri =
                        ARRAY_SIZE(exynos4210_pdma1_peri);
                exynos_pdma1_pdata.peri_id = exynos4210_pdma1_peri;
+
+               if (samsung_rev() == EXYNOS4210_REV_0)
+                       exynos_mdma1_device.res.start = EXYNOS4_PA_S_MDMA1;
        } else if (soc_is_exynos4212() || soc_is_exynos4412()) {
                exynos_pdma0_pdata.nr_valid_peri =
                        ARRAY_SIZE(exynos4212_pdma0_peri);
index 8480849affb922789d73b597c81b76c6778a16ba..ed4da4544cd2fded70c65dd7d5d5539635a94557 100644 (file)
@@ -90,6 +90,7 @@
 
 #define EXYNOS4_PA_MDMA0               0x10810000
 #define EXYNOS4_PA_MDMA1               0x12850000
+#define EXYNOS4_PA_S_MDMA1             0x12840000
 #define EXYNOS4_PA_PDMA0               0x12680000
 #define EXYNOS4_PA_PDMA1               0x12690000
 #define EXYNOS5_PA_MDMA0               0x10800000
index e58d786faf78c773636f10b168415df2c0ac61ef..eadf4b59e7d28e6ae1d254f0f86a398759d5f9bc 100644 (file)
@@ -99,6 +99,7 @@ static char const *exynos4_dt_compat[] __initdata = {
 
 DT_MACHINE_START(EXYNOS4210_DT, "Samsung Exynos4 (Flattened Device Tree)")
        /* Maintainer: Thomas Abraham <thomas.abraham@linaro.org> */
+       .smp            = smp_ops(exynos_smp_ops),
        .init_irq       = exynos4_init_irq,
        .map_io         = exynos4_dt_map_io,
        .handle_irq     = gic_handle_irq,
index 82c27230d4a93e657ca4c4a4e1e79439c422bbae..86e37cd9376cc7a522a17a65ca39cc127dd7deeb 100644 (file)
@@ -28,6 +28,7 @@ void highbank_restart(char mode, const char *cmd)
                hignbank_set_pwr_soft_reset();
 
        scu_power_mode(scu_base_addr, SCU_PM_POWEROFF);
-       cpu_do_idle();
+       while (1)
+               cpu_do_idle();
 }
 
index 1a7a8dd045a13ab6481bcc653e877d899b0597b7..1ab91b5209e6503e7742450c4dc424a15b2e651c 100644 (file)
@@ -108,7 +108,7 @@ struct clk *imx_clk_busy_divider(const char *name, const char *parent_name,
        busy->div.hw.init = &init;
 
        clk = clk_register(NULL, &busy->div.hw);
-       if (!clk)
+       if (IS_ERR(clk))
                kfree(busy);
 
        return clk;
index 3c1b8ff9a0a61c24f2e7d6647a62168cd8a7e146..cc49c7ae186ed2bc0d3519bf7648a153ddb45d55 100644 (file)
@@ -112,7 +112,7 @@ struct clk *clk_register_gate2(struct device *dev, const char *name,
 
        clk = clk_register(dev, &gate->hw);
        if (IS_ERR(clk))
-               kfree(clk);
+               kfree(gate);
 
        return clk;
 }
index d20d4795f4eaebeb633c73ec441c36a661949a47..01e2f843bf2e0d65910bf0951f12555077f7693e 100644 (file)
@@ -127,8 +127,8 @@ int __init mx25_clocks_init(void)
        clk[esdhc2_ipg_per] = imx_clk_gate("esdhc2_ipg_per", "per4", ccm(CCM_CGCR0),  4);
        clk[gpt_ipg_per] = imx_clk_gate("gpt_ipg_per", "per5", ccm(CCM_CGCR0),  5);
        clk[i2c_ipg_per] = imx_clk_gate("i2c_ipg_per", "per6", ccm(CCM_CGCR0),  6);
-       clk[lcdc_ipg_per] = imx_clk_gate("lcdc_ipg_per", "per8", ccm(CCM_CGCR0),  7);
-       clk[nfc_ipg_per] = imx_clk_gate("nfc_ipg_per", "ipg_per", ccm(CCM_CGCR0),  8);
+       clk[lcdc_ipg_per] = imx_clk_gate("lcdc_ipg_per", "per7", ccm(CCM_CGCR0),  7);
+       clk[nfc_ipg_per] = imx_clk_gate("nfc_ipg_per", "per8", ccm(CCM_CGCR0),  8);
        clk[ssi1_ipg_per] = imx_clk_gate("ssi1_ipg_per", "per13", ccm(CCM_CGCR0), 13);
        clk[ssi2_ipg_per] = imx_clk_gate("ssi2_ipg_per", "per14", ccm(CCM_CGCR0), 14);
        clk[uart_ipg_per] = imx_clk_gate("uart_ipg_per", "per15", ccm(CCM_CGCR0), 15);
index 3b6b640eed247ea1b7848c7a7fa01801f0190cde..366e5d59d886f7cd43bb79bfe50a70c9fa6a6c5b 100644 (file)
@@ -109,7 +109,7 @@ int __init mx27_clocks_init(unsigned long fref)
        clk[per3_div] = imx_clk_divider("per3_div", "mpll_main2", CCM_PCDR1, 16, 6);
        clk[per4_div] = imx_clk_divider("per4_div", "mpll_main2", CCM_PCDR1, 24, 6);
        clk[vpu_sel] = imx_clk_mux("vpu_sel", CCM_CSCR, 21, 1, vpu_sel_clks, ARRAY_SIZE(vpu_sel_clks));
-       clk[vpu_div] = imx_clk_divider("vpu_div", "vpu_sel", CCM_PCDR0, 10, 3);
+       clk[vpu_div] = imx_clk_divider("vpu_div", "vpu_sel", CCM_PCDR0, 10, 6);
        clk[usb_div] = imx_clk_divider("usb_div", "spll", CCM_CSCR, 28, 3);
        clk[cpu_sel] = imx_clk_mux("cpu_sel", CCM_CSCR, 15, 1, cpu_sel_clks, ARRAY_SIZE(cpu_sel_clks));
        clk[clko_sel] = imx_clk_mux("clko_sel", CCM_CCSR, 0, 5, clko_sel_clks, ARRAY_SIZE(clko_sel_clks));
@@ -121,7 +121,7 @@ int __init mx27_clocks_init(unsigned long fref)
        clk[ssi1_sel] = imx_clk_mux("ssi1_sel", CCM_CSCR, 22, 1, ssi_sel_clks, ARRAY_SIZE(ssi_sel_clks));
        clk[ssi2_sel] = imx_clk_mux("ssi2_sel", CCM_CSCR, 23, 1, ssi_sel_clks, ARRAY_SIZE(ssi_sel_clks));
        clk[ssi1_div] = imx_clk_divider("ssi1_div", "ssi1_sel", CCM_PCDR0, 16, 6);
-       clk[ssi2_div] = imx_clk_divider("ssi2_div", "ssi2_sel", CCM_PCDR0, 26, 3);
+       clk[ssi2_div] = imx_clk_divider("ssi2_div", "ssi2_sel", CCM_PCDR0, 26, 6);
        clk[clko_en] = imx_clk_gate("clko_en", "clko_div", CCM_PCCR0, 0);
        clk[ssi2_ipg_gate] = imx_clk_gate("ssi2_ipg_gate", "ipg", CCM_PCCR0, 0);
        clk[ssi1_ipg_gate] = imx_clk_gate("ssi1_ipg_gate", "ipg", CCM_PCCR0, 1);
index 412c583a24b01a7e35fc976572cdafc50e08e13e..576af7446952553acab68a77207cfd3d71298dbe 100644 (file)
@@ -30,7 +30,7 @@
 #define MX25_H1_SIC_SHIFT      21
 #define MX25_H1_SIC_MASK       (0x3 << MX25_H1_SIC_SHIFT)
 #define MX25_H1_PP_BIT         (1 << 18)
-#define MX25_H1_PM_BIT         (1 << 8)
+#define MX25_H1_PM_BIT         (1 << 16)
 #define MX25_H1_IPPUE_UP_BIT   (1 << 7)
 #define MX25_H1_IPPUE_DOWN_BIT (1 << 6)
 #define MX25_H1_TLL_BIT                (1 << 5)
index 779e16eb65cb49aeaa58af79b19aac4e08b9bb47..293397852e4e6506bb1e46e590c292ef10fb116c 100644 (file)
@@ -30,7 +30,7 @@
 #define MX35_H1_SIC_SHIFT      21
 #define MX35_H1_SIC_MASK       (0x3 << MX35_H1_SIC_SHIFT)
 #define MX35_H1_PP_BIT         (1 << 18)
-#define MX35_H1_PM_BIT         (1 << 8)
+#define MX35_H1_PM_BIT         (1 << 16)
 #define MX35_H1_IPPUE_UP_BIT   (1 << 7)
 #define MX35_H1_IPPUE_DOWN_BIT (1 << 6)
 #define MX35_H1_TLL_BIT                (1 << 5)
index 9d2c843bde02438ccd79b2b5552397b97aeb1b65..b5deb0554552d1bbe586fcf2b7fd2d1bc0a33c06 100644 (file)
@@ -108,9 +108,8 @@ void __init imx3_init_l2x0(void)
        }
 
        l2x0_base = ioremap(MX3x_L2CC_BASE_ADDR, 4096);
-       if (IS_ERR(l2x0_base)) {
-               printk(KERN_ERR "remapping L2 cache area failed with %ld\n",
-                               PTR_ERR(l2x0_base));
+       if (!l2x0_base) {
+               printk(KERN_ERR "remapping L2 cache area failed\n");
                return;
        }
 
index 2a1a898c7f90c661ec641aead23acd8d00a634cb..d669e227e00c18ac1c9783fd4e370d6f3b9e51e6 100644 (file)
@@ -11,7 +11,6 @@ config ARCH_OMAP2PLUS_TYPICAL
        select I2C_OMAP
        select MENELAUS if ARCH_OMAP2
        select NEON if ARCH_OMAP3 || ARCH_OMAP4 || SOC_OMAP5
-       select PINCTRL
        select PM_RUNTIME
        select REGULATOR
        select SERIAL_OMAP
index 48d5e41dfbfabe3da59ef00f7457f5012cf2ec1a..378590694447bdbdd3ed4d7862624ac5d000c402 100644 (file)
@@ -580,6 +580,11 @@ static void __init igep_wlan_bt_init(void)
        } else
                return;
 
+       /* Make sure that the GPIO pins are muxed correctly */
+       omap_mux_init_gpio(igep_wlan_bt_gpios[0].gpio, OMAP_PIN_OUTPUT);
+       omap_mux_init_gpio(igep_wlan_bt_gpios[1].gpio, OMAP_PIN_OUTPUT);
+       omap_mux_init_gpio(igep_wlan_bt_gpios[2].gpio, OMAP_PIN_OUTPUT);
+
        err = gpio_request_array(igep_wlan_bt_gpios,
                                 ARRAY_SIZE(igep_wlan_bt_gpios));
        if (err) {
index 388c431c745a0e4134c847f96f84b73912053bf7..d41ab98890ffcc45731c7625b3ad7f44d53bb855 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/input.h>
 #include <linux/gpio_keys.h>
 #include <linux/opp.h>
+#include <linux/cpu.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
@@ -444,27 +445,31 @@ static struct omap_board_mux board_mux[] __initdata = {
 };
 #endif
 
-static void __init beagle_opp_init(void)
+static int __init beagle_opp_init(void)
 {
        int r = 0;
 
-       /* Initialize the omap3 opp table */
-       if (omap3_opp_init()) {
+       if (!machine_is_omap3_beagle())
+               return 0;
+
+       /* Initialize the omap3 opp table if not already created. */
+       r = omap3_opp_init();
+       if (IS_ERR_VALUE(r) && (r != -EEXIST)) {
                pr_err("%s: opp default init failed\n", __func__);
-               return;
+               return r;
        }
 
        /* Custom OPP enabled for all xM versions */
        if (cpu_is_omap3630()) {
                struct device *mpu_dev, *iva_dev;
 
-               mpu_dev = omap_device_get_by_hwmod_name("mpu");
+               mpu_dev = get_cpu_device(0);
                iva_dev = omap_device_get_by_hwmod_name("iva");
 
                if (IS_ERR(mpu_dev) || IS_ERR(iva_dev)) {
                        pr_err("%s: Aiee.. no mpu/dsp devices? %p %p\n",
                                __func__, mpu_dev, iva_dev);
-                       return;
+                       return -ENODEV;
                }
                /* Enable MPU 1GHz and lower opps */
                r = opp_enable(mpu_dev, 800000000);
@@ -484,8 +489,9 @@ static void __init beagle_opp_init(void)
                        opp_disable(iva_dev, 660000000);
                }
        }
-       return;
+       return 0;
 }
+device_initcall(beagle_opp_init);
 
 static void __init omap3_beagle_init(void)
 {
@@ -522,8 +528,6 @@ static void __init omap3_beagle_init(void)
        /* Ensure SDRC pins are mux'd for self-refresh */
        omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT);
        omap_mux_init_signal("sdrc_cke1", OMAP_PIN_OUTPUT);
-
-       beagle_opp_init();
 }
 
 MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagle Board")
index 114ab4b8e0e356883192bb847237172df9d46ab3..1a45d6bd253921a9b8e8f646f568c868a0b4df85 100644 (file)
@@ -1073,6 +1073,8 @@ static struct omap_clk am33xx_clks[] = {
        CLK(NULL,       "gfx_fck_div_ck",       &gfx_fck_div_ck,        CK_AM33XX),
        CLK(NULL,       "sysclkout_pre_ck",     &sysclkout_pre_ck,      CK_AM33XX),
        CLK(NULL,       "clkout2_ck",           &clkout2_ck,    CK_AM33XX),
+       CLK(NULL,       "timer_32k_ck",         &clkdiv32k_ick, CK_AM33XX),
+       CLK(NULL,       "timer_sys_ck",         &sys_clkin_ck,  CK_AM33XX),
 };
 
 int __init am33xx_clk_init(void)
index b56d06b48782a8608f77c43f9902972c1cb24bd5..95192a062d5db4b8401e73a78492c2990c26a463 100644 (file)
@@ -359,7 +359,7 @@ static struct clockdomain iss_44xx_clkdm = {
        .clkdm_offs       = OMAP4430_CM2_CAM_CAM_CDOFFS,
        .wkdep_srcs       = iss_wkup_sleep_deps,
        .sleepdep_srcs    = iss_wkup_sleep_deps,
-       .flags            = CLKDM_CAN_HWSUP_SWSUP,
+       .flags            = CLKDM_CAN_SWSUP,
 };
 
 static struct clockdomain l3_dss_44xx_clkdm = {
index 48daac2581b4a154a768923681ac108c084a5c98..84551f205e46fd20d5ef47849d279643f80f3b18 100644 (file)
@@ -64,30 +64,36 @@ void __init omap_ads7846_init(int bus_num, int gpio_pendown, int gpio_debounce,
        struct spi_board_info *spi_bi = &ads7846_spi_board_info;
        int err;
 
-       err = gpio_request_one(gpio_pendown, GPIOF_IN, "TSPenDown");
-       if (err) {
-               pr_err("Couldn't obtain gpio for TSPenDown: %d\n", err);
-               return;
-       }
+       /*
+        * If a board defines get_pendown_state() function, request the pendown
+        * GPIO and set the GPIO debounce time.
+        * If a board does not define the get_pendown_state() function, then
+        * the ads7846 driver will setup the pendown GPIO itself.
+        */
+       if (board_pdata && board_pdata->get_pendown_state) {
+               err = gpio_request_one(gpio_pendown, GPIOF_IN, "TSPenDown");
+               if (err) {
+                       pr_err("Couldn't obtain gpio for TSPenDown: %d\n", err);
+                       return;
+               }
 
-       if (gpio_debounce)
-               gpio_set_debounce(gpio_pendown, gpio_debounce);
+               if (gpio_debounce)
+                       gpio_set_debounce(gpio_pendown, gpio_debounce);
+
+               gpio_export(gpio_pendown, 0);
+       }
 
        spi_bi->bus_num = bus_num;
        spi_bi->irq     = gpio_to_irq(gpio_pendown);
 
+       ads7846_config.gpio_pendown = gpio_pendown;
+
        if (board_pdata) {
                board_pdata->gpio_pendown = gpio_pendown;
+               board_pdata->gpio_pendown_debounce = gpio_debounce;
                spi_bi->platform_data = board_pdata;
-               if (board_pdata->get_pendown_state)
-                       gpio_export(gpio_pendown, 0);
-       } else {
-               ads7846_config.gpio_pendown = gpio_pendown;
        }
 
-       if (!board_pdata || (board_pdata && !board_pdata->get_pendown_state))
-               gpio_free(gpio_pendown);
-
        spi_register_board_info(&ads7846_spi_board_info, 1);
 }
 #else
index cba60e05e32ecef6a6c97cbf6679b99f474d4a5a..c72b5a7277200d08bc28e3b5348bfedcb677fefc 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/of.h>
 #include <linux/pinctrl/machine.h>
 #include <linux/platform_data/omap4-keypad.h>
+#include <linux/platform_data/omap_ocp2scp.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/map.h>
@@ -613,6 +614,83 @@ static void omap_init_vout(void)
 static inline void omap_init_vout(void) {}
 #endif
 
+#if defined(CONFIG_OMAP_OCP2SCP) || defined(CONFIG_OMAP_OCP2SCP_MODULE)
+static int count_ocp2scp_devices(struct omap_ocp2scp_dev *ocp2scp_dev)
+{
+       int cnt = 0;
+
+       while (ocp2scp_dev->drv_name != NULL) {
+               cnt++;
+               ocp2scp_dev++;
+       }
+
+       return cnt;
+}
+
+static void omap_init_ocp2scp(void)
+{
+       struct omap_hwmod       *oh;
+       struct platform_device  *pdev;
+       int                     bus_id = -1, dev_cnt = 0, i;
+       struct omap_ocp2scp_dev *ocp2scp_dev;
+       const char              *oh_name, *name;
+       struct omap_ocp2scp_platform_data *pdata;
+
+       if (!cpu_is_omap44xx())
+               return;
+
+       oh_name = "ocp2scp_usb_phy";
+       name    = "omap-ocp2scp";
+
+       oh = omap_hwmod_lookup(oh_name);
+       if (!oh) {
+               pr_err("%s: could not find omap_hwmod for %s\n", __func__,
+                                                               oh_name);
+               return;
+       }
+
+       pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+       if (!pdata) {
+               pr_err("%s: No memory for ocp2scp pdata\n", __func__);
+               return;
+       }
+
+       ocp2scp_dev = oh->dev_attr;
+       dev_cnt = count_ocp2scp_devices(ocp2scp_dev);
+
+       if (!dev_cnt) {
+               pr_err("%s: No devices connected to ocp2scp\n", __func__);
+               kfree(pdata);
+               return;
+       }
+
+       pdata->devices = kzalloc(sizeof(struct omap_ocp2scp_dev *)
+                                       * dev_cnt, GFP_KERNEL);
+       if (!pdata->devices) {
+               pr_err("%s: No memory for ocp2scp pdata devices\n", __func__);
+               kfree(pdata);
+               return;
+       }
+
+       for (i = 0; i < dev_cnt; i++, ocp2scp_dev++)
+               pdata->devices[i] = ocp2scp_dev;
+
+       pdata->dev_cnt  = dev_cnt;
+
+       pdev = omap_device_build(name, bus_id, oh, pdata, sizeof(*pdata), NULL,
+                                                               0, false);
+       if (IS_ERR(pdev)) {
+               pr_err("Could not build omap_device for %s %s\n",
+                                               name, oh_name);
+               kfree(pdata->devices);
+               kfree(pdata);
+               return;
+       }
+}
+#else
+static inline void omap_init_ocp2scp(void) { }
+#endif
+
 /*-------------------------------------------------------------------------*/
 
 static int __init omap2_init_devices(void)
@@ -640,6 +718,7 @@ static int __init omap2_init_devices(void)
        omap_init_sham();
        omap_init_aes();
        omap_init_vout();
+       omap_init_ocp2scp();
 
        return 0;
 }
index 17f80e4ab162e4f2d4f15f8d99ccfa03496e225b..c47140bbbec4d8a5243110a68703d2861a7f3cb0 100644 (file)
@@ -614,16 +614,16 @@ static struct omap_mux __initdata omap3_muxmodes[] = {
                "sys_off_mode", NULL, NULL, NULL,
                "gpio_9", NULL, NULL, "safe_mode"),
        _OMAP3_MUXENTRY(UART1_CTS, 150,
-               "uart1_cts", NULL, NULL, NULL,
+               "uart1_cts", "ssi1_rdy_tx", NULL, NULL,
                "gpio_150", "hsusb3_tll_clk", NULL, "safe_mode"),
        _OMAP3_MUXENTRY(UART1_RTS, 149,
-               "uart1_rts", NULL, NULL, NULL,
+               "uart1_rts", "ssi1_flag_tx", NULL, NULL,
                "gpio_149", NULL, NULL, "safe_mode"),
        _OMAP3_MUXENTRY(UART1_RX, 151,
-               "uart1_rx", NULL, "mcbsp1_clkr", "mcspi4_clk",
+               "uart1_rx", "ss1_wake_tx", "mcbsp1_clkr", "mcspi4_clk",
                "gpio_151", NULL, NULL, "safe_mode"),
        _OMAP3_MUXENTRY(UART1_TX, 148,
-               "uart1_tx", NULL, NULL, NULL,
+               "uart1_tx", "ssi1_dat_tx", NULL, NULL,
                "gpio_148", NULL, NULL, "safe_mode"),
        _OMAP3_MUXENTRY(UART2_CTS, 144,
                "uart2_cts", "mcbsp3_dx", "gpt9_pwm_evt", NULL,
index b969ab1d258b91894415c3507bd8b50cd2aefa50..87cc6d058de25cf2552c1b274af1a06f5d3ee509 100644 (file)
@@ -421,6 +421,38 @@ static int _set_softreset(struct omap_hwmod *oh, u32 *v)
        return 0;
 }
 
+/**
+ * _wait_softreset_complete - wait for an OCP softreset to complete
+ * @oh: struct omap_hwmod * to wait on
+ *
+ * Wait until the IP block represented by @oh reports that its OCP
+ * softreset is complete.  This can be triggered by software (see
+ * _ocp_softreset()) or by hardware upon returning from off-mode (one
+ * example is HSMMC).  Waits for up to MAX_MODULE_SOFTRESET_WAIT
+ * microseconds.  Returns the number of microseconds waited.
+ */
+static int _wait_softreset_complete(struct omap_hwmod *oh)
+{
+       struct omap_hwmod_class_sysconfig *sysc;
+       u32 softrst_mask;
+       int c = 0;
+
+       sysc = oh->class->sysc;
+
+       if (sysc->sysc_flags & SYSS_HAS_RESET_STATUS)
+               omap_test_timeout((omap_hwmod_read(oh, sysc->syss_offs)
+                                  & SYSS_RESETDONE_MASK),
+                                 MAX_MODULE_SOFTRESET_WAIT, c);
+       else if (sysc->sysc_flags & SYSC_HAS_RESET_STATUS) {
+               softrst_mask = (0x1 << sysc->sysc_fields->srst_shift);
+               omap_test_timeout(!(omap_hwmod_read(oh, sysc->sysc_offs)
+                                   & softrst_mask),
+                                 MAX_MODULE_SOFTRESET_WAIT, c);
+       }
+
+       return c;
+}
+
 /**
  * _set_dmadisable: set OCP_SYSCONFIG.DMADISABLE bit in @v
  * @oh: struct omap_hwmod *
@@ -1282,6 +1314,18 @@ static void _enable_sysc(struct omap_hwmod *oh)
        if (!oh->class->sysc)
                return;
 
+       /*
+        * Wait until reset has completed, this is needed as the IP
+        * block is reset automatically by hardware in some cases
+        * (off-mode for example), and the drivers require the
+        * IP to be ready when they access it
+        */
+       if (oh->flags & HWMOD_CONTROL_OPT_CLKS_IN_RESET)
+               _enable_optional_clocks(oh);
+       _wait_softreset_complete(oh);
+       if (oh->flags & HWMOD_CONTROL_OPT_CLKS_IN_RESET)
+               _disable_optional_clocks(oh);
+
        v = oh->_sysc_cache;
        sf = oh->class->sysc->sysc_flags;
 
@@ -1804,7 +1848,7 @@ static int _am33xx_disable_module(struct omap_hwmod *oh)
  */
 static int _ocp_softreset(struct omap_hwmod *oh)
 {
-       u32 v, softrst_mask;
+       u32 v;
        int c = 0;
        int ret = 0;
 
@@ -1834,19 +1878,7 @@ static int _ocp_softreset(struct omap_hwmod *oh)
        if (oh->class->sysc->srst_udelay)
                udelay(oh->class->sysc->srst_udelay);
 
-       if (oh->class->sysc->sysc_flags & SYSS_HAS_RESET_STATUS)
-               omap_test_timeout((omap_hwmod_read(oh,
-                                                   oh->class->sysc->syss_offs)
-                                  & SYSS_RESETDONE_MASK),
-                                 MAX_MODULE_SOFTRESET_WAIT, c);
-       else if (oh->class->sysc->sysc_flags & SYSC_HAS_RESET_STATUS) {
-               softrst_mask = (0x1 << oh->class->sysc->sysc_fields->srst_shift);
-               omap_test_timeout(!(omap_hwmod_read(oh,
-                                                    oh->class->sysc->sysc_offs)
-                                  & softrst_mask),
-                                 MAX_MODULE_SOFTRESET_WAIT, c);
-       }
-
+       c = _wait_softreset_complete(oh);
        if (c == MAX_MODULE_SOFTRESET_WAIT)
                pr_warning("omap_hwmod: %s: softreset failed (waited %d usec)\n",
                           oh->name, MAX_MODULE_SOFTRESET_WAIT);
@@ -2352,6 +2384,9 @@ static int __init _setup_reset(struct omap_hwmod *oh)
        if (oh->_state != _HWMOD_STATE_INITIALIZED)
                return -EINVAL;
 
+       if (oh->flags & HWMOD_EXT_OPT_MAIN_CLK)
+               return -EPERM;
+
        if (oh->rst_lines_cnt == 0) {
                r = _enable(oh);
                if (r) {
index 652d0285bd6dd7b1a445bcbab02e395e04c5e11a..0b1249e003987da276c2072aed5d39bcc334e8f5 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/io.h>
 #include <linux/platform_data/gpio-omap.h>
 #include <linux/power/smartreflex.h>
+#include <linux/platform_data/omap_ocp2scp.h>
 
 #include <plat/omap_hwmod.h>
 #include <plat/i2c.h>
@@ -2125,6 +2126,14 @@ static struct omap_hwmod omap44xx_mcpdm_hwmod = {
        .name           = "mcpdm",
        .class          = &omap44xx_mcpdm_hwmod_class,
        .clkdm_name     = "abe_clkdm",
+       /*
+        * It's suspected that the McPDM requires an off-chip main
+        * functional clock, controlled via I2C.  This IP block is
+        * currently reset very early during boot, before I2C is
+        * available, so it doesn't seem that we have any choice in
+        * the kernel other than to avoid resetting it.
+        */
+       .flags          = HWMOD_EXT_OPT_MAIN_CLK,
        .mpu_irqs       = omap44xx_mcpdm_irqs,
        .sdma_reqs      = omap44xx_mcpdm_sdma_reqs,
        .main_clk       = "mcpdm_fck",
@@ -2681,6 +2690,32 @@ static struct omap_hwmod_class omap44xx_ocp2scp_hwmod_class = {
        .sysc   = &omap44xx_ocp2scp_sysc,
 };
 
+/* ocp2scp dev_attr */
+static struct resource omap44xx_usb_phy_and_pll_addrs[] = {
+       {
+               .name           = "usb_phy",
+               .start          = 0x4a0ad080,
+               .end            = 0x4a0ae000,
+               .flags          = IORESOURCE_MEM,
+       },
+       {
+               /* XXX: Remove this once control module driver is in place */
+               .name           = "ctrl_dev",
+               .start          = 0x4a002300,
+               .end            = 0x4a002303,
+               .flags          = IORESOURCE_MEM,
+       },
+       { }
+};
+
+static struct omap_ocp2scp_dev ocp2scp_dev_attr[] = {
+       {
+               .drv_name       = "omap-usb2",
+               .res            = omap44xx_usb_phy_and_pll_addrs,
+       },
+       { }
+};
+
 /* ocp2scp_usb_phy */
 static struct omap_hwmod omap44xx_ocp2scp_usb_phy_hwmod = {
        .name           = "ocp2scp_usb_phy",
@@ -2694,6 +2729,7 @@ static struct omap_hwmod omap44xx_ocp2scp_usb_phy_hwmod = {
                        .modulemode   = MODULEMODE_HWCTRL,
                },
        },
+       .dev_attr       = ocp2scp_dev_attr,
 };
 
 /*
index 686137d164dac9faee69b2293e524fa08c69bcea..67d66131cfa796c9f0724e43a2820a0752e1fa73 100644 (file)
@@ -91,6 +91,7 @@ extern void omap3_save_scratchpad_contents(void);
 
 #define PM_RTA_ERRATUM_i608            (1 << 0)
 #define PM_SDRC_WAKEUP_ERRATUM_i583    (1 << 1)
+#define PM_PER_MEMORIES_ERRATUM_i582   (1 << 2)
 
 #if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3)
 extern u16 pm34xx_errata;
index ba670db1fd37416a8da3e1d343b319afa8161adf..3a904de4313ec82deb6b4f2e61d460e318ef0e87 100644 (file)
@@ -652,14 +652,17 @@ static void __init pm_errata_configure(void)
                /* Enable the l2 cache toggling in sleep logic */
                enable_omap3630_toggle_l2_on_restore();
                if (omap_rev() < OMAP3630_REV_ES1_2)
-                       pm34xx_errata |= PM_SDRC_WAKEUP_ERRATUM_i583;
+                       pm34xx_errata |= (PM_SDRC_WAKEUP_ERRATUM_i583 |
+                                         PM_PER_MEMORIES_ERRATUM_i582);
+       } else if (cpu_is_omap34xx()) {
+               pm34xx_errata |= PM_PER_MEMORIES_ERRATUM_i582;
        }
 }
 
 int __init omap3_pm_init(void)
 {
        struct power_state *pwrst, *tmp;
-       struct clockdomain *neon_clkdm, *mpu_clkdm;
+       struct clockdomain *neon_clkdm, *mpu_clkdm, *per_clkdm, *wkup_clkdm;
        int ret;
 
        if (!omap3_has_io_chain_ctrl())
@@ -711,6 +714,8 @@ int __init omap3_pm_init(void)
 
        neon_clkdm = clkdm_lookup("neon_clkdm");
        mpu_clkdm = clkdm_lookup("mpu_clkdm");
+       per_clkdm = clkdm_lookup("per_clkdm");
+       wkup_clkdm = clkdm_lookup("wkup_clkdm");
 
 #ifdef CONFIG_SUSPEND
        omap_pm_suspend = omap3_pm_suspend;
@@ -727,6 +732,27 @@ int __init omap3_pm_init(void)
        if (IS_PM34XX_ERRATUM(PM_RTA_ERRATUM_i608))
                omap3630_ctrl_disable_rta();
 
+       /*
+        * The UART3/4 FIFO and the sidetone memory in McBSP2/3 are
+        * not correctly reset when the PER powerdomain comes back
+        * from OFF or OSWR when the CORE powerdomain is kept active.
+        * See OMAP36xx Erratum i582 "PER Domain reset issue after
+        * Domain-OFF/OSWR Wakeup".  This wakeup dependency is not a
+        * complete workaround.  The kernel must also prevent the PER
+        * powerdomain from going to OSWR/OFF while the CORE
+        * powerdomain is not going to OSWR/OFF.  And if PER last
+        * power state was off while CORE last power state was ON, the
+        * UART3/4 and McBSP2/3 SIDETONE devices need to run a
+        * self-test using their loopback tests; if that fails, those
+        * devices are unusable until the PER/CORE can complete a transition
+        * from ON to OSWR/OFF and then back to ON.
+        *
+        * XXX Technically this workaround is only needed if off-mode
+        * or OSWR is enabled.
+        */
+       if (IS_PM34XX_ERRATUM(PM_PER_MEMORIES_ERRATUM_i582))
+               clkdm_add_wkdep(per_clkdm, wkup_clkdm);
+
        clkdm_add_wkdep(neon_clkdm, mpu_clkdm);
        if (omap_type() != OMAP2_DEVICE_TYPE_GP) {
                omap3_secure_ram_storage =
index 0405c8190803a34ef666dd197a15f18dccdcad8f..a507cd6cf4f12259ab6a0bbad75fdc2e38bbe3a8 100644 (file)
@@ -329,6 +329,11 @@ void __init omap_serial_init_port(struct omap_board_data *bdata,
 
        oh->mux = omap_hwmod_mux_init(bdata->pads, bdata->pads_cnt);
 
+       if (console_uart_id == bdata->id) {
+               omap_device_enable(pdev);
+               pm_runtime_set_active(&pdev->dev);
+       }
+
        oh->dev_attr = uart;
 
        if (((cpu_is_omap34xx() || cpu_is_omap44xx()) && bdata->pads)
index 635e109f5ad352e97e04dfad00c11e8728c72c98..a256135d8e48f59c0a6a103b2d449682caac9be2 100644 (file)
@@ -73,6 +73,7 @@ void __init omap4_pmic_init(const char *pmic_type,
 {
        /* PMIC part*/
        omap_mux_init_signal("sys_nirq1", OMAP_PIN_INPUT_PULLUP | OMAP_PIN_OFF_WAKEUPENABLE);
+       omap_mux_init_signal("fref_clk0_out.sys_drm_msecure", OMAP_PIN_OUTPUT);
        omap_pmic_init(1, 400, pmic_type, 7 + OMAP44XX_IRQ_GIC_START, pmic_data);
 
        /* Register additional devices on i2c1 bus if needed */
@@ -366,7 +367,7 @@ static struct regulator_init_data omap4_clk32kg_idata = {
 };
 
 static struct regulator_consumer_supply omap4_vdd1_supply[] = {
-       REGULATOR_SUPPLY("vcc", "mpu.0"),
+       REGULATOR_SUPPLY("vcc", "cpu0"),
 };
 
 static struct regulator_consumer_supply omap4_vdd2_supply[] = {
index 880249b170125b0c9f6b4d870e9f3d6a6420fc53..75878c37959bff682bfdefca0548afb001891734 100644 (file)
@@ -264,7 +264,7 @@ static void __init omap_vc_i2c_init(struct voltagedomain *voltdm)
 
        if (initialized) {
                if (voltdm->pmic->i2c_high_speed != i2c_high_speed)
-                       pr_warn("%s: I2C config for vdd_%s does not match other channels (%u).",
+                       pr_warn("%s: I2C config for vdd_%s does not match other channels (%u).\n",
                                __func__, voltdm->name, i2c_high_speed);
                return;
        }
index 5ecbd17b56416a40c0e966508b37066d29b81d55..e2c6391863fedd9b008d594c516eea1f55936e64 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/mfd/asic3.h>
 #include <linux/mtd/physmap.h>
 #include <linux/pda_power.h>
+#include <linux/pwm.h>
 #include <linux/pwm_backlight.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/gpio-regulator.h>
@@ -556,7 +557,7 @@ static struct platform_device hx4700_lcd = {
  */
 
 static struct platform_pwm_backlight_data backlight_data = {
-       .pwm_id         = 1,
+       .pwm_id         = -1,   /* Superseded by pwm_lookup */
        .max_brightness = 200,
        .dft_brightness = 100,
        .pwm_period_ns  = 30923,
@@ -571,6 +572,10 @@ static struct platform_device backlight = {
        },
 };
 
+static struct pwm_lookup hx4700_pwm_lookup[] = {
+       PWM_LOOKUP("pxa27x-pwm.1", 0, "pwm-backlight", NULL),
+};
+
 /*
  * USB "Transceiver"
  */
@@ -872,6 +877,7 @@ static void __init hx4700_init(void)
        pxa_set_stuart_info(NULL);
 
        platform_add_devices(devices, ARRAY_SIZE(devices));
+       pwm_add_table(hx4700_pwm_lookup, ARRAY_SIZE(hx4700_pwm_lookup));
 
        pxa_set_ficp_info(&ficp_info);
        pxa27x_set_i2c_power_info(NULL);
index 438f02fe122a6d1d727671675af53b7564b99ae4..842596d4d31e19e59cd898084125944a03db7b90 100644 (file)
@@ -86,10 +86,7 @@ static void spitz_discharge1(int on)
        gpio_set_value(SPITZ_GPIO_LED_GREEN, on);
 }
 
-static unsigned long gpio18_config[] = {
-       GPIO18_RDY,
-       GPIO18_GPIO,
-};
+static unsigned long gpio18_config = GPIO18_GPIO;
 
 static void spitz_presuspend(void)
 {
@@ -112,7 +109,7 @@ static void spitz_presuspend(void)
        PGSR3 &= ~SPITZ_GPIO_G3_STROBE_BIT;
        PGSR2 |= GPIO_bit(SPITZ_GPIO_KEY_STROBE0);
 
-       pxa2xx_mfp_config(&gpio18_config[0], 1);
+       pxa2xx_mfp_config(&gpio18_config, 1);
        gpio_request_one(18, GPIOF_OUT_INIT_HIGH, "Unknown");
        gpio_free(18);
 
@@ -131,7 +128,6 @@ static void spitz_presuspend(void)
 
 static void spitz_postsuspend(void)
 {
-       pxa2xx_mfp_config(&gpio18_config[1], 1);
 }
 
 static int spitz_should_wakeup(unsigned int resume_on_alarm)
index ed5a95ece9eb2d365b7152cdb4bd5cfe508e672b..77ee0b732237d93de59c80632279a00dbf5dc2bd 100644 (file)
@@ -61,6 +61,7 @@
 #include <plat/nand-core.h>
 #include <plat/adc-core.h>
 #include <plat/rtc-core.h>
+#include <plat/spi-core.h>
 
 static struct map_desc s3c2416_iodesc[] __initdata = {
        IODESC_ENT(WATCHDOG),
@@ -132,6 +133,7 @@ void __init s3c2416_map_io(void)
        /* initialize device information early */
        s3c2416_default_sdhci0();
        s3c2416_default_sdhci1();
+       s3c64xx_spi_setname("s3c2443-spi");
 
        iotable_init(s3c2416_iodesc, ARRAY_SIZE(s3c2416_iodesc));
 }
index ab648ad8fa508651624054ca2d9693f9d34fb1e5..165b6a6b3daaa9450201db7b0c721f76c62574f2 100644 (file)
@@ -43,6 +43,7 @@
 #include <plat/nand-core.h>
 #include <plat/adc-core.h>
 #include <plat/rtc-core.h>
+#include <plat/spi-core.h>
 
 static struct map_desc s3c2443_iodesc[] __initdata = {
        IODESC_ENT(WATCHDOG),
@@ -100,6 +101,9 @@ void __init s3c2443_map_io(void)
        s3c24xx_gpiocfg_default.set_pull = s3c2443_gpio_setpull;
        s3c24xx_gpiocfg_default.get_pull = s3c2443_gpio_getpull;
 
+       /* initialize device information early */
+       s3c64xx_spi_setname("s3c2443-spi");
+
        iotable_init(s3c2443_iodesc, ARRAY_SIZE(s3c2443_iodesc));
 }
 
index 6e6a0a9d6778b0b1fe41a6857cef015ee55bc39d..111e404a81fd44a8627025c975898e12f20598b7 100644 (file)
@@ -44,6 +44,7 @@
 #include <plat/sdhci.h>
 #include <plat/adc-core.h>
 #include <plat/fb-core.h>
+#include <plat/spi-core.h>
 #include <plat/gpio-cfg.h>
 #include <plat/regs-irqtype.h>
 #include <plat/regs-serial.h>
@@ -179,6 +180,7 @@ void __init s5p6440_map_io(void)
        /* initialize any device information early */
        s3c_adc_setname("s3c64xx-adc");
        s3c_fb_setname("s5p64x0-fb");
+       s3c64xx_spi_setname("s5p64x0-spi");
 
        s5p64x0_default_sdhci0();
        s5p64x0_default_sdhci1();
@@ -193,6 +195,7 @@ void __init s5p6450_map_io(void)
        /* initialize any device information early */
        s3c_adc_setname("s3c64xx-adc");
        s3c_fb_setname("s5p64x0-fb");
+       s3c64xx_spi_setname("s5p64x0-spi");
 
        s5p64x0_default_sdhci0();
        s5p64x0_default_sdhci1();
index 621908658861596a43e4817f6978e352eab7604d..cc6e561c99588430f7e3b99993d761ffebecf949 100644 (file)
@@ -45,6 +45,7 @@
 #include <plat/fb-core.h>
 #include <plat/iic-core.h>
 #include <plat/onenand-core.h>
+#include <plat/spi-core.h>
 #include <plat/regs-serial.h>
 #include <plat/watchdog-reset.h>
 
@@ -165,6 +166,8 @@ void __init s5pc100_map_io(void)
        s3c_onenand_setname("s5pc100-onenand");
        s3c_fb_setname("s5pc100-fb");
        s3c_cfcon_setname("s5pc100-pata");
+
+       s3c64xx_spi_setname("s5pc100-spi");
 }
 
 void __init s5pc100_init_clocks(int xtal)
index 4c9e9027df9aed2cbd0314ec1cebc0d80a1d3530..a0c50efe8145f167b4482a814e15329d7f32db27 100644 (file)
@@ -43,6 +43,7 @@
 #include <plat/iic-core.h>
 #include <plat/keypad-core.h>
 #include <plat/tv-core.h>
+#include <plat/spi-core.h>
 #include <plat/regs-serial.h>
 
 #include "common.h"
@@ -196,6 +197,8 @@ void __init s5pv210_map_io(void)
 
        /* setup TV devices */
        s5p_hdmi_setname("s5pv210-hdmi");
+
+       s3c64xx_spi_setname("s5pv210-spi");
 }
 
 void __init s5pv210_init_clocks(int xtal)
index 2917668f0091c1042a70e512f50c12bacdb3ebb2..ebbffc25f24fc1ad48c75d36ee10d36709cc7a1e 100644 (file)
@@ -247,7 +247,7 @@ void __init r8a7779_add_standard_devices(void)
 {
 #ifdef CONFIG_CACHE_L2X0
        /* Early BRESP enable, Shared attribute override enable, 64K*16way */
-       l2x0_init((void __iomem __force *)(0xf0100000), 0x40470000, 0x82000fff);
+       l2x0_init(IOMEM(0xf0100000), 0x40470000, 0x82000fff);
 #endif
        r8a7779_pm_init();
 
diff --git a/arch/arm/mach-spear13xx/include/mach/spear1310_misc_regs.h b/arch/arm/mach-spear13xx/include/mach/spear1310_misc_regs.h
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/arch/arm/mach-spear13xx/include/mach/spear1340_misc_regs.h b/arch/arm/mach-spear13xx/include/mach/spear1340_misc_regs.h
deleted file mode 100644 (file)
index e69de29..0000000
index 2236cbd03cd79c11d897353d33401ddc4a3c962e..1f3fbc2bb7768a4389e8c7796affdfb65f521d1b 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/stat.h>
 #include <linux/of.h>
 #include <linux/of_irq.h>
+#include <linux/irq.h>
 #include <linux/platform_data/clk-ux500.h>
 
 #include <asm/hardware/gic.h>
index b9f60ebe3bc4f13f3dc13e4e4531da549890eca4..b820edaf31843fb309fc29f882ce9d4e80c04c62 100644 (file)
@@ -745,7 +745,7 @@ do_alignment_t32_to_handler(unsigned long *pinstr, struct pt_regs *regs,
 static int
 do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
 {
-       union offset_union offset;
+       union offset_union uninitialized_var(offset);
        unsigned long instr = 0, instrptr;
        int (*handler)(unsigned long addr, unsigned long instr, struct pt_regs *regs);
        unsigned int type;
@@ -856,8 +856,10 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
                if (thumb2_32b) {
                        offset.un = 0;
                        handler = do_alignment_t32_to_handler(&instr, regs, &offset);
-               } else
+               } else {
+                       offset.un = 0;
                        handler = do_alignment_ldmstm;
+               }
                break;
 
        default:
index 477a2d23ddf17efb95af55cebbc25d35793a417d..58bc3e4d3bd0a76094d8a2a40c0be9bece4eaf7a 100644 (file)
@@ -610,7 +610,7 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
                         gfp_t gfp, pgprot_t prot, bool is_coherent, const void *caller)
 {
        u64 mask = get_coherent_dma_mask(dev);
-       struct page *page;
+       struct page *page = NULL;
        void *addr;
 
 #ifdef CONFIG_DMA_API_DEBUG
index bf312c354a214761646a3a3738fb6080b84fff33..0f5a5f2a2c7bbc1bb79668ac291dde283741be7a 100644 (file)
@@ -17,7 +17,6 @@ struct arm_vmregion {
        struct list_head        vm_list;
        unsigned long           vm_start;
        unsigned long           vm_end;
-       void                    *priv;
        int                     vm_active;
        const void              *caller;
 };
index 540d3a7d92dfaacf8fd82cbd745327c7d2e094a9..e7b920b58675d79bab4b1ef598b18e0f05fb14ed 100644 (file)
@@ -55,7 +55,7 @@ struct platform_device *__init imx_add_mxc_mmc(
        struct resource res[] = {
                {
                        .start = data->iobase,
-                       .end = data->iobase + SZ_4K - 1,
+                       .end = data->iobase + data->iosize - 1,
                        .flags = IORESOURCE_MEM,
                }, {
                        .start = data->irq,
index 7cd56ed5cd949b25c0ae4ad02729241006b42783..82fcb206b5b25c679434c8217b72978c2a68df1f 100644 (file)
@@ -26,6 +26,7 @@ config ARCH_OMAP2PLUS
        select CLKDEV_LOOKUP
        select GENERIC_IRQ_CHIP
        select OMAP_DM_TIMER
+       select PINCTRL
        select PROC_DEVICETREE if PROC_FS
        select SPARSE_IRQ
        select USE_OF
index a5683a84c6ee0e313cb8f9daeeb7c72106952a4e..6013831a043e320fafd5e718a558d422fa67a624 100644 (file)
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/i2c.h>
+#include <linux/i2c-omap.h>
 #include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/clk.h>
 
 #include <mach/irqs.h>
 #include <plat/i2c.h>
+#include <plat/omap-pm.h>
 #include <plat/omap_device.h>
 
 #define OMAP_I2C_SIZE          0x3f
@@ -127,6 +129,16 @@ static inline int omap1_i2c_add_bus(int bus_id)
 
 
 #ifdef CONFIG_ARCH_OMAP2PLUS
+/*
+ * XXX This function is a temporary compatibility wrapper - only
+ * needed until the I2C driver can be converted to call
+ * omap_pm_set_max_dev_wakeup_lat() and handle a return code.
+ */
+static void omap_pm_set_max_mpu_wakeup_lat_compat(struct device *dev, long t)
+{
+       omap_pm_set_max_mpu_wakeup_lat(dev, t);
+}
+
 static inline int omap2_i2c_add_bus(int bus_id)
 {
        int l;
@@ -158,6 +170,15 @@ static inline int omap2_i2c_add_bus(int bus_id)
        dev_attr = (struct omap_i2c_dev_attr *)oh->dev_attr;
        pdata->flags = dev_attr->flags;
 
+       /*
+        * When waiting for completion of a i2c transfer, we need to
+        * set a wake up latency constraint for the MPU. This is to
+        * ensure quick enough wakeup from idle, when transfer
+        * completes.
+        * Only omap3 has support for constraints
+        */
+       if (cpu_is_omap34xx())
+               pdata->set_mpu_wkup_lat = omap_pm_set_max_mpu_wakeup_lat_compat;
        pdev = omap_device_build(name, bus_id, oh, pdata,
                        sizeof(struct omap_i2c_bus_platform_data),
                        NULL, 0, 0);
index f4a4cd014795d676d85ffdc05622a4ac3e889a5c..1957a8516e938e2d9f42b690903211095e6ed959 100644 (file)
 #define OMAP_UART_WER_MOD_WKUP 0X7F
 
 /* Enable XON/XOFF flow control on output */
-#define OMAP_UART_SW_TX                0x8
+#define OMAP_UART_SW_TX                0x04
 
 /* Enable XON/XOFF flow control on input */
-#define OMAP_UART_SW_RX                0x2
+#define OMAP_UART_SW_RX                0x04
 
 #define OMAP_UART_SYSC_RESET   0X07
 #define OMAP_UART_TCR_TRIG     0X0F
index b3349f7b1a2cda6458ed75b541a07298c84e7234..1db029438022066311c858079bf5753b08e359f5 100644 (file)
@@ -443,6 +443,11 @@ struct omap_hwmod_omap4_prcm {
  *     in order to complete the reset. Optional clocks will be disabled
  *     again after the reset.
  * HWMOD_16BIT_REG: Module has 16bit registers
+ * HWMOD_EXT_OPT_MAIN_CLK: The only main functional clock source for
+ *     this IP block comes from an off-chip source and is not always
+ *     enabled.  This prevents the hwmod code from being able to
+ *     enable and reset the IP block early.  XXX Eventually it should
+ *     be possible to query the clock framework for this information.
  */
 #define HWMOD_SWSUP_SIDLE                      (1 << 0)
 #define HWMOD_SWSUP_MSTANDBY                   (1 << 1)
@@ -453,6 +458,7 @@ struct omap_hwmod_omap4_prcm {
 #define HWMOD_NO_IDLEST                                (1 << 6)
 #define HWMOD_CONTROL_OPT_CLKS_IN_RESET                (1 << 7)
 #define HWMOD_16BIT_REG                                (1 << 8)
+#define HWMOD_EXT_OPT_MAIN_CLK                 (1 << 9)
 
 /*
  * omap_hwmod._int_flags definitions
diff --git a/arch/arm/plat-samsung/include/plat/spi-core.h b/arch/arm/plat-samsung/include/plat/spi-core.h
new file mode 100644 (file)
index 0000000..0b9428a
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2012 Heiko Stuebner <heiko@sntech.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __PLAT_S3C_SPI_CORE_H
+#define __PLAT_S3C_SPI_CORE_H
+
+/* These functions are only for use with the core support code, such as
+ * the cpu specific initialisation code
+ */
+
+/* re-define device name depending on support. */
+static inline void s3c64xx_spi_setname(char *name)
+{
+#ifdef CONFIG_S3C64XX_DEV_SPI0
+       s3c64xx_device_spi0.name = name;
+#endif
+#ifdef CONFIG_S3C64XX_DEV_SPI1
+       s3c64xx_device_spi1.name = name;
+#endif
+#ifdef CONFIG_S3C64XX_DEV_SPI2
+       s3c64xx_device_spi2.name = name;
+#endif
+}
+
+#endif /* __PLAT_S3C_SPI_CORE_H */
index 635cb1865e4d56af08b8579eb72dbaadfa77f211..32d05c8219dc35acf9db46a49e521ca312fc336e 100644 (file)
@@ -5,6 +5,6 @@
 #
 
 include/generated/mach-types.h: $(src)/gen-mach-types $(src)/mach-types
-       @echo '  Generating $@'
+       @$(kecho) '  Generating $@'
        @mkdir -p $(dir $@)
        $(Q)$(AWK) -f $^ > $@ || { rm -f $@; /bin/false; }
index c834b32af275d73d4cd760efeb4a365e940f1df7..3b44e0dd0a9327f8d75fc72c7bc8838a913f8571 100644 (file)
@@ -701,11 +701,14 @@ static int __init vfp_init(void)
                        elf_hwcap |= HWCAP_VFPv3;
 
                        /*
-                        * Check for VFPv3 D16. CPUs in this configuration
-                        * only have 16 x 64bit registers.
+                        * Check for VFPv3 D16 and VFPv4 D16.  CPUs in
+                        * this configuration only have 16 x 64bit
+                        * registers.
                         */
                        if (((fmrx(MVFR0) & MVFR0_A_SIMD_MASK)) == 1)
-                               elf_hwcap |= HWCAP_VFPv3D16;
+                               elf_hwcap |= HWCAP_VFPv3D16; /* also v4-D16 */
+                       else
+                               elf_hwcap |= HWCAP_VFPD32;
                }
 #endif
                /*
index 59bcb96ac3692446989501f363301daa81674d5b..f57609275449e704892101a514ecc40ee3021a3c 100644 (file)
@@ -166,3 +166,14 @@ void free_xenballooned_pages(int nr_pages, struct page **pages)
        *pages = NULL;
 }
 EXPORT_SYMBOL_GPL(free_xenballooned_pages);
+
+/* In the hypervisor.S file. */
+EXPORT_SYMBOL_GPL(HYPERVISOR_event_channel_op);
+EXPORT_SYMBOL_GPL(HYPERVISOR_grant_table_op);
+EXPORT_SYMBOL_GPL(HYPERVISOR_xen_version);
+EXPORT_SYMBOL_GPL(HYPERVISOR_console_io);
+EXPORT_SYMBOL_GPL(HYPERVISOR_sched_op);
+EXPORT_SYMBOL_GPL(HYPERVISOR_hvm_op);
+EXPORT_SYMBOL_GPL(HYPERVISOR_memory_op);
+EXPORT_SYMBOL_GPL(HYPERVISOR_physdev_op);
+EXPORT_SYMBOL_GPL(privcmd_call);
index dbd1330c01966c20667853b6d9de97754b869d91..859a9bb002d54875e5089a940442d5015a9fe1a4 100644 (file)
@@ -33,7 +33,7 @@
 #include <xen/page.h>
 #include <xen/grant_table.h>
 
-int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes,
+int arch_gnttab_map_shared(xen_pfn_t *frames, unsigned long nr_gframes,
                           unsigned long max_nr_gframes,
                           void **__shared)
 {
index 074f5ed101b9d17bf49c2a0cd13b078408fcb64c..71f723984cbd94eced133e49bc7fd0db8dbdf92b 100644 (file)
 
 #include <linux/linkage.h>
 #include <asm/assembler.h>
+#include <asm/opcodes-virt.h>
 #include <xen/interface/xen.h>
 
 
-/* HVC 0xEA1 */
-#ifdef CONFIG_THUMB2_KERNEL
-#define xen_hvc .word 0xf7e08ea1
-#else
-#define xen_hvc .word 0xe140ea71
-#endif
+#define XEN_IMM 0xEA1
 
 #define HYPERCALL_SIMPLE(hypercall)            \
 ENTRY(HYPERVISOR_##hypercall)                  \
        mov r12, #__HYPERVISOR_##hypercall;     \
-       xen_hvc;                                                        \
+       __HVC(XEN_IMM);                                         \
        mov pc, lr;                                                     \
 ENDPROC(HYPERVISOR_##hypercall)
 
@@ -76,7 +72,7 @@ ENTRY(HYPERVISOR_##hypercall)                 \
        stmdb sp!, {r4}                                         \
        ldr r4, [sp, #4]                                        \
        mov r12, #__HYPERVISOR_##hypercall;     \
-       xen_hvc                                                         \
+       __HVC(XEN_IMM);                                         \
        ldm sp!, {r4}                                           \
        mov pc, lr                                                      \
 ENDPROC(HYPERVISOR_##hypercall)
@@ -100,7 +96,7 @@ ENTRY(privcmd_call)
        mov r2, r3
        ldr r3, [sp, #8]
        ldr r4, [sp, #4]
-       xen_hvc
+       __HVC(XEN_IMM)
        ldm sp!, {r4}
        mov pc, lr
 ENDPROC(privcmd_call);
index ef54a59a9e89cba5e4920b8733aeea067d19d9e5..15ac18a56c93b78a2d3972e7196ce89875c2135c 100644 (file)
@@ -1,6 +1,7 @@
 config ARM64
        def_bool y
        select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
+       select ARCH_WANT_COMPAT_IPC_PARSE_VERSION
        select GENERIC_CLOCKEVENTS
        select GENERIC_HARDIRQS_NO_DEPRECATED
        select GENERIC_IOMAP
index cf284649dfcbff5c84501ad539f4bc880e6766a7..07fea290d7c15b211e881856bb48d943a80c337a 100644 (file)
 #include <asm/user.h>
 
 typedef unsigned long elf_greg_t;
-typedef unsigned long elf_freg_t[3];
 
 #define ELF_NGREG (sizeof (struct pt_regs) / sizeof(elf_greg_t))
 typedef elf_greg_t elf_gregset_t[ELF_NGREG];
-
-typedef struct user_fp elf_fpregset_t;
+typedef struct user_fpsimd_state elf_fpregset_t;
 
 #define EM_AARCH64             183
 
@@ -87,7 +85,6 @@ typedef struct user_fp elf_fpregset_t;
 #define R_AARCH64_MOVW_PREL_G2_NC      292
 #define R_AARCH64_MOVW_PREL_G3         293
 
-
 /*
  * These are used to set parameters in the core dumps.
  */
index b42fab9f62a955f0e5ec864b186520103ebda60c..c43b4ac13008ffec8f0b39101e5cfd77e43fd3b5 100644 (file)
@@ -25,9 +25,8 @@
  *  - FPSR and FPCR
  *  - 32 128-bit data registers
  *
- * Note that user_fp forms a prefix of this structure, which is relied
- * upon in the ptrace FP/SIMD accessors. struct user_fpsimd_state must
- * form a prefix of struct fpsimd_state.
+ * Note that user_fpsimd forms a prefix of this structure, which is
+ * relied upon in the ptrace FP/SIMD accessors.
  */
 struct fpsimd_state {
        union {
index 74a2a7d304a959159e3cf69c94f0ede77a8232c2..d2f05a608274534a08180fc3866658a225bb560c 100644 (file)
@@ -114,7 +114,7 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
  *  I/O port access primitives.
  */
 #define IO_SPACE_LIMIT         0xffff
-#define PCI_IOBASE             ((void __iomem *)0xffffffbbfffe0000UL)
+#define PCI_IOBASE             ((void __iomem *)(MODULES_VADDR - SZ_2M))
 
 static inline u8 inb(unsigned long addr)
 {
@@ -222,12 +222,12 @@ extern void __iomem *__ioremap(phys_addr_t phys_addr, size_t size, pgprot_t prot
 extern void __iounmap(volatile void __iomem *addr);
 
 #define PROT_DEFAULT           (PTE_TYPE_PAGE | PTE_AF | PTE_DIRTY)
-#define PROT_DEVICE_nGnRE      (PROT_DEFAULT | PTE_XN | PTE_ATTRINDX(MT_DEVICE_nGnRE))
+#define PROT_DEVICE_nGnRE      (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_ATTRINDX(MT_DEVICE_nGnRE))
 #define PROT_NORMAL_NC         (PROT_DEFAULT | PTE_ATTRINDX(MT_NORMAL_NC))
 
-#define ioremap(addr, size)            __ioremap((addr), (size), PROT_DEVICE_nGnRE)
-#define ioremap_nocache(addr, size)    __ioremap((addr), (size), PROT_DEVICE_nGnRE)
-#define ioremap_wc(addr, size)         __ioremap((addr), (size), PROT_NORMAL_NC)
+#define ioremap(addr, size)            __ioremap((addr), (size), __pgprot(PROT_DEVICE_nGnRE))
+#define ioremap_nocache(addr, size)    __ioremap((addr), (size), __pgprot(PROT_DEVICE_nGnRE))
+#define ioremap_wc(addr, size)         __ioremap((addr), (size), __pgprot(PROT_NORMAL_NC))
 #define iounmap                                __iounmap
 
 #define ARCH_HAS_IOREMAP_WC
index 0f3b4581d9251ab17b4750eb8501c8d77cbee428..75fd13d289b93193f261c89fa83fb6973738f6f2 100644 (file)
@@ -38,7 +38,8 @@
 #define PMD_SECT_S             (_AT(pmdval_t, 3) << 8)
 #define PMD_SECT_AF            (_AT(pmdval_t, 1) << 10)
 #define PMD_SECT_NG            (_AT(pmdval_t, 1) << 11)
-#define PMD_SECT_XN            (_AT(pmdval_t, 1) << 54)
+#define PMD_SECT_PXN           (_AT(pmdval_t, 1) << 53)
+#define PMD_SECT_UXN           (_AT(pmdval_t, 1) << 54)
 
 /*
  * AttrIndx[2:0] encoding (mapping attributes defined in the MAIR* registers).
@@ -57,7 +58,8 @@
 #define PTE_SHARED             (_AT(pteval_t, 3) << 8)         /* SH[1:0], inner shareable */
 #define PTE_AF                 (_AT(pteval_t, 1) << 10)        /* Access Flag */
 #define PTE_NG                 (_AT(pteval_t, 1) << 11)        /* nG */
-#define PTE_XN                 (_AT(pteval_t, 1) << 54)        /* XN */
+#define PTE_PXN                        (_AT(pteval_t, 1) << 53)        /* Privileged XN */
+#define PTE_UXN                        (_AT(pteval_t, 1) << 54)        /* User XN */
 
 /*
  * AttrIndx[2:0] encoding (mapping attributes defined in the MAIR* registers).
index 8960239be722893a8094ceef323da22ff26eef63..14aba2db6776d099935c76e95bd4797f3a707376 100644 (file)
@@ -62,23 +62,23 @@ extern pgprot_t pgprot_default;
 
 #define _MOD_PROT(p, b)        __pgprot(pgprot_val(p) | (b))
 
-#define PAGE_NONE              _MOD_PROT(pgprot_default, PTE_NG | PTE_XN | PTE_RDONLY)
-#define PAGE_SHARED            _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_XN)
-#define PAGE_SHARED_EXEC       _MOD_PROT(pgprot_default, PTE_USER | PTE_NG)
-#define PAGE_COPY              _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_XN | PTE_RDONLY)
-#define PAGE_COPY_EXEC         _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_RDONLY)
-#define PAGE_READONLY          _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_XN | PTE_RDONLY)
-#define PAGE_READONLY_EXEC     _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_RDONLY)
-#define PAGE_KERNEL            _MOD_PROT(pgprot_default, PTE_XN | PTE_DIRTY)
-#define PAGE_KERNEL_EXEC       _MOD_PROT(pgprot_default, PTE_DIRTY)
-
-#define __PAGE_NONE            __pgprot(_PAGE_DEFAULT | PTE_NG | PTE_XN | PTE_RDONLY)
-#define __PAGE_SHARED          __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_XN)
-#define __PAGE_SHARED_EXEC     __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG)
-#define __PAGE_COPY            __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_XN | PTE_RDONLY)
-#define __PAGE_COPY_EXEC       __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_RDONLY)
-#define __PAGE_READONLY                __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_XN | PTE_RDONLY)
-#define __PAGE_READONLY_EXEC   __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_RDONLY)
+#define PAGE_NONE              _MOD_PROT(pgprot_default, PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY)
+#define PAGE_SHARED            _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_UXN)
+#define PAGE_SHARED_EXEC       _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN)
+#define PAGE_COPY              _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY)
+#define PAGE_COPY_EXEC         _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_RDONLY)
+#define PAGE_READONLY          _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY)
+#define PAGE_READONLY_EXEC     _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_RDONLY)
+#define PAGE_KERNEL            _MOD_PROT(pgprot_default, PTE_PXN | PTE_UXN | PTE_DIRTY)
+#define PAGE_KERNEL_EXEC       _MOD_PROT(pgprot_default, PTE_UXN | PTE_DIRTY)
+
+#define __PAGE_NONE            __pgprot(_PAGE_DEFAULT | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY)
+#define __PAGE_SHARED          __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN)
+#define __PAGE_SHARED_EXEC     __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN)
+#define __PAGE_COPY            __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY)
+#define __PAGE_COPY_EXEC       __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_RDONLY)
+#define __PAGE_READONLY                __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY)
+#define __PAGE_READONLY_EXEC   __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_RDONLY)
 
 #endif /* __ASSEMBLY__ */
 
@@ -130,10 +130,10 @@ extern struct page *empty_zero_page;
 #define pte_young(pte)         (pte_val(pte) & PTE_AF)
 #define pte_special(pte)       (pte_val(pte) & PTE_SPECIAL)
 #define pte_write(pte)         (!(pte_val(pte) & PTE_RDONLY))
-#define pte_exec(pte)          (!(pte_val(pte) & PTE_XN))
+#define pte_exec(pte)          (!(pte_val(pte) & PTE_UXN))
 
 #define pte_present_exec_user(pte) \
-       ((pte_val(pte) & (PTE_VALID | PTE_USER | PTE_XN)) == \
+       ((pte_val(pte) & (PTE_VALID | PTE_USER | PTE_UXN)) == \
         (PTE_VALID | PTE_USER))
 
 #define PTE_BIT_FUNC(fn,op) \
@@ -262,7 +262,7 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr)
 
 static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 {
-       const pteval_t mask = PTE_USER | PTE_XN | PTE_RDONLY;
+       const pteval_t mask = PTE_USER | PTE_PXN | PTE_UXN | PTE_RDONLY;
        pte_val(pte) = (pte_val(pte) & ~mask) | (pgprot_val(newprot) & mask);
        return pte;
 }
index 5d810044fedabf7fb897ffc603c3f8a3aae271db..77f696c143396d9bf93521d6444bf12dd4b82c01 100644 (file)
@@ -43,6 +43,8 @@
 #else
 #define STACK_TOP              STACK_TOP_MAX
 #endif /* CONFIG_COMPAT */
+
+#define ARCH_LOW_ADDRESS_LIMIT PHYS_MASK
 #endif /* __KERNEL__ */
 
 struct debug_info {
index 63f853f8b718026a69342ce8bb46ff6fd948066e..68aff2816e8605113945a66e60e1dd2f5b5c2ade 100644 (file)
@@ -14,7 +14,6 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 #ifdef CONFIG_COMPAT
-#define __ARCH_WANT_COMPAT_IPC_PARSE_VERSION
 #define __ARCH_WANT_COMPAT_STAT64
 #define __ARCH_WANT_SYS_GETHOSTNAME
 #define __ARCH_WANT_SYS_PAUSE
index ecbf2d81ec5ce483416bf57e2030bff2431c1972..c76c7241125b66d8ee762b13bdae3f73328f8fe7 100644 (file)
@@ -613,17 +613,11 @@ enum armv8_pmuv3_perf_types {
        ARMV8_PMUV3_PERFCTR_BUS_ACCESS                          = 0x19,
        ARMV8_PMUV3_PERFCTR_MEM_ERROR                           = 0x1A,
        ARMV8_PMUV3_PERFCTR_BUS_CYCLES                          = 0x1D,
-
-       /*
-        * This isn't an architected event.
-        * We detect this event number and use the cycle counter instead.
-        */
-       ARMV8_PMUV3_PERFCTR_CPU_CYCLES                          = 0xFF,
 };
 
 /* PMUv3 HW events mapping. */
 static const unsigned armv8_pmuv3_perf_map[PERF_COUNT_HW_MAX] = {
-       [PERF_COUNT_HW_CPU_CYCLES]              = ARMV8_PMUV3_PERFCTR_CPU_CYCLES,
+       [PERF_COUNT_HW_CPU_CYCLES]              = ARMV8_PMUV3_PERFCTR_CLOCK_CYCLES,
        [PERF_COUNT_HW_INSTRUCTIONS]            = ARMV8_PMUV3_PERFCTR_INSTR_EXECUTED,
        [PERF_COUNT_HW_CACHE_REFERENCES]        = ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS,
        [PERF_COUNT_HW_CACHE_MISSES]            = ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL,
@@ -1106,7 +1100,7 @@ static int armv8pmu_get_event_idx(struct pmu_hw_events *cpuc,
        unsigned long evtype = event->config_base & ARMV8_EVTYPE_EVENT;
 
        /* Always place a cycle counter into the cycle counter. */
-       if (evtype == ARMV8_PMUV3_PERFCTR_CPU_CYCLES) {
+       if (evtype == ARMV8_PMUV3_PERFCTR_CLOCK_CYCLES) {
                if (test_and_set_bit(ARMV8_IDX_CYCLE_COUNTER, cpuc->used_mask))
                        return -EAGAIN;
 
index f22965ea1cfcd4bd2a5c6a276ed8675c49de19e4..e04cebdbb47fc5a82ae6042169b098b8fae13d54 100644 (file)
@@ -309,24 +309,6 @@ struct task_struct *__switch_to(struct task_struct *prev,
        return last;
 }
 
-/*
- * Fill in the task's elfregs structure for a core dump.
- */
-int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs)
-{
-       elf_core_copy_regs(elfregs, task_pt_regs(t));
-       return 1;
-}
-
-/*
- * fill in the fpe structure for a core dump...
- */
-int dump_fpu (struct pt_regs *regs, struct user_fp *fp)
-{
-       return 0;
-}
-EXPORT_SYMBOL(dump_fpu);
-
 /*
  * Shuffle the argument into the correct register before calling the
  * thread function.  x1 is the thread argument, x2 is the pointer to
index 226b6bf6e9c296ffbc0c94599b17222d69cae15d..538300f2273d82420973a0697a6d145aef60366a 100644 (file)
@@ -211,8 +211,7 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
         * before we continue.
         */
        set_cpu_online(cpu, true);
-       while (!cpu_active(cpu))
-               cpu_relax();
+       complete(&cpu_running);
 
        /*
         * OK, it's off to the idle thread for us
index efbf7df05d3f6e2ffe4b6105b8cdb0e49a97ab1b..4cd28931dba95da0711a4aeabed694613febce5f 100644 (file)
@@ -80,7 +80,7 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max)
 #ifdef CONFIG_ZONE_DMA32
        /* 4GB maximum for 32-bit only capable devices */
        max_dma32 = min(max, MAX_DMA32_PFN);
-       zone_size[ZONE_DMA32] = max_dma32 - min;
+       zone_size[ZONE_DMA32] = max(min, max_dma32) - min;
 #endif
        zone_size[ZONE_NORMAL] = max - max_dma32;
 
index b7412504f08a2c91635c6f75da624a59b6a6a953..df2eb4bd9fa2abbaa06c6978537fcabc88c22cf7 100644 (file)
@@ -13,6 +13,7 @@ config FRV
        select GENERIC_CPU_DEVICES
        select ARCH_WANT_IPC_PARSE_VERSION
        select GENERIC_KERNEL_THREAD
+       select GENERIC_KERNEL_EXECVE
 
 config ZONE_DMA
        bool
index 6ae3254da01976b6fdaa374f588c3c58a081058c..636d5bbcd53f31ca5cbbb96ca9f3e29f501fdfff 100644 (file)
@@ -17,6 +17,8 @@ PARAMS_PHYS    = 0x0207c000
 INITRD_PHYS     = 0x02180000
 INITRD_VIRT     = 0x02180000
 
+OBJCOPYFLAGS   :=-O binary -R .note -R .note.gnu.build-id -R .comment
+
 #
 # If you don't define ZRELADDR above,
 # then it defaults to ZTEXTADDR
@@ -32,18 +34,18 @@ Image: $(obj)/Image
 targets: $(obj)/Image
 
 $(obj)/Image: vmlinux FORCE
-       $(OBJCOPY) -O binary -R .note -R .comment -S vmlinux $@
+       $(OBJCOPY) $(OBJCOPYFLAGS) -S vmlinux $@
 
 #$(obj)/Image: $(CONFIGURE) $(SYSTEM)
-#      $(OBJCOPY) -O binary -R .note -R .comment -g -S $(SYSTEM) $@
+#      $(OBJCOPY) $(OBJCOPYFLAGS) -g -S $(SYSTEM) $@
 
 bzImage: zImage
 
 zImage:        $(CONFIGURE) compressed/$(LINUX)
-       $(OBJCOPY) -O binary -R .note -R .comment -S compressed/$(LINUX) $@
+       $(OBJCOPY) $(OBJCOPYFLAGS) -S compressed/$(LINUX) $@
 
 bootpImage: bootp/bootp
-       $(OBJCOPY) -O binary -R .note -R .comment -S bootp/bootp $@
+       $(OBJCOPY) $(OBJCOPYFLAGS) -S bootp/bootp $@
 
 compressed/$(LINUX): $(LINUX) dep
        @$(MAKE) -C compressed $(LINUX)
index 266a5b25a0c1698347715c91fd45b7e95b8eb864..2358634caccaa6b50a8cad83fb0601e1350e71d0 100644 (file)
@@ -30,7 +30,6 @@
 #define __ARCH_WANT_SYS_RT_SIGACTION
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
 #define __ARCH_WANT_SYS_EXECVE
-#define __ARCH_WANT_KERNEL_EXECVE
 
 /*
  * "Conditional" syscalls
index ee0beb354e4df38e0c067410e8f9643deec2856f..dfcd263c05176ea6cdbf3c169070a93fe79b8f5b 100644 (file)
@@ -869,11 +869,6 @@ ret_from_kernel_thread:
        call            schedule_tail
        calll.p         @(gr21,gr0)
        or              gr20,gr20,gr8
-       bra             sys_exit
-
-       .globl          ret_from_kernel_execve
-ret_from_kernel_execve:
-       ori             gr28,0,sp
        bra             __syscall_exit
 
 ###################################################################################################
@@ -1080,27 +1075,10 @@ __entry_return_from_kernel_interrupt:
        subicc          gr5,#0,gr0,icc0
        beq             icc0,#0,__entry_return_direct
 
-__entry_preempt_need_resched:
-       ldi             @(gr15,#TI_FLAGS),gr4
-       andicc          gr4,#_TIF_NEED_RESCHED,gr0,icc0
-       beq             icc0,#1,__entry_return_direct
-
-       setlos          #PREEMPT_ACTIVE,gr5
-       sti             gr5,@(gr15,#TI_FLAGS)
-
-       andi            gr23,#~PSR_PIL,gr23
-       movgs           gr23,psr
-
-       call            schedule
-       sti             gr0,@(gr15,#TI_PRE_COUNT)
-
-       movsg           psr,gr23
-       ori             gr23,#PSR_PIL_14,gr23
-       movgs           gr23,psr
-       bra             __entry_preempt_need_resched
-#else
-       bra             __entry_return_direct
+       subcc           gr0,gr0,gr0,icc2                /* set Z and clear C */
+       call            preempt_schedule_irq
 #endif
+       bra             __entry_return_direct
 
 
 ###############################################################################
index e1e3aa196aa4c25adcb33ed09fe1296b4be8e69d..7e33215f1d8fabfd28a1aa5c5144a8e73f621a90 100644 (file)
@@ -181,6 +181,9 @@ int copy_thread(unsigned long clone_flags,
        childregs = (struct pt_regs *)
                (task_stack_page(p) + THREAD_SIZE - FRV_FRAME0_SIZE);
 
+       /* set up the userspace frame (the only place that the USP is stored) */
+       *childregs = *__kernel_frame0_ptr;
+
        p->set_child_tid = p->clear_child_tid = NULL;
 
        p->thread.frame  = childregs;
@@ -191,10 +194,8 @@ int copy_thread(unsigned long clone_flags,
        p->thread.frame0 = childregs;
 
        if (unlikely(!regs)) {
-               memset(childregs, 0, sizeof(struct pt_regs));
                childregs->gr9 = usp; /* function */
                childregs->gr8 = arg;
-               childregs->psr = PSR_S;
                p->thread.pc = (unsigned long) ret_from_kernel_thread;
                save_user_regs(p->thread.user);
                return 0;
index e47857f889b6d2a18dcf839249bae5f7af66f334..b99c2a7cc7a41f6a0398c4a34715749d2a935afc 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <linux/types.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 #include <linux/dma-mapping.h>
 #include <linux/list.h>
 #include <linux/pci.h>
index c6350283649d47ad3bfa50a8ef61f8f582896857..05887a1d80e5cc3755e995637e008fcf753deb94 100644 (file)
@@ -2,7 +2,8 @@
 #define __ARCH_H8300_CACHE_H
 
 /* bytes per L1 cache line */
-#define        L1_CACHE_BYTES  4
+#define        L1_CACHE_SHIFT  2
+#define        L1_CACHE_BYTES  (1 << L1_CACHE_SHIFT)
 
 /* m68k-elf-gcc  2.95.2 doesn't like these */
 
index 4a159da23633dbf359c9886513958ce49e842ce7..dd02f09b6eda6e2b41f1dd643a6ff550625a15e0 100644 (file)
@@ -1,3 +1,4 @@
 
 generic-y += clkdev.h
 generic-y += exec.h
+generic-y += kvm_para.h
diff --git a/arch/ia64/include/asm/kvm_para.h b/arch/ia64/include/asm/kvm_para.h
deleted file mode 100644 (file)
index 47c00f9..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2007 Xiantao Zhang <xiantao.zhang@intel.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- */
-#ifndef __IA64_KVM_PARA_H
-#define __IA64_KVM_PARA_H
-
-#include <uapi/asm/kvm_para.h>
-
-
-static inline unsigned int kvm_arch_para_features(void)
-{
-       return 0;
-}
-
-static inline bool kvm_check_and_clear_guest_paused(void)
-{
-       return false;
-}
-
-#endif
index acd5b68e887128e90f8e59530d77dc3985bf1e97..082e383c1b6f22dc8370fdac789489acbb04ffba 100644 (file)
@@ -637,7 +637,6 @@ mem_init (void)
 
        high_memory = __va(max_low_pfn * PAGE_SIZE);
 
-       reset_zone_present_pages();
        for_each_online_pgdat(pgdat)
                if (pgdat->bdata->node_bootmem_map)
                        totalram_pages += free_all_bootmem_node(pgdat);
index ecb540810ab3ace200ae66368d700d97b4abf0d2..88fa3ac86fae9af988331112cba87ff711eb3555 100644 (file)
@@ -1,5 +1,3 @@
-include include/asm-generic/Kbuild.asm
-header-y += cachectl.h
 
 generic-y += bitsperlong.h
 generic-y += clkdev.h
diff --git a/arch/m68k/include/asm/a.out.h b/arch/m68k/include/asm/a.out.h
deleted file mode 100644 (file)
index 3885fe4..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef __M68K_A_OUT_H__
-#define __M68K_A_OUT_H__
-
-struct exec
-{
-  unsigned long a_info;                /* Use macros N_MAGIC, etc for access */
-  unsigned a_text;             /* length of text, in bytes */
-  unsigned a_data;             /* length of data, in bytes */
-  unsigned a_bss;              /* length of uninitialized data area for file, in bytes */
-  unsigned a_syms;             /* length of symbol table data in file, in bytes */
-  unsigned a_entry;            /* start address */
-  unsigned a_trsize;           /* length of relocation info for text, in bytes */
-  unsigned a_drsize;           /* length of relocation info for data, in bytes */
-};
-
-#define N_TRSIZE(a)    ((a).a_trsize)
-#define N_DRSIZE(a)    ((a).a_drsize)
-#define N_SYMSIZE(a)   ((a).a_syms)
-
-#endif /* __M68K_A_OUT_H__ */
diff --git a/arch/m68k/include/asm/auxvec.h b/arch/m68k/include/asm/auxvec.h
deleted file mode 100644 (file)
index 844d6d5..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-#ifndef __ASMm68k_AUXVEC_H
-#define __ASMm68k_AUXVEC_H
-
-#endif
diff --git a/arch/m68k/include/asm/byteorder.h b/arch/m68k/include/asm/byteorder.h
deleted file mode 100644 (file)
index 31b260a..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _M68K_BYTEORDER_H
-#define _M68K_BYTEORDER_H
-
-#include <linux/byteorder/big_endian.h>
-
-#endif /* _M68K_BYTEORDER_H */
diff --git a/arch/m68k/include/asm/cachectl.h b/arch/m68k/include/asm/cachectl.h
deleted file mode 100644 (file)
index 525978e..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef _M68K_CACHECTL_H
-#define _M68K_CACHECTL_H
-
-/* Definitions for the cacheflush system call.  */
-
-#define FLUSH_SCOPE_LINE    1  /* Flush a cache line */
-#define FLUSH_SCOPE_PAGE    2  /* Flush a page */
-#define FLUSH_SCOPE_ALL     3  /* Flush the whole cache -- superuser only */
-
-#define FLUSH_CACHE_DATA    1  /* Writeback and flush data cache */
-#define FLUSH_CACHE_INSN    2  /* Flush instruction cache */
-#define FLUSH_CACHE_BOTH    3  /* Flush both caches */
-
-#endif /* _M68K_CACHECTL_H */
diff --git a/arch/m68k/include/asm/fcntl.h b/arch/m68k/include/asm/fcntl.h
deleted file mode 100644 (file)
index 1c369b2..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef _M68K_FCNTL_H
-#define _M68K_FCNTL_H
-
-#define O_DIRECTORY    040000  /* must be a directory */
-#define O_NOFOLLOW     0100000 /* don't follow links */
-#define O_DIRECT       0200000 /* direct disk access hint - currently ignored */
-#define O_LARGEFILE    0400000
-
-#include <asm-generic/fcntl.h>
-
-#endif /* _M68K_FCNTL_H */
diff --git a/arch/m68k/include/asm/ioctls.h b/arch/m68k/include/asm/ioctls.h
deleted file mode 100644 (file)
index 1332bb4..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef __ARCH_M68K_IOCTLS_H__
-#define __ARCH_M68K_IOCTLS_H__
-
-#define FIOQSIZE       0x545E
-
-#include <asm-generic/ioctls.h>
-
-#endif /* __ARCH_M68K_IOCTLS_H__ */
diff --git a/arch/m68k/include/asm/msgbuf.h b/arch/m68k/include/asm/msgbuf.h
deleted file mode 100644 (file)
index 243cb79..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef _M68K_MSGBUF_H
-#define _M68K_MSGBUF_H
-
-/*
- * The msqid64_ds structure for m68k architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
- * - 2 miscellaneous 32-bit values
- */
-
-struct msqid64_ds {
-       struct ipc64_perm msg_perm;
-       __kernel_time_t msg_stime;      /* last msgsnd time */
-       unsigned long   __unused1;
-       __kernel_time_t msg_rtime;      /* last msgrcv time */
-       unsigned long   __unused2;
-       __kernel_time_t msg_ctime;      /* last change time */
-       unsigned long   __unused3;
-       unsigned long  msg_cbytes;      /* current number of bytes on queue */
-       unsigned long  msg_qnum;        /* number of messages in queue */
-       unsigned long  msg_qbytes;      /* max number of bytes on queue */
-       __kernel_pid_t msg_lspid;       /* pid of last msgsnd */
-       __kernel_pid_t msg_lrpid;       /* last receive pid */
-       unsigned long  __unused4;
-       unsigned long  __unused5;
-};
-
-#endif /* _M68K_MSGBUF_H */
diff --git a/arch/m68k/include/asm/param.h b/arch/m68k/include/asm/param.h
deleted file mode 100644 (file)
index 36265cc..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _M68K_PARAM_H
-#define _M68K_PARAM_H
-
-#ifdef __uClinux__
-#define EXEC_PAGESIZE  4096
-#else
-#define EXEC_PAGESIZE  8192
-#endif
-
-#include <asm-generic/param.h>
-
-#endif /* _M68K_PARAM_H */
diff --git a/arch/m68k/include/asm/poll.h b/arch/m68k/include/asm/poll.h
deleted file mode 100644 (file)
index f080fcd..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef __m68k_POLL_H
-#define __m68k_POLL_H
-
-#define POLLWRNORM     POLLOUT
-#define POLLWRBAND     256
-
-#include <asm-generic/poll.h>
-
-#endif
diff --git a/arch/m68k/include/asm/posix_types.h b/arch/m68k/include/asm/posix_types.h
deleted file mode 100644 (file)
index cf4dbf7..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-#ifndef __ARCH_M68K_POSIX_TYPES_H
-#define __ARCH_M68K_POSIX_TYPES_H
-
-/*
- * This file is generally used by user-level software, so you need to
- * be a little careful about namespace pollution etc.  Also, we cannot
- * assume GCC is being used.
- */
-
-typedef unsigned short __kernel_mode_t;
-#define __kernel_mode_t __kernel_mode_t
-
-typedef unsigned short __kernel_ipc_pid_t;
-#define __kernel_ipc_pid_t __kernel_ipc_pid_t
-
-typedef unsigned short __kernel_uid_t;
-typedef unsigned short __kernel_gid_t;
-#define __kernel_uid_t __kernel_uid_t
-
-typedef unsigned short __kernel_old_dev_t;
-#define __kernel_old_dev_t __kernel_old_dev_t
-
-#include <asm-generic/posix_types.h>
-
-#endif
index 5e08b597f012192e8a5f8cd4cc4d0a20690b485d..0f717045bddef4094584fe9c5be624e9ee2d4927 100644 (file)
@@ -1,82 +1,10 @@
 #ifndef _M68K_PTRACE_H
 #define _M68K_PTRACE_H
 
-#define PT_D1     0
-#define PT_D2     1
-#define PT_D3     2
-#define PT_D4     3
-#define PT_D5     4
-#define PT_D6     5
-#define PT_D7     6
-#define PT_A0     7
-#define PT_A1     8
-#define PT_A2     9
-#define PT_A3     10
-#define PT_A4     11
-#define PT_A5     12
-#define PT_A6     13
-#define PT_D0     14
-#define PT_USP    15
-#define PT_ORIG_D0 16
-#define PT_SR     17
-#define PT_PC     18
+#include <uapi/asm/ptrace.h>
 
 #ifndef __ASSEMBLY__
 
-/* this struct defines the way the registers are stored on the
-   stack during a system call. */
-
-struct pt_regs {
-  long     d1;
-  long     d2;
-  long     d3;
-  long     d4;
-  long     d5;
-  long     a0;
-  long     a1;
-  long     a2;
-  long     d0;
-  long     orig_d0;
-  long     stkadj;
-#ifdef CONFIG_COLDFIRE
-  unsigned format :  4; /* frame format specifier */
-  unsigned vector : 12; /* vector offset */
-  unsigned short sr;
-  unsigned long  pc;
-#else
-  unsigned short sr;
-  unsigned long  pc;
-  unsigned format :  4; /* frame format specifier */
-  unsigned vector : 12; /* vector offset */
-#endif
-};
-
-/*
- * This is the extended stack used by signal handlers and the context
- * switcher: it's pushed after the normal "struct pt_regs".
- */
-struct switch_stack {
-       unsigned long  d6;
-       unsigned long  d7;
-       unsigned long  a3;
-       unsigned long  a4;
-       unsigned long  a5;
-       unsigned long  a6;
-       unsigned long  retpc;
-};
-
-/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
-#define PTRACE_GETREGS            12
-#define PTRACE_SETREGS            13
-#define PTRACE_GETFPREGS          14
-#define PTRACE_SETFPREGS          15
-
-#define PTRACE_GET_THREAD_AREA    25
-
-#define PTRACE_SINGLEBLOCK     33      /* resume execution until next branch */
-
-#ifdef __KERNEL__
-
 #ifndef PS_S
 #define PS_S  (0x2000)
 #define PS_M  (0x1000)
@@ -94,6 +22,5 @@ struct switch_stack {
 #define arch_has_block_step()  (1)
 #endif
 
-#endif /* __KERNEL__ */
 #endif /* __ASSEMBLY__ */
 #endif /* _M68K_PTRACE_H */
diff --git a/arch/m68k/include/asm/sembuf.h b/arch/m68k/include/asm/sembuf.h
deleted file mode 100644 (file)
index 2308052..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-#ifndef _M68K_SEMBUF_H
-#define _M68K_SEMBUF_H
-
-/*
- * The semid64_ds structure for m68k architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
- * - 2 miscellaneous 32-bit values
- */
-
-struct semid64_ds {
-       struct ipc64_perm sem_perm;             /* permissions .. see ipc.h */
-       __kernel_time_t sem_otime;              /* last semop time */
-       unsigned long   __unused1;
-       __kernel_time_t sem_ctime;              /* last change time */
-       unsigned long   __unused2;
-       unsigned long   sem_nsems;              /* no. of semaphores in array */
-       unsigned long   __unused3;
-       unsigned long   __unused4;
-};
-
-#endif /* _M68K_SEMBUF_H */
index 00c2c5397d37ee787eaeac0df751e220c3cefa26..65e78a2dad64a9840fdb96bdc898e8b848f52331 100644 (file)
 **   Redesign of the boot information structure; moved boot information
 **   structure to bootinfo.h
 */
-
 #ifndef _M68K_SETUP_H
 #define _M68K_SETUP_H
 
+#include <uapi/asm/setup.h>
 
 
-    /*
-     *  Linux/m68k Architectures
-     */
-
-#define MACH_AMIGA    1
-#define MACH_ATARI    2
-#define MACH_MAC      3
-#define MACH_APOLLO   4
-#define MACH_SUN3     5
-#define MACH_MVME147  6
-#define MACH_MVME16x  7
-#define MACH_BVME6000 8
-#define MACH_HP300    9
-#define MACH_Q40     10
-#define MACH_SUN3X   11
-#define MACH_M54XX   12
-
-#define COMMAND_LINE_SIZE 256
-
-#ifdef __KERNEL__
-
 #define CL_SIZE COMMAND_LINE_SIZE
 
 #ifndef __ASSEMBLY__
@@ -194,63 +173,6 @@ extern unsigned long m68k_machtype;
 #  define MACH_TYPE (m68k_machtype)
 #endif
 
-#endif /* __KERNEL__ */
-
-
-    /*
-     *  CPU, FPU and MMU types
-     *
-     *  Note: we may rely on the following equalities:
-     *
-     *      CPU_68020 == MMU_68851
-     *      CPU_68030 == MMU_68030
-     *      CPU_68040 == FPU_68040 == MMU_68040
-     *      CPU_68060 == FPU_68060 == MMU_68060
-     */
-
-#define CPUB_68020     0
-#define CPUB_68030     1
-#define CPUB_68040     2
-#define CPUB_68060     3
-#define CPUB_COLDFIRE  4
-
-#define CPU_68020      (1<<CPUB_68020)
-#define CPU_68030      (1<<CPUB_68030)
-#define CPU_68040      (1<<CPUB_68040)
-#define CPU_68060      (1<<CPUB_68060)
-#define CPU_COLDFIRE   (1<<CPUB_COLDFIRE)
-
-#define FPUB_68881     0
-#define FPUB_68882     1
-#define FPUB_68040     2                       /* Internal FPU */
-#define FPUB_68060     3                       /* Internal FPU */
-#define FPUB_SUNFPA    4                       /* Sun-3 FPA */
-#define FPUB_COLDFIRE  5                       /* ColdFire FPU */
-
-#define FPU_68881      (1<<FPUB_68881)
-#define FPU_68882      (1<<FPUB_68882)
-#define FPU_68040      (1<<FPUB_68040)
-#define FPU_68060      (1<<FPUB_68060)
-#define FPU_SUNFPA     (1<<FPUB_SUNFPA)
-#define FPU_COLDFIRE   (1<<FPUB_COLDFIRE)
-
-#define MMUB_68851     0
-#define MMUB_68030     1                       /* Internal MMU */
-#define MMUB_68040     2                       /* Internal MMU */
-#define MMUB_68060     3                       /* Internal MMU */
-#define MMUB_APOLLO    4                       /* Custom Apollo */
-#define MMUB_SUN3      5                       /* Custom Sun-3 */
-#define MMUB_COLDFIRE  6                       /* Internal MMU */
-
-#define MMU_68851      (1<<MMUB_68851)
-#define MMU_68030      (1<<MMUB_68030)
-#define MMU_68040      (1<<MMUB_68040)
-#define MMU_68060      (1<<MMUB_68060)
-#define MMU_SUN3       (1<<MMUB_SUN3)
-#define MMU_APOLLO     (1<<MMUB_APOLLO)
-#define MMU_COLDFIRE   (1<<MMUB_COLDFIRE)
-
-#ifdef __KERNEL__
 
 #ifndef __ASSEMBLY__
 extern unsigned long m68k_cputype;
@@ -385,6 +307,4 @@ extern int m68k_realnum_memory;             /* real # of memory blocks found */
 extern struct mem_info m68k_memory[NUM_MEMINFO];/* memory description */
 #endif
 
-#endif /* __KERNEL__ */
-
 #endif /* _M68K_SETUP_H */
diff --git a/arch/m68k/include/asm/shmbuf.h b/arch/m68k/include/asm/shmbuf.h
deleted file mode 100644 (file)
index f8928d6..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-#ifndef _M68K_SHMBUF_H
-#define _M68K_SHMBUF_H
-
-/*
- * The shmid64_ds structure for m68k architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
- * - 2 miscellaneous 32-bit values
- */
-
-struct shmid64_ds {
-       struct ipc64_perm       shm_perm;       /* operation perms */
-       size_t                  shm_segsz;      /* size of segment (bytes) */
-       __kernel_time_t         shm_atime;      /* last attach time */
-       unsigned long           __unused1;
-       __kernel_time_t         shm_dtime;      /* last detach time */
-       unsigned long           __unused2;
-       __kernel_time_t         shm_ctime;      /* last change time */
-       unsigned long           __unused3;
-       __kernel_pid_t          shm_cpid;       /* pid of creator */
-       __kernel_pid_t          shm_lpid;       /* pid of last operator */
-       unsigned long           shm_nattch;     /* no. of current attaches */
-       unsigned long           __unused4;
-       unsigned long           __unused5;
-};
-
-struct shminfo64 {
-       unsigned long   shmmax;
-       unsigned long   shmmin;
-       unsigned long   shmmni;
-       unsigned long   shmseg;
-       unsigned long   shmall;
-       unsigned long   __unused1;
-       unsigned long   __unused2;
-       unsigned long   __unused3;
-       unsigned long   __unused4;
-};
-
-#endif /* _M68K_SHMBUF_H */
diff --git a/arch/m68k/include/asm/sigcontext.h b/arch/m68k/include/asm/sigcontext.h
deleted file mode 100644 (file)
index 523db2a..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef _ASM_M68k_SIGCONTEXT_H
-#define _ASM_M68k_SIGCONTEXT_H
-
-struct sigcontext {
-       unsigned long  sc_mask;         /* old sigmask */
-       unsigned long  sc_usp;          /* old user stack pointer */
-       unsigned long  sc_d0;
-       unsigned long  sc_d1;
-       unsigned long  sc_a0;
-       unsigned long  sc_a1;
-#ifdef __uClinux__
-       unsigned long  sc_a5;
-#endif
-       unsigned short sc_sr;
-       unsigned long  sc_pc;
-       unsigned short sc_formatvec;
-#ifndef __uClinux__
-       unsigned long  sc_fpregs[2*3];  /* room for two fp registers */
-       unsigned long  sc_fpcntl[3];
-       unsigned char  sc_fpstate[216];
-#endif
-};
-
-#endif
index 60e88660169c4575f53bb26d429b095abfd04a4e..2df26b57c26ada5cf34d6c608f75ebd7460f2063 100644 (file)
@@ -1,12 +1,8 @@
 #ifndef _M68K_SIGNAL_H
 #define _M68K_SIGNAL_H
 
-#include <linux/types.h>
+#include <uapi/asm/signal.h>
 
-/* Avoid too many header ordering problems.  */
-struct siginfo;
-
-#ifdef __KERNEL__
 /* Most things should be clean enough to redefine this at will, if care
    is taken to make libc match.  */
 
@@ -20,92 +16,6 @@ typedef struct {
        unsigned long sig[_NSIG_WORDS];
 } sigset_t;
 
-#else
-/* Here we must cater to libcs that poke about in kernel headers.  */
-
-#define NSIG           32
-typedef unsigned long sigset_t;
-
-#endif /* __KERNEL__ */
-
-#define SIGHUP          1
-#define SIGINT          2
-#define SIGQUIT                 3
-#define SIGILL          4
-#define SIGTRAP                 5
-#define SIGABRT                 6
-#define SIGIOT          6
-#define SIGBUS          7
-#define SIGFPE          8
-#define SIGKILL                 9
-#define SIGUSR1                10
-#define SIGSEGV                11
-#define SIGUSR2                12
-#define SIGPIPE                13
-#define SIGALRM                14
-#define SIGTERM                15
-#define SIGSTKFLT      16
-#define SIGCHLD                17
-#define SIGCONT                18
-#define SIGSTOP                19
-#define SIGTSTP                20
-#define SIGTTIN                21
-#define SIGTTOU                22
-#define SIGURG         23
-#define SIGXCPU                24
-#define SIGXFSZ                25
-#define SIGVTALRM      26
-#define SIGPROF                27
-#define SIGWINCH       28
-#define SIGIO          29
-#define SIGPOLL                SIGIO
-/*
-#define SIGLOST                29
-*/
-#define SIGPWR         30
-#define SIGSYS         31
-#define        SIGUNUSED       31
-
-/* These should not be considered constants from userland.  */
-#define SIGRTMIN       32
-#define SIGRTMAX       _NSIG
-
-/*
- * SA_FLAGS values:
- *
- * SA_ONSTACK indicates that a registered stack_t will be used.
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
- * SA_RESETHAND clears the handler when the signal is delivered.
- * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
- * SA_NODEFER prevents the current signal from being masked in the handler.
- *
- * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
- * Unix names RESETHAND and NODEFER respectively.
- */
-#define SA_NOCLDSTOP   0x00000001
-#define SA_NOCLDWAIT   0x00000002
-#define SA_SIGINFO     0x00000004
-#define SA_ONSTACK     0x08000000
-#define SA_RESTART     0x10000000
-#define SA_NODEFER     0x40000000
-#define SA_RESETHAND   0x80000000
-
-#define SA_NOMASK      SA_NODEFER
-#define SA_ONESHOT     SA_RESETHAND
-
-/*
- * sigaltstack controls
- */
-#define SS_ONSTACK     1
-#define SS_DISABLE     2
-
-#define MINSIGSTKSZ    2048
-#define SIGSTKSZ       8192
-
-#include <asm-generic/signal-defs.h>
-
-#ifdef __KERNEL__
 struct old_sigaction {
        __sighandler_t sa_handler;
        old_sigset_t sa_mask;
@@ -123,31 +33,6 @@ struct sigaction {
 struct k_sigaction {
        struct sigaction sa;
 };
-#else
-/* Here we must cater to libcs that poke about in kernel headers.  */
-
-struct sigaction {
-       union {
-         __sighandler_t _sa_handler;
-         void (*_sa_sigaction)(int, struct siginfo *, void *);
-       } _u;
-       sigset_t sa_mask;
-       unsigned long sa_flags;
-       void (*sa_restorer)(void);
-};
-
-#define sa_handler     _u._sa_handler
-#define sa_sigaction   _u._sa_sigaction
-
-#endif /* __KERNEL__ */
-
-typedef struct sigaltstack {
-       void __user *ss_sp;
-       int ss_flags;
-       size_t ss_size;
-} stack_t;
-
-#ifdef __KERNEL__
 #include <asm/sigcontext.h>
 
 #ifndef CONFIG_CPU_HAS_NO_BITFIELDS
@@ -156,7 +41,7 @@ typedef struct sigaltstack {
 static inline void sigaddset(sigset_t *set, int _sig)
 {
        asm ("bfset %0{%1,#1}"
-               : "+od" (*set)
+               : "+o" (*set)
                : "id" ((_sig - 1) ^ 31)
                : "cc");
 }
@@ -164,7 +49,7 @@ static inline void sigaddset(sigset_t *set, int _sig)
 static inline void sigdelset(sigset_t *set, int _sig)
 {
        asm ("bfclr %0{%1,#1}"
-               : "+od" (*set)
+               : "+o" (*set)
                : "id" ((_sig - 1) ^ 31)
                : "cc");
 }
@@ -180,7 +65,7 @@ static inline int __gen_sigismember(sigset_t *set, int _sig)
        int ret;
        asm ("bfextu %1{%2,#1},%0"
                : "=d" (ret)
-               : "od" (*set), "id" ((_sig-1) ^ 31)
+               : "o" (*set), "id" ((_sig-1) ^ 31)
                : "cc");
        return ret;
 }
@@ -208,5 +93,4 @@ struct pt_regs;
 extern void ptrace_signal_deliver(struct pt_regs *regs, void *cookie);
 #endif /* __uClinux__ */
 
-#endif /* __KERNEL__ */
 #endif /* _M68K_SIGNAL_H */
diff --git a/arch/m68k/include/asm/socket.h b/arch/m68k/include/asm/socket.h
deleted file mode 100644 (file)
index d1be684..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-#ifndef _ASM_SOCKET_H
-#define _ASM_SOCKET_H
-
-#include <asm/sockios.h>
-
-/* For setsockopt(2) */
-#define SOL_SOCKET     1
-
-#define SO_DEBUG       1
-#define SO_REUSEADDR   2
-#define SO_TYPE                3
-#define SO_ERROR       4
-#define SO_DONTROUTE   5
-#define SO_BROADCAST   6
-#define SO_SNDBUF      7
-#define SO_RCVBUF      8
-#define SO_SNDBUFFORCE 32
-#define SO_RCVBUFFORCE 33
-#define SO_KEEPALIVE   9
-#define SO_OOBINLINE   10
-#define SO_NO_CHECK    11
-#define SO_PRIORITY    12
-#define SO_LINGER      13
-#define SO_BSDCOMPAT   14
-/* To add :#define SO_REUSEPORT 15 */
-#define SO_PASSCRED    16
-#define SO_PEERCRED    17
-#define SO_RCVLOWAT    18
-#define SO_SNDLOWAT    19
-#define SO_RCVTIMEO    20
-#define SO_SNDTIMEO    21
-
-/* Security levels - as per NRL IPv6 - don't actually do anything */
-#define SO_SECURITY_AUTHENTICATION             22
-#define SO_SECURITY_ENCRYPTION_TRANSPORT       23
-#define SO_SECURITY_ENCRYPTION_NETWORK         24
-
-#define SO_BINDTODEVICE        25
-
-/* Socket filtering */
-#define SO_ATTACH_FILTER        26
-#define SO_DETACH_FILTER        27
-
-#define SO_PEERNAME             28
-#define SO_TIMESTAMP           29
-#define SCM_TIMESTAMP          SO_TIMESTAMP
-
-#define SO_ACCEPTCONN          30
-
-#define SO_PEERSEC             31
-#define SO_PASSSEC             34
-#define SO_TIMESTAMPNS         35
-#define SCM_TIMESTAMPNS                SO_TIMESTAMPNS
-
-#define SO_MARK                        36
-
-#define SO_TIMESTAMPING                37
-#define SCM_TIMESTAMPING       SO_TIMESTAMPING
-
-#define SO_PROTOCOL            38
-#define SO_DOMAIN              39
-
-#define SO_RXQ_OVFL             40
-
-#define SO_WIFI_STATUS         41
-#define SCM_WIFI_STATUS                SO_WIFI_STATUS
-#define SO_PEEK_OFF            42
-
-/* Instruct lower device to use last 4-bytes of skb data as FCS */
-#define SO_NOFCS               43
-
-#endif /* _ASM_SOCKET_H */
diff --git a/arch/m68k/include/asm/sockios.h b/arch/m68k/include/asm/sockios.h
deleted file mode 100644 (file)
index c04a239..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef __ARCH_M68K_SOCKIOS__
-#define __ARCH_M68K_SOCKIOS__
-
-/* Socket-level I/O control calls. */
-#define FIOSETOWN      0x8901
-#define SIOCSPGRP      0x8902
-#define FIOGETOWN      0x8903
-#define SIOCGPGRP      0x8904
-#define SIOCATMARK     0x8905
-#define SIOCGSTAMP     0x8906          /* Get stamp (timeval) */
-#define SIOCGSTAMPNS   0x8907          /* Get stamp (timespec) */
-
-#endif /* __ARCH_M68K_SOCKIOS__ */
diff --git a/arch/m68k/include/asm/stat.h b/arch/m68k/include/asm/stat.h
deleted file mode 100644 (file)
index dd38bc2..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-#ifndef _M68K_STAT_H
-#define _M68K_STAT_H
-
-struct __old_kernel_stat {
-       unsigned short st_dev;
-       unsigned short st_ino;
-       unsigned short st_mode;
-       unsigned short st_nlink;
-       unsigned short st_uid;
-       unsigned short st_gid;
-       unsigned short st_rdev;
-       unsigned long  st_size;
-       unsigned long  st_atime;
-       unsigned long  st_mtime;
-       unsigned long  st_ctime;
-};
-
-struct stat {
-       unsigned short st_dev;
-       unsigned short __pad1;
-       unsigned long  st_ino;
-       unsigned short st_mode;
-       unsigned short st_nlink;
-       unsigned short st_uid;
-       unsigned short st_gid;
-       unsigned short st_rdev;
-       unsigned short __pad2;
-       unsigned long  st_size;
-       unsigned long  st_blksize;
-       unsigned long  st_blocks;
-       unsigned long  st_atime;
-       unsigned long  __unused1;
-       unsigned long  st_mtime;
-       unsigned long  __unused2;
-       unsigned long  st_ctime;
-       unsigned long  __unused3;
-       unsigned long  __unused4;
-       unsigned long  __unused5;
-};
-
-/* This matches struct stat64 in glibc2.1, hence the absolutely
- * insane amounts of padding around dev_t's.
- */
-struct stat64 {
-       unsigned long long      st_dev;
-       unsigned char   __pad1[2];
-
-#define STAT64_HAS_BROKEN_ST_INO       1
-       unsigned long   __st_ino;
-
-       unsigned int    st_mode;
-       unsigned int    st_nlink;
-
-       unsigned long   st_uid;
-       unsigned long   st_gid;
-
-       unsigned long long      st_rdev;
-       unsigned char   __pad3[2];
-
-       long long       st_size;
-       unsigned long   st_blksize;
-
-       unsigned long long      st_blocks;      /* Number 512-byte blocks allocated. */
-
-       unsigned long   st_atime;
-       unsigned long   st_atime_nsec;
-
-       unsigned long   st_mtime;
-       unsigned long   st_mtime_nsec;
-
-       unsigned long   st_ctime;
-       unsigned long   st_ctime_nsec;
-
-       unsigned long long      st_ino;
-};
-
-#endif /* _M68K_STAT_H */
diff --git a/arch/m68k/include/asm/swab.h b/arch/m68k/include/asm/swab.h
deleted file mode 100644 (file)
index b7b37a4..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-#ifndef _M68K_SWAB_H
-#define _M68K_SWAB_H
-
-#include <linux/types.h>
-#include <linux/compiler.h>
-
-#define __SWAB_64_THRU_32__
-
-#if defined (__mcfisaaplus__) || defined (__mcfisac__)
-static inline __attribute_const__ __u32 __arch_swab32(__u32 val)
-{
-       __asm__("byterev %0" : "=d" (val) : "0" (val));
-       return val;
-}
-
-#define __arch_swab32 __arch_swab32
-#elif !defined(__mcoldfire__)
-
-static inline __attribute_const__ __u32 __arch_swab32(__u32 val)
-{
-       __asm__("rolw #8,%0; swap %0; rolw #8,%0" : "=d" (val) : "0" (val));
-       return val;
-}
-#define __arch_swab32 __arch_swab32
-#endif
-
-#endif /* _M68K_SWAB_H */
diff --git a/arch/m68k/include/asm/termbits.h b/arch/m68k/include/asm/termbits.h
deleted file mode 100644 (file)
index aea1e37..0000000
+++ /dev/null
@@ -1,201 +0,0 @@
-#ifndef __ARCH_M68K_TERMBITS_H__
-#define __ARCH_M68K_TERMBITS_H__
-
-#include <linux/posix_types.h>
-
-typedef unsigned char  cc_t;
-typedef unsigned int   speed_t;
-typedef unsigned int   tcflag_t;
-
-#define NCCS 19
-struct termios {
-       tcflag_t c_iflag;               /* input mode flags */
-       tcflag_t c_oflag;               /* output mode flags */
-       tcflag_t c_cflag;               /* control mode flags */
-       tcflag_t c_lflag;               /* local mode flags */
-       cc_t c_line;                    /* line discipline */
-       cc_t c_cc[NCCS];                /* control characters */
-};
-
-struct termios2 {
-       tcflag_t c_iflag;               /* input mode flags */
-       tcflag_t c_oflag;               /* output mode flags */
-       tcflag_t c_cflag;               /* control mode flags */
-       tcflag_t c_lflag;               /* local mode flags */
-       cc_t c_line;                    /* line discipline */
-       cc_t c_cc[NCCS];                /* control characters */
-       speed_t c_ispeed;               /* input speed */
-       speed_t c_ospeed;               /* output speed */
-};
-
-struct ktermios {
-       tcflag_t c_iflag;               /* input mode flags */
-       tcflag_t c_oflag;               /* output mode flags */
-       tcflag_t c_cflag;               /* control mode flags */
-       tcflag_t c_lflag;               /* local mode flags */
-       cc_t c_line;                    /* line discipline */
-       cc_t c_cc[NCCS];                /* control characters */
-       speed_t c_ispeed;               /* input speed */
-       speed_t c_ospeed;               /* output speed */
-};
-
-/* c_cc characters */
-#define VINTR 0
-#define VQUIT 1
-#define VERASE 2
-#define VKILL 3
-#define VEOF 4
-#define VTIME 5
-#define VMIN 6
-#define VSWTC 7
-#define VSTART 8
-#define VSTOP 9
-#define VSUSP 10
-#define VEOL 11
-#define VREPRINT 12
-#define VDISCARD 13
-#define VWERASE 14
-#define VLNEXT 15
-#define VEOL2 16
-
-
-/* c_iflag bits */
-#define IGNBRK 0000001
-#define BRKINT 0000002
-#define IGNPAR 0000004
-#define PARMRK 0000010
-#define INPCK  0000020
-#define ISTRIP 0000040
-#define INLCR  0000100
-#define IGNCR  0000200
-#define ICRNL  0000400
-#define IUCLC  0001000
-#define IXON   0002000
-#define IXANY  0004000
-#define IXOFF  0010000
-#define IMAXBEL        0020000
-#define IUTF8  0040000
-
-/* c_oflag bits */
-#define OPOST  0000001
-#define OLCUC  0000002
-#define ONLCR  0000004
-#define OCRNL  0000010
-#define ONOCR  0000020
-#define ONLRET 0000040
-#define OFILL  0000100
-#define OFDEL  0000200
-#define NLDLY  0000400
-#define   NL0  0000000
-#define   NL1  0000400
-#define CRDLY  0003000
-#define   CR0  0000000
-#define   CR1  0001000
-#define   CR2  0002000
-#define   CR3  0003000
-#define TABDLY 0014000
-#define   TAB0 0000000
-#define   TAB1 0004000
-#define   TAB2 0010000
-#define   TAB3 0014000
-#define   XTABS        0014000
-#define BSDLY  0020000
-#define   BS0  0000000
-#define   BS1  0020000
-#define VTDLY  0040000
-#define   VT0  0000000
-#define   VT1  0040000
-#define FFDLY  0100000
-#define   FF0  0000000
-#define   FF1  0100000
-
-/* c_cflag bit meaning */
-#define CBAUD  0010017
-#define  B0    0000000         /* hang up */
-#define  B50   0000001
-#define  B75   0000002
-#define  B110  0000003
-#define  B134  0000004
-#define  B150  0000005
-#define  B200  0000006
-#define  B300  0000007
-#define  B600  0000010
-#define  B1200 0000011
-#define  B1800 0000012
-#define  B2400 0000013
-#define  B4800 0000014
-#define  B9600 0000015
-#define  B19200        0000016
-#define  B38400        0000017
-#define EXTA B19200
-#define EXTB B38400
-#define CSIZE  0000060
-#define   CS5  0000000
-#define   CS6  0000020
-#define   CS7  0000040
-#define   CS8  0000060
-#define CSTOPB 0000100
-#define CREAD  0000200
-#define PARENB 0000400
-#define PARODD 0001000
-#define HUPCL  0002000
-#define CLOCAL 0004000
-#define CBAUDEX 0010000
-#define    BOTHER 0010000
-#define    B57600 0010001
-#define   B115200 0010002
-#define   B230400 0010003
-#define   B460800 0010004
-#define   B500000 0010005
-#define   B576000 0010006
-#define   B921600 0010007
-#define  B1000000 0010010
-#define  B1152000 0010011
-#define  B1500000 0010012
-#define  B2000000 0010013
-#define  B2500000 0010014
-#define  B3000000 0010015
-#define  B3500000 0010016
-#define  B4000000 0010017
-#define CIBAUD   002003600000          /* input baud rate */
-#define CMSPAR   010000000000          /* mark or space (stick) parity */
-#define CRTSCTS          020000000000          /* flow control */
-
-#define IBSHIFT        16                      /* Shift from CBAUD to CIBAUD */
-
-/* c_lflag bits */
-#define ISIG   0000001
-#define ICANON 0000002
-#define XCASE  0000004
-#define ECHO   0000010
-#define ECHOE  0000020
-#define ECHOK  0000040
-#define ECHONL 0000100
-#define NOFLSH 0000200
-#define TOSTOP 0000400
-#define ECHOCTL        0001000
-#define ECHOPRT        0002000
-#define ECHOKE 0004000
-#define FLUSHO 0010000
-#define PENDIN 0040000
-#define IEXTEN 0100000
-#define EXTPROC        0200000
-
-
-/* tcflow() and TCXONC use these */
-#define        TCOOFF          0
-#define        TCOON           1
-#define        TCIOFF          2
-#define        TCION           3
-
-/* tcflush() and TCFLSH use these */
-#define        TCIFLUSH        0
-#define        TCOFLUSH        1
-#define        TCIOFLUSH       2
-
-/* tcsetattr uses these */
-#define        TCSANOW         0
-#define        TCSADRAIN       1
-#define        TCSAFLUSH       2
-
-#endif /* __ARCH_M68K_TERMBITS_H__ */
index 0823032e404572fe7bbeca5a639fddd0595248b2..ad8efb098663ee41a28487f385c84642c4f4bf0f 100644 (file)
@@ -1,27 +1,8 @@
 #ifndef _M68K_TERMIOS_H
 #define _M68K_TERMIOS_H
 
-#include <asm/termbits.h>
-#include <asm/ioctls.h>
+#include <uapi/asm/termios.h>
 
-struct winsize {
-       unsigned short ws_row;
-       unsigned short ws_col;
-       unsigned short ws_xpixel;
-       unsigned short ws_ypixel;
-};
-
-#define NCC 8
-struct termio {
-       unsigned short c_iflag;         /* input mode flags */
-       unsigned short c_oflag;         /* output mode flags */
-       unsigned short c_cflag;         /* control mode flags */
-       unsigned short c_lflag;         /* local mode flags */
-       unsigned char c_line;           /* line discipline */
-       unsigned char c_cc[NCC];        /* control characters */
-};
-
-#ifdef __KERNEL__
 /*     intr=^C         quit=^|         erase=del       kill=^U
        eof=^D          vtime=\0        vmin=\1         sxtc=\0
        start=^Q        stop=^S         susp=^Z         eol=\0
@@ -29,27 +10,6 @@ struct termio {
        eol2=\0
 */
 #define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
-#endif
-
-/* modem lines */
-#define TIOCM_LE       0x001
-#define TIOCM_DTR      0x002
-#define TIOCM_RTS      0x004
-#define TIOCM_ST       0x008
-#define TIOCM_SR       0x010
-#define TIOCM_CTS      0x020
-#define TIOCM_CAR      0x040
-#define TIOCM_RNG      0x080
-#define TIOCM_DSR      0x100
-#define TIOCM_CD       TIOCM_CAR
-#define TIOCM_RI       TIOCM_RNG
-#define TIOCM_OUT1     0x2000
-#define TIOCM_OUT2     0x4000
-#define TIOCM_LOOP     0x8000
-
-/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
-
-#ifdef __KERNEL__
 
 /*
  * Translate a "termio" structure into a "termios". Ugh.
@@ -87,6 +47,4 @@ struct termio {
 #define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios))
 #define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios))
 
-#endif /* __KERNEL__ */
-
 #endif /* _M68K_TERMIOS_H */
index c702ad71679195f501f540b7ed5b32108f920813..5fc7f7bec1c807ced0c300d5f6f4747cf781c024 100644 (file)
 #ifndef _ASM_M68K_UNISTD_H_
 #define _ASM_M68K_UNISTD_H_
 
-/*
- * This file contains the system call numbers.
- */
-
-#define __NR_restart_syscall     0
-#define __NR_exit                1
-#define __NR_fork                2
-#define __NR_read                3
-#define __NR_write               4
-#define __NR_open                5
-#define __NR_close               6
-#define __NR_waitpid             7
-#define __NR_creat               8
-#define __NR_link                9
-#define __NR_unlink             10
-#define __NR_execve             11
-#define __NR_chdir              12
-#define __NR_time               13
-#define __NR_mknod              14
-#define __NR_chmod              15
-#define __NR_chown              16
-/*#define __NR_break            17*/
-#define __NR_oldstat            18
-#define __NR_lseek              19
-#define __NR_getpid             20
-#define __NR_mount              21
-#define __NR_umount             22
-#define __NR_setuid             23
-#define __NR_getuid             24
-#define __NR_stime              25
-#define __NR_ptrace             26
-#define __NR_alarm              27
-#define __NR_oldfstat           28
-#define __NR_pause              29
-#define __NR_utime              30
-/*#define __NR_stty             31*/
-/*#define __NR_gtty             32*/
-#define __NR_access             33
-#define __NR_nice               34
-/*#define __NR_ftime            35*/
-#define __NR_sync               36
-#define __NR_kill               37
-#define __NR_rename             38
-#define __NR_mkdir              39
-#define __NR_rmdir              40
-#define __NR_dup                41
-#define __NR_pipe               42
-#define __NR_times              43
-/*#define __NR_prof             44*/
-#define __NR_brk                45
-#define __NR_setgid             46
-#define __NR_getgid             47
-#define __NR_signal             48
-#define __NR_geteuid            49
-#define __NR_getegid            50
-#define __NR_acct               51
-#define __NR_umount2            52
-/*#define __NR_lock             53*/
-#define __NR_ioctl              54
-#define __NR_fcntl              55
-/*#define __NR_mpx              56*/
-#define __NR_setpgid            57
-/*#define __NR_ulimit           58*/
-/*#define __NR_oldolduname      59*/
-#define __NR_umask              60
-#define __NR_chroot             61
-#define __NR_ustat              62
-#define __NR_dup2               63
-#define __NR_getppid            64
-#define __NR_getpgrp            65
-#define __NR_setsid             66
-#define __NR_sigaction          67
-#define __NR_sgetmask           68
-#define __NR_ssetmask           69
-#define __NR_setreuid           70
-#define __NR_setregid           71
-#define __NR_sigsuspend                 72
-#define __NR_sigpending                 73
-#define __NR_sethostname        74
-#define __NR_setrlimit          75
-#define __NR_getrlimit          76
-#define __NR_getrusage          77
-#define __NR_gettimeofday       78
-#define __NR_settimeofday       79
-#define __NR_getgroups          80
-#define __NR_setgroups          81
-#define __NR_select             82
-#define __NR_symlink            83
-#define __NR_oldlstat           84
-#define __NR_readlink           85
-#define __NR_uselib             86
-#define __NR_swapon             87
-#define __NR_reboot             88
-#define __NR_readdir            89
-#define __NR_mmap               90
-#define __NR_munmap             91
-#define __NR_truncate           92
-#define __NR_ftruncate          93
-#define __NR_fchmod             94
-#define __NR_fchown             95
-#define __NR_getpriority        96
-#define __NR_setpriority        97
-/*#define __NR_profil           98*/
-#define __NR_statfs             99
-#define __NR_fstatfs           100
-/*#define __NR_ioperm          101*/
-#define __NR_socketcall                102
-#define __NR_syslog            103
-#define __NR_setitimer         104
-#define __NR_getitimer         105
-#define __NR_stat              106
-#define __NR_lstat             107
-#define __NR_fstat             108
-/*#define __NR_olduname                109*/
-/*#define __NR_iopl            110*/ /* not supported */
-#define __NR_vhangup           111
-/*#define __NR_idle            112*/ /* Obsolete */
-/*#define __NR_vm86            113*/ /* not supported */
-#define __NR_wait4             114
-#define __NR_swapoff           115
-#define __NR_sysinfo           116
-#define __NR_ipc               117
-#define __NR_fsync             118
-#define __NR_sigreturn         119
-#define __NR_clone             120
-#define __NR_setdomainname     121
-#define __NR_uname             122
-#define __NR_cacheflush                123
-#define __NR_adjtimex          124
-#define __NR_mprotect          125
-#define __NR_sigprocmask       126
-#define __NR_create_module     127
-#define __NR_init_module       128
-#define __NR_delete_module     129
-#define __NR_get_kernel_syms   130
-#define __NR_quotactl          131
-#define __NR_getpgid           132
-#define __NR_fchdir            133
-#define __NR_bdflush           134
-#define __NR_sysfs             135
-#define __NR_personality       136
-/*#define __NR_afs_syscall     137*/ /* Syscall for Andrew File System */
-#define __NR_setfsuid          138
-#define __NR_setfsgid          139
-#define __NR__llseek           140
-#define __NR_getdents          141
-#define __NR__newselect                142
-#define __NR_flock             143
-#define __NR_msync             144
-#define __NR_readv             145
-#define __NR_writev            146
-#define __NR_getsid            147
-#define __NR_fdatasync         148
-#define __NR__sysctl           149
-#define __NR_mlock             150
-#define __NR_munlock           151
-#define __NR_mlockall          152
-#define __NR_munlockall                153
-#define __NR_sched_setparam            154
-#define __NR_sched_getparam            155
-#define __NR_sched_setscheduler                156
-#define __NR_sched_getscheduler                157
-#define __NR_sched_yield               158
-#define __NR_sched_get_priority_max    159
-#define __NR_sched_get_priority_min    160
-#define __NR_sched_rr_get_interval     161
-#define __NR_nanosleep         162
-#define __NR_mremap            163
-#define __NR_setresuid         164
-#define __NR_getresuid         165
-#define __NR_getpagesize       166
-#define __NR_query_module      167
-#define __NR_poll              168
-#define __NR_nfsservctl                169
-#define __NR_setresgid         170
-#define __NR_getresgid         171
-#define __NR_prctl             172
-#define __NR_rt_sigreturn      173
-#define __NR_rt_sigaction      174
-#define __NR_rt_sigprocmask    175
-#define __NR_rt_sigpending     176
-#define __NR_rt_sigtimedwait   177
-#define __NR_rt_sigqueueinfo   178
-#define __NR_rt_sigsuspend     179
-#define __NR_pread64           180
-#define __NR_pwrite64          181
-#define __NR_lchown            182
-#define __NR_getcwd            183
-#define __NR_capget            184
-#define __NR_capset            185
-#define __NR_sigaltstack       186
-#define __NR_sendfile          187
-#define __NR_getpmsg           188     /* some people actually want streams */
-#define __NR_putpmsg           189     /* some people actually want streams */
-#define __NR_vfork             190
-#define __NR_ugetrlimit                191
-#define __NR_mmap2             192
-#define __NR_truncate64                193
-#define __NR_ftruncate64       194
-#define __NR_stat64            195
-#define __NR_lstat64           196
-#define __NR_fstat64           197
-#define __NR_chown32           198
-#define __NR_getuid32          199
-#define __NR_getgid32          200
-#define __NR_geteuid32         201
-#define __NR_getegid32         202
-#define __NR_setreuid32                203
-#define __NR_setregid32                204
-#define __NR_getgroups32       205
-#define __NR_setgroups32       206
-#define __NR_fchown32          207
-#define __NR_setresuid32       208
-#define __NR_getresuid32       209
-#define __NR_setresgid32       210
-#define __NR_getresgid32       211
-#define __NR_lchown32          212
-#define __NR_setuid32          213
-#define __NR_setgid32          214
-#define __NR_setfsuid32                215
-#define __NR_setfsgid32                216
-#define __NR_pivot_root                217
-/* 218*/
-/* 219*/
-#define __NR_getdents64                220
-#define __NR_gettid            221
-#define __NR_tkill             222
-#define __NR_setxattr          223
-#define __NR_lsetxattr         224
-#define __NR_fsetxattr         225
-#define __NR_getxattr          226
-#define __NR_lgetxattr         227
-#define __NR_fgetxattr         228
-#define __NR_listxattr         229
-#define __NR_llistxattr                230
-#define __NR_flistxattr                231
-#define __NR_removexattr       232
-#define __NR_lremovexattr      233
-#define __NR_fremovexattr      234
-#define __NR_futex             235
-#define __NR_sendfile64                236
-#define __NR_mincore           237
-#define __NR_madvise           238
-#define __NR_fcntl64           239
-#define __NR_readahead         240
-#define __NR_io_setup          241
-#define __NR_io_destroy                242
-#define __NR_io_getevents      243
-#define __NR_io_submit         244
-#define __NR_io_cancel         245
-#define __NR_fadvise64         246
-#define __NR_exit_group                247
-#define __NR_lookup_dcookie    248
-#define __NR_epoll_create      249
-#define __NR_epoll_ctl         250
-#define __NR_epoll_wait                251
-#define __NR_remap_file_pages  252
-#define __NR_set_tid_address   253
-#define __NR_timer_create      254
-#define __NR_timer_settime     255
-#define __NR_timer_gettime     256
-#define __NR_timer_getoverrun  257
-#define __NR_timer_delete      258
-#define __NR_clock_settime     259
-#define __NR_clock_gettime     260
-#define __NR_clock_getres      261
-#define __NR_clock_nanosleep   262
-#define __NR_statfs64          263
-#define __NR_fstatfs64         264
-#define __NR_tgkill            265
-#define __NR_utimes            266
-#define __NR_fadvise64_64      267
-#define __NR_mbind             268
-#define __NR_get_mempolicy     269
-#define __NR_set_mempolicy     270
-#define __NR_mq_open           271
-#define __NR_mq_unlink         272
-#define __NR_mq_timedsend      273
-#define __NR_mq_timedreceive   274
-#define __NR_mq_notify         275
-#define __NR_mq_getsetattr     276
-#define __NR_waitid            277
-/*#define __NR_vserver         278*/
-#define __NR_add_key           279
-#define __NR_request_key       280
-#define __NR_keyctl            281
-#define __NR_ioprio_set                282
-#define __NR_ioprio_get                283
-#define __NR_inotify_init      284
-#define __NR_inotify_add_watch 285
-#define __NR_inotify_rm_watch  286
-#define __NR_migrate_pages     287
-#define __NR_openat            288
-#define __NR_mkdirat           289
-#define __NR_mknodat           290
-#define __NR_fchownat          291
-#define __NR_futimesat         292
-#define __NR_fstatat64         293
-#define __NR_unlinkat          294
-#define __NR_renameat          295
-#define __NR_linkat            296
-#define __NR_symlinkat         297
-#define __NR_readlinkat                298
-#define __NR_fchmodat          299
-#define __NR_faccessat         300
-#define __NR_pselect6          301
-#define __NR_ppoll             302
-#define __NR_unshare           303
-#define __NR_set_robust_list   304
-#define __NR_get_robust_list   305
-#define __NR_splice            306
-#define __NR_sync_file_range   307
-#define __NR_tee               308
-#define __NR_vmsplice          309
-#define __NR_move_pages                310
-#define __NR_sched_setaffinity 311
-#define __NR_sched_getaffinity 312
-#define __NR_kexec_load                313
-#define __NR_getcpu            314
-#define __NR_epoll_pwait       315
-#define __NR_utimensat         316
-#define __NR_signalfd          317
-#define __NR_timerfd_create    318
-#define __NR_eventfd           319
-#define __NR_fallocate         320
-#define __NR_timerfd_settime   321
-#define __NR_timerfd_gettime   322
-#define __NR_signalfd4         323
-#define __NR_eventfd2          324
-#define __NR_epoll_create1     325
-#define __NR_dup3              326
-#define __NR_pipe2             327
-#define __NR_inotify_init1     328
-#define __NR_preadv            329
-#define __NR_pwritev           330
-#define __NR_rt_tgsigqueueinfo 331
-#define __NR_perf_event_open   332
-#define __NR_get_thread_area   333
-#define __NR_set_thread_area   334
-#define __NR_atomic_cmpxchg_32 335
-#define __NR_atomic_barrier    336
-#define __NR_fanotify_init     337
-#define __NR_fanotify_mark     338
-#define __NR_prlimit64         339
-#define __NR_name_to_handle_at 340
-#define __NR_open_by_handle_at 341
-#define __NR_clock_adjtime     342
-#define __NR_syncfs            343
-#define __NR_setns             344
-#define __NR_process_vm_readv  345
-#define __NR_process_vm_writev 346
+#include <uapi/asm/unistd.h>
 
-#ifdef __KERNEL__
 
-#define NR_syscalls            347
+#define NR_syscalls            348
 
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_OLD_STAT
  */
 #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 
-#endif /* __KERNEL__ */
 #endif /* _ASM_M68K_UNISTD_H_ */
index baebb3da1d44160fc6f6f259886656e6f494b167..972bce120e1e94b8550408f788e0502ecd3d308f 100644 (file)
@@ -1,3 +1,26 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
 
+header-y += a.out.h
+header-y += auxvec.h
+header-y += byteorder.h
+header-y += cachectl.h
+header-y += fcntl.h
+header-y += ioctls.h
+header-y += msgbuf.h
+header-y += param.h
+header-y += poll.h
+header-y += posix_types.h
+header-y += ptrace.h
+header-y += sembuf.h
+header-y += setup.h
+header-y += shmbuf.h
+header-y += sigcontext.h
+header-y += signal.h
+header-y += socket.h
+header-y += sockios.h
+header-y += stat.h
+header-y += swab.h
+header-y += termbits.h
+header-y += termios.h
+header-y += unistd.h
diff --git a/arch/m68k/include/uapi/asm/a.out.h b/arch/m68k/include/uapi/asm/a.out.h
new file mode 100644 (file)
index 0000000..3885fe4
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef __M68K_A_OUT_H__
+#define __M68K_A_OUT_H__
+
+struct exec
+{
+  unsigned long a_info;                /* Use macros N_MAGIC, etc for access */
+  unsigned a_text;             /* length of text, in bytes */
+  unsigned a_data;             /* length of data, in bytes */
+  unsigned a_bss;              /* length of uninitialized data area for file, in bytes */
+  unsigned a_syms;             /* length of symbol table data in file, in bytes */
+  unsigned a_entry;            /* start address */
+  unsigned a_trsize;           /* length of relocation info for text, in bytes */
+  unsigned a_drsize;           /* length of relocation info for data, in bytes */
+};
+
+#define N_TRSIZE(a)    ((a).a_trsize)
+#define N_DRSIZE(a)    ((a).a_drsize)
+#define N_SYMSIZE(a)   ((a).a_syms)
+
+#endif /* __M68K_A_OUT_H__ */
diff --git a/arch/m68k/include/uapi/asm/auxvec.h b/arch/m68k/include/uapi/asm/auxvec.h
new file mode 100644 (file)
index 0000000..844d6d5
--- /dev/null
@@ -0,0 +1,4 @@
+#ifndef __ASMm68k_AUXVEC_H
+#define __ASMm68k_AUXVEC_H
+
+#endif
diff --git a/arch/m68k/include/uapi/asm/byteorder.h b/arch/m68k/include/uapi/asm/byteorder.h
new file mode 100644 (file)
index 0000000..31b260a
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _M68K_BYTEORDER_H
+#define _M68K_BYTEORDER_H
+
+#include <linux/byteorder/big_endian.h>
+
+#endif /* _M68K_BYTEORDER_H */
diff --git a/arch/m68k/include/uapi/asm/cachectl.h b/arch/m68k/include/uapi/asm/cachectl.h
new file mode 100644 (file)
index 0000000..525978e
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef _M68K_CACHECTL_H
+#define _M68K_CACHECTL_H
+
+/* Definitions for the cacheflush system call.  */
+
+#define FLUSH_SCOPE_LINE    1  /* Flush a cache line */
+#define FLUSH_SCOPE_PAGE    2  /* Flush a page */
+#define FLUSH_SCOPE_ALL     3  /* Flush the whole cache -- superuser only */
+
+#define FLUSH_CACHE_DATA    1  /* Writeback and flush data cache */
+#define FLUSH_CACHE_INSN    2  /* Flush instruction cache */
+#define FLUSH_CACHE_BOTH    3  /* Flush both caches */
+
+#endif /* _M68K_CACHECTL_H */
diff --git a/arch/m68k/include/uapi/asm/fcntl.h b/arch/m68k/include/uapi/asm/fcntl.h
new file mode 100644 (file)
index 0000000..1c369b2
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef _M68K_FCNTL_H
+#define _M68K_FCNTL_H
+
+#define O_DIRECTORY    040000  /* must be a directory */
+#define O_NOFOLLOW     0100000 /* don't follow links */
+#define O_DIRECT       0200000 /* direct disk access hint - currently ignored */
+#define O_LARGEFILE    0400000
+
+#include <asm-generic/fcntl.h>
+
+#endif /* _M68K_FCNTL_H */
diff --git a/arch/m68k/include/uapi/asm/ioctls.h b/arch/m68k/include/uapi/asm/ioctls.h
new file mode 100644 (file)
index 0000000..1332bb4
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef __ARCH_M68K_IOCTLS_H__
+#define __ARCH_M68K_IOCTLS_H__
+
+#define FIOQSIZE       0x545E
+
+#include <asm-generic/ioctls.h>
+
+#endif /* __ARCH_M68K_IOCTLS_H__ */
diff --git a/arch/m68k/include/uapi/asm/msgbuf.h b/arch/m68k/include/uapi/asm/msgbuf.h
new file mode 100644 (file)
index 0000000..243cb79
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef _M68K_MSGBUF_H
+#define _M68K_MSGBUF_H
+
+/*
+ * The msqid64_ds structure for m68k architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct msqid64_ds {
+       struct ipc64_perm msg_perm;
+       __kernel_time_t msg_stime;      /* last msgsnd time */
+       unsigned long   __unused1;
+       __kernel_time_t msg_rtime;      /* last msgrcv time */
+       unsigned long   __unused2;
+       __kernel_time_t msg_ctime;      /* last change time */
+       unsigned long   __unused3;
+       unsigned long  msg_cbytes;      /* current number of bytes on queue */
+       unsigned long  msg_qnum;        /* number of messages in queue */
+       unsigned long  msg_qbytes;      /* max number of bytes on queue */
+       __kernel_pid_t msg_lspid;       /* pid of last msgsnd */
+       __kernel_pid_t msg_lrpid;       /* last receive pid */
+       unsigned long  __unused4;
+       unsigned long  __unused5;
+};
+
+#endif /* _M68K_MSGBUF_H */
diff --git a/arch/m68k/include/uapi/asm/param.h b/arch/m68k/include/uapi/asm/param.h
new file mode 100644 (file)
index 0000000..36265cc
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef _M68K_PARAM_H
+#define _M68K_PARAM_H
+
+#ifdef __uClinux__
+#define EXEC_PAGESIZE  4096
+#else
+#define EXEC_PAGESIZE  8192
+#endif
+
+#include <asm-generic/param.h>
+
+#endif /* _M68K_PARAM_H */
diff --git a/arch/m68k/include/uapi/asm/poll.h b/arch/m68k/include/uapi/asm/poll.h
new file mode 100644 (file)
index 0000000..f080fcd
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef __m68k_POLL_H
+#define __m68k_POLL_H
+
+#define POLLWRNORM     POLLOUT
+#define POLLWRBAND     256
+
+#include <asm-generic/poll.h>
+
+#endif
diff --git a/arch/m68k/include/uapi/asm/posix_types.h b/arch/m68k/include/uapi/asm/posix_types.h
new file mode 100644 (file)
index 0000000..cf4dbf7
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef __ARCH_M68K_POSIX_TYPES_H
+#define __ARCH_M68K_POSIX_TYPES_H
+
+/*
+ * This file is generally used by user-level software, so you need to
+ * be a little careful about namespace pollution etc.  Also, we cannot
+ * assume GCC is being used.
+ */
+
+typedef unsigned short __kernel_mode_t;
+#define __kernel_mode_t __kernel_mode_t
+
+typedef unsigned short __kernel_ipc_pid_t;
+#define __kernel_ipc_pid_t __kernel_ipc_pid_t
+
+typedef unsigned short __kernel_uid_t;
+typedef unsigned short __kernel_gid_t;
+#define __kernel_uid_t __kernel_uid_t
+
+typedef unsigned short __kernel_old_dev_t;
+#define __kernel_old_dev_t __kernel_old_dev_t
+
+#include <asm-generic/posix_types.h>
+
+#endif
diff --git a/arch/m68k/include/uapi/asm/ptrace.h b/arch/m68k/include/uapi/asm/ptrace.h
new file mode 100644 (file)
index 0000000..caf92fd
--- /dev/null
@@ -0,0 +1,79 @@
+#ifndef _UAPI_M68K_PTRACE_H
+#define _UAPI_M68K_PTRACE_H
+
+#define PT_D1     0
+#define PT_D2     1
+#define PT_D3     2
+#define PT_D4     3
+#define PT_D5     4
+#define PT_D6     5
+#define PT_D7     6
+#define PT_A0     7
+#define PT_A1     8
+#define PT_A2     9
+#define PT_A3     10
+#define PT_A4     11
+#define PT_A5     12
+#define PT_A6     13
+#define PT_D0     14
+#define PT_USP    15
+#define PT_ORIG_D0 16
+#define PT_SR     17
+#define PT_PC     18
+
+#ifndef __ASSEMBLY__
+
+/* this struct defines the way the registers are stored on the
+   stack during a system call. */
+
+struct pt_regs {
+  long     d1;
+  long     d2;
+  long     d3;
+  long     d4;
+  long     d5;
+  long     a0;
+  long     a1;
+  long     a2;
+  long     d0;
+  long     orig_d0;
+  long     stkadj;
+#ifdef CONFIG_COLDFIRE
+  unsigned format :  4; /* frame format specifier */
+  unsigned vector : 12; /* vector offset */
+  unsigned short sr;
+  unsigned long  pc;
+#else
+  unsigned short sr;
+  unsigned long  pc;
+  unsigned format :  4; /* frame format specifier */
+  unsigned vector : 12; /* vector offset */
+#endif
+};
+
+/*
+ * This is the extended stack used by signal handlers and the context
+ * switcher: it's pushed after the normal "struct pt_regs".
+ */
+struct switch_stack {
+       unsigned long  d6;
+       unsigned long  d7;
+       unsigned long  a3;
+       unsigned long  a4;
+       unsigned long  a5;
+       unsigned long  a6;
+       unsigned long  retpc;
+};
+
+/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
+#define PTRACE_GETREGS            12
+#define PTRACE_SETREGS            13
+#define PTRACE_GETFPREGS          14
+#define PTRACE_SETFPREGS          15
+
+#define PTRACE_GET_THREAD_AREA    25
+
+#define PTRACE_SINGLEBLOCK     33      /* resume execution until next branch */
+
+#endif /* __ASSEMBLY__ */
+#endif /* _UAPI_M68K_PTRACE_H */
diff --git a/arch/m68k/include/uapi/asm/sembuf.h b/arch/m68k/include/uapi/asm/sembuf.h
new file mode 100644 (file)
index 0000000..2308052
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef _M68K_SEMBUF_H
+#define _M68K_SEMBUF_H
+
+/*
+ * The semid64_ds structure for m68k architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct semid64_ds {
+       struct ipc64_perm sem_perm;             /* permissions .. see ipc.h */
+       __kernel_time_t sem_otime;              /* last semop time */
+       unsigned long   __unused1;
+       __kernel_time_t sem_ctime;              /* last change time */
+       unsigned long   __unused2;
+       unsigned long   sem_nsems;              /* no. of semaphores in array */
+       unsigned long   __unused3;
+       unsigned long   __unused4;
+};
+
+#endif /* _M68K_SEMBUF_H */
diff --git a/arch/m68k/include/uapi/asm/setup.h b/arch/m68k/include/uapi/asm/setup.h
new file mode 100644 (file)
index 0000000..85579bf
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+** asm/setup.h -- Definition of the Linux/m68k setup information
+**
+** Copyright 1992 by Greg Harp
+**
+** 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.
+**
+** Created 09/29/92 by Greg Harp
+**
+** 5/2/94 Roman Hodek:
+**   Added bi_atari part of the machine dependent union bi_un; for now it
+**   contains just a model field to distinguish between TT and Falcon.
+** 26/7/96 Roman Zippel:
+**   Renamed to setup.h; added some useful macros to allow gcc some
+**   optimizations if possible.
+** 5/10/96 Geert Uytterhoeven:
+**   Redesign of the boot information structure; moved boot information
+**   structure to bootinfo.h
+*/
+
+#ifndef _UAPI_M68K_SETUP_H
+#define _UAPI_M68K_SETUP_H
+
+
+
+    /*
+     *  Linux/m68k Architectures
+     */
+
+#define MACH_AMIGA    1
+#define MACH_ATARI    2
+#define MACH_MAC      3
+#define MACH_APOLLO   4
+#define MACH_SUN3     5
+#define MACH_MVME147  6
+#define MACH_MVME16x  7
+#define MACH_BVME6000 8
+#define MACH_HP300    9
+#define MACH_Q40     10
+#define MACH_SUN3X   11
+#define MACH_M54XX   12
+
+#define COMMAND_LINE_SIZE 256
+
+
+
+    /*
+     *  CPU, FPU and MMU types
+     *
+     *  Note: we may rely on the following equalities:
+     *
+     *      CPU_68020 == MMU_68851
+     *      CPU_68030 == MMU_68030
+     *      CPU_68040 == FPU_68040 == MMU_68040
+     *      CPU_68060 == FPU_68060 == MMU_68060
+     */
+
+#define CPUB_68020     0
+#define CPUB_68030     1
+#define CPUB_68040     2
+#define CPUB_68060     3
+#define CPUB_COLDFIRE  4
+
+#define CPU_68020      (1<<CPUB_68020)
+#define CPU_68030      (1<<CPUB_68030)
+#define CPU_68040      (1<<CPUB_68040)
+#define CPU_68060      (1<<CPUB_68060)
+#define CPU_COLDFIRE   (1<<CPUB_COLDFIRE)
+
+#define FPUB_68881     0
+#define FPUB_68882     1
+#define FPUB_68040     2                       /* Internal FPU */
+#define FPUB_68060     3                       /* Internal FPU */
+#define FPUB_SUNFPA    4                       /* Sun-3 FPA */
+#define FPUB_COLDFIRE  5                       /* ColdFire FPU */
+
+#define FPU_68881      (1<<FPUB_68881)
+#define FPU_68882      (1<<FPUB_68882)
+#define FPU_68040      (1<<FPUB_68040)
+#define FPU_68060      (1<<FPUB_68060)
+#define FPU_SUNFPA     (1<<FPUB_SUNFPA)
+#define FPU_COLDFIRE   (1<<FPUB_COLDFIRE)
+
+#define MMUB_68851     0
+#define MMUB_68030     1                       /* Internal MMU */
+#define MMUB_68040     2                       /* Internal MMU */
+#define MMUB_68060     3                       /* Internal MMU */
+#define MMUB_APOLLO    4                       /* Custom Apollo */
+#define MMUB_SUN3      5                       /* Custom Sun-3 */
+#define MMUB_COLDFIRE  6                       /* Internal MMU */
+
+#define MMU_68851      (1<<MMUB_68851)
+#define MMU_68030      (1<<MMUB_68030)
+#define MMU_68040      (1<<MMUB_68040)
+#define MMU_68060      (1<<MMUB_68060)
+#define MMU_SUN3       (1<<MMUB_SUN3)
+#define MMU_APOLLO     (1<<MMUB_APOLLO)
+#define MMU_COLDFIRE   (1<<MMUB_COLDFIRE)
+
+
+#endif /* _UAPI_M68K_SETUP_H */
diff --git a/arch/m68k/include/uapi/asm/shmbuf.h b/arch/m68k/include/uapi/asm/shmbuf.h
new file mode 100644 (file)
index 0000000..f8928d6
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef _M68K_SHMBUF_H
+#define _M68K_SHMBUF_H
+
+/*
+ * The shmid64_ds structure for m68k architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct shmid64_ds {
+       struct ipc64_perm       shm_perm;       /* operation perms */
+       size_t                  shm_segsz;      /* size of segment (bytes) */
+       __kernel_time_t         shm_atime;      /* last attach time */
+       unsigned long           __unused1;
+       __kernel_time_t         shm_dtime;      /* last detach time */
+       unsigned long           __unused2;
+       __kernel_time_t         shm_ctime;      /* last change time */
+       unsigned long           __unused3;
+       __kernel_pid_t          shm_cpid;       /* pid of creator */
+       __kernel_pid_t          shm_lpid;       /* pid of last operator */
+       unsigned long           shm_nattch;     /* no. of current attaches */
+       unsigned long           __unused4;
+       unsigned long           __unused5;
+};
+
+struct shminfo64 {
+       unsigned long   shmmax;
+       unsigned long   shmmin;
+       unsigned long   shmmni;
+       unsigned long   shmseg;
+       unsigned long   shmall;
+       unsigned long   __unused1;
+       unsigned long   __unused2;
+       unsigned long   __unused3;
+       unsigned long   __unused4;
+};
+
+#endif /* _M68K_SHMBUF_H */
diff --git a/arch/m68k/include/uapi/asm/sigcontext.h b/arch/m68k/include/uapi/asm/sigcontext.h
new file mode 100644 (file)
index 0000000..523db2a
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef _ASM_M68k_SIGCONTEXT_H
+#define _ASM_M68k_SIGCONTEXT_H
+
+struct sigcontext {
+       unsigned long  sc_mask;         /* old sigmask */
+       unsigned long  sc_usp;          /* old user stack pointer */
+       unsigned long  sc_d0;
+       unsigned long  sc_d1;
+       unsigned long  sc_a0;
+       unsigned long  sc_a1;
+#ifdef __uClinux__
+       unsigned long  sc_a5;
+#endif
+       unsigned short sc_sr;
+       unsigned long  sc_pc;
+       unsigned short sc_formatvec;
+#ifndef __uClinux__
+       unsigned long  sc_fpregs[2*3];  /* room for two fp registers */
+       unsigned long  sc_fpcntl[3];
+       unsigned char  sc_fpstate[216];
+#endif
+};
+
+#endif
diff --git a/arch/m68k/include/uapi/asm/signal.h b/arch/m68k/include/uapi/asm/signal.h
new file mode 100644 (file)
index 0000000..2b450f3
--- /dev/null
@@ -0,0 +1,118 @@
+#ifndef _UAPI_M68K_SIGNAL_H
+#define _UAPI_M68K_SIGNAL_H
+
+#include <linux/types.h>
+
+/* Avoid too many header ordering problems.  */
+struct siginfo;
+
+#ifndef __KERNEL__
+/* Here we must cater to libcs that poke about in kernel headers.  */
+
+#define NSIG           32
+typedef unsigned long sigset_t;
+
+#endif /* __KERNEL__ */
+
+#define SIGHUP          1
+#define SIGINT          2
+#define SIGQUIT                 3
+#define SIGILL          4
+#define SIGTRAP                 5
+#define SIGABRT                 6
+#define SIGIOT          6
+#define SIGBUS          7
+#define SIGFPE          8
+#define SIGKILL                 9
+#define SIGUSR1                10
+#define SIGSEGV                11
+#define SIGUSR2                12
+#define SIGPIPE                13
+#define SIGALRM                14
+#define SIGTERM                15
+#define SIGSTKFLT      16
+#define SIGCHLD                17
+#define SIGCONT                18
+#define SIGSTOP                19
+#define SIGTSTP                20
+#define SIGTTIN                21
+#define SIGTTOU                22
+#define SIGURG         23
+#define SIGXCPU                24
+#define SIGXFSZ                25
+#define SIGVTALRM      26
+#define SIGPROF                27
+#define SIGWINCH       28
+#define SIGIO          29
+#define SIGPOLL                SIGIO
+/*
+#define SIGLOST                29
+*/
+#define SIGPWR         30
+#define SIGSYS         31
+#define        SIGUNUSED       31
+
+/* These should not be considered constants from userland.  */
+#define SIGRTMIN       32
+#define SIGRTMAX       _NSIG
+
+/*
+ * SA_FLAGS values:
+ *
+ * SA_ONSTACK indicates that a registered stack_t will be used.
+ * SA_RESTART flag to get restarting signals (which were the default long ago)
+ * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
+ * SA_RESETHAND clears the handler when the signal is delivered.
+ * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
+ * SA_NODEFER prevents the current signal from being masked in the handler.
+ *
+ * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
+ * Unix names RESETHAND and NODEFER respectively.
+ */
+#define SA_NOCLDSTOP   0x00000001
+#define SA_NOCLDWAIT   0x00000002
+#define SA_SIGINFO     0x00000004
+#define SA_ONSTACK     0x08000000
+#define SA_RESTART     0x10000000
+#define SA_NODEFER     0x40000000
+#define SA_RESETHAND   0x80000000
+
+#define SA_NOMASK      SA_NODEFER
+#define SA_ONESHOT     SA_RESETHAND
+
+/*
+ * sigaltstack controls
+ */
+#define SS_ONSTACK     1
+#define SS_DISABLE     2
+
+#define MINSIGSTKSZ    2048
+#define SIGSTKSZ       8192
+
+#include <asm-generic/signal-defs.h>
+
+#ifndef __KERNEL__
+/* Here we must cater to libcs that poke about in kernel headers.  */
+
+struct sigaction {
+       union {
+         __sighandler_t _sa_handler;
+         void (*_sa_sigaction)(int, struct siginfo *, void *);
+       } _u;
+       sigset_t sa_mask;
+       unsigned long sa_flags;
+       void (*sa_restorer)(void);
+};
+
+#define sa_handler     _u._sa_handler
+#define sa_sigaction   _u._sa_sigaction
+
+#endif /* __KERNEL__ */
+
+typedef struct sigaltstack {
+       void __user *ss_sp;
+       int ss_flags;
+       size_t ss_size;
+} stack_t;
+
+#endif /* _UAPI_M68K_SIGNAL_H */
diff --git a/arch/m68k/include/uapi/asm/socket.h b/arch/m68k/include/uapi/asm/socket.h
new file mode 100644 (file)
index 0000000..d1be684
--- /dev/null
@@ -0,0 +1,72 @@
+#ifndef _ASM_SOCKET_H
+#define _ASM_SOCKET_H
+
+#include <asm/sockios.h>
+
+/* For setsockopt(2) */
+#define SOL_SOCKET     1
+
+#define SO_DEBUG       1
+#define SO_REUSEADDR   2
+#define SO_TYPE                3
+#define SO_ERROR       4
+#define SO_DONTROUTE   5
+#define SO_BROADCAST   6
+#define SO_SNDBUF      7
+#define SO_RCVBUF      8
+#define SO_SNDBUFFORCE 32
+#define SO_RCVBUFFORCE 33
+#define SO_KEEPALIVE   9
+#define SO_OOBINLINE   10
+#define SO_NO_CHECK    11
+#define SO_PRIORITY    12
+#define SO_LINGER      13
+#define SO_BSDCOMPAT   14
+/* To add :#define SO_REUSEPORT 15 */
+#define SO_PASSCRED    16
+#define SO_PEERCRED    17
+#define SO_RCVLOWAT    18
+#define SO_SNDLOWAT    19
+#define SO_RCVTIMEO    20
+#define SO_SNDTIMEO    21
+
+/* Security levels - as per NRL IPv6 - don't actually do anything */
+#define SO_SECURITY_AUTHENTICATION             22
+#define SO_SECURITY_ENCRYPTION_TRANSPORT       23
+#define SO_SECURITY_ENCRYPTION_NETWORK         24
+
+#define SO_BINDTODEVICE        25
+
+/* Socket filtering */
+#define SO_ATTACH_FILTER        26
+#define SO_DETACH_FILTER        27
+
+#define SO_PEERNAME             28
+#define SO_TIMESTAMP           29
+#define SCM_TIMESTAMP          SO_TIMESTAMP
+
+#define SO_ACCEPTCONN          30
+
+#define SO_PEERSEC             31
+#define SO_PASSSEC             34
+#define SO_TIMESTAMPNS         35
+#define SCM_TIMESTAMPNS                SO_TIMESTAMPNS
+
+#define SO_MARK                        36
+
+#define SO_TIMESTAMPING                37
+#define SCM_TIMESTAMPING       SO_TIMESTAMPING
+
+#define SO_PROTOCOL            38
+#define SO_DOMAIN              39
+
+#define SO_RXQ_OVFL             40
+
+#define SO_WIFI_STATUS         41
+#define SCM_WIFI_STATUS                SO_WIFI_STATUS
+#define SO_PEEK_OFF            42
+
+/* Instruct lower device to use last 4-bytes of skb data as FCS */
+#define SO_NOFCS               43
+
+#endif /* _ASM_SOCKET_H */
diff --git a/arch/m68k/include/uapi/asm/sockios.h b/arch/m68k/include/uapi/asm/sockios.h
new file mode 100644 (file)
index 0000000..c04a239
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef __ARCH_M68K_SOCKIOS__
+#define __ARCH_M68K_SOCKIOS__
+
+/* Socket-level I/O control calls. */
+#define FIOSETOWN      0x8901
+#define SIOCSPGRP      0x8902
+#define FIOGETOWN      0x8903
+#define SIOCGPGRP      0x8904
+#define SIOCATMARK     0x8905
+#define SIOCGSTAMP     0x8906          /* Get stamp (timeval) */
+#define SIOCGSTAMPNS   0x8907          /* Get stamp (timespec) */
+
+#endif /* __ARCH_M68K_SOCKIOS__ */
diff --git a/arch/m68k/include/uapi/asm/stat.h b/arch/m68k/include/uapi/asm/stat.h
new file mode 100644 (file)
index 0000000..dd38bc2
--- /dev/null
@@ -0,0 +1,77 @@
+#ifndef _M68K_STAT_H
+#define _M68K_STAT_H
+
+struct __old_kernel_stat {
+       unsigned short st_dev;
+       unsigned short st_ino;
+       unsigned short st_mode;
+       unsigned short st_nlink;
+       unsigned short st_uid;
+       unsigned short st_gid;
+       unsigned short st_rdev;
+       unsigned long  st_size;
+       unsigned long  st_atime;
+       unsigned long  st_mtime;
+       unsigned long  st_ctime;
+};
+
+struct stat {
+       unsigned short st_dev;
+       unsigned short __pad1;
+       unsigned long  st_ino;
+       unsigned short st_mode;
+       unsigned short st_nlink;
+       unsigned short st_uid;
+       unsigned short st_gid;
+       unsigned short st_rdev;
+       unsigned short __pad2;
+       unsigned long  st_size;
+       unsigned long  st_blksize;
+       unsigned long  st_blocks;
+       unsigned long  st_atime;
+       unsigned long  __unused1;
+       unsigned long  st_mtime;
+       unsigned long  __unused2;
+       unsigned long  st_ctime;
+       unsigned long  __unused3;
+       unsigned long  __unused4;
+       unsigned long  __unused5;
+};
+
+/* This matches struct stat64 in glibc2.1, hence the absolutely
+ * insane amounts of padding around dev_t's.
+ */
+struct stat64 {
+       unsigned long long      st_dev;
+       unsigned char   __pad1[2];
+
+#define STAT64_HAS_BROKEN_ST_INO       1
+       unsigned long   __st_ino;
+
+       unsigned int    st_mode;
+       unsigned int    st_nlink;
+
+       unsigned long   st_uid;
+       unsigned long   st_gid;
+
+       unsigned long long      st_rdev;
+       unsigned char   __pad3[2];
+
+       long long       st_size;
+       unsigned long   st_blksize;
+
+       unsigned long long      st_blocks;      /* Number 512-byte blocks allocated. */
+
+       unsigned long   st_atime;
+       unsigned long   st_atime_nsec;
+
+       unsigned long   st_mtime;
+       unsigned long   st_mtime_nsec;
+
+       unsigned long   st_ctime;
+       unsigned long   st_ctime_nsec;
+
+       unsigned long long      st_ino;
+};
+
+#endif /* _M68K_STAT_H */
diff --git a/arch/m68k/include/uapi/asm/swab.h b/arch/m68k/include/uapi/asm/swab.h
new file mode 100644 (file)
index 0000000..b7b37a4
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef _M68K_SWAB_H
+#define _M68K_SWAB_H
+
+#include <linux/types.h>
+#include <linux/compiler.h>
+
+#define __SWAB_64_THRU_32__
+
+#if defined (__mcfisaaplus__) || defined (__mcfisac__)
+static inline __attribute_const__ __u32 __arch_swab32(__u32 val)
+{
+       __asm__("byterev %0" : "=d" (val) : "0" (val));
+       return val;
+}
+
+#define __arch_swab32 __arch_swab32
+#elif !defined(__mcoldfire__)
+
+static inline __attribute_const__ __u32 __arch_swab32(__u32 val)
+{
+       __asm__("rolw #8,%0; swap %0; rolw #8,%0" : "=d" (val) : "0" (val));
+       return val;
+}
+#define __arch_swab32 __arch_swab32
+#endif
+
+#endif /* _M68K_SWAB_H */
diff --git a/arch/m68k/include/uapi/asm/termbits.h b/arch/m68k/include/uapi/asm/termbits.h
new file mode 100644 (file)
index 0000000..aea1e37
--- /dev/null
@@ -0,0 +1,201 @@
+#ifndef __ARCH_M68K_TERMBITS_H__
+#define __ARCH_M68K_TERMBITS_H__
+
+#include <linux/posix_types.h>
+
+typedef unsigned char  cc_t;
+typedef unsigned int   speed_t;
+typedef unsigned int   tcflag_t;
+
+#define NCCS 19
+struct termios {
+       tcflag_t c_iflag;               /* input mode flags */
+       tcflag_t c_oflag;               /* output mode flags */
+       tcflag_t c_cflag;               /* control mode flags */
+       tcflag_t c_lflag;               /* local mode flags */
+       cc_t c_line;                    /* line discipline */
+       cc_t c_cc[NCCS];                /* control characters */
+};
+
+struct termios2 {
+       tcflag_t c_iflag;               /* input mode flags */
+       tcflag_t c_oflag;               /* output mode flags */
+       tcflag_t c_cflag;               /* control mode flags */
+       tcflag_t c_lflag;               /* local mode flags */
+       cc_t c_line;                    /* line discipline */
+       cc_t c_cc[NCCS];                /* control characters */
+       speed_t c_ispeed;               /* input speed */
+       speed_t c_ospeed;               /* output speed */
+};
+
+struct ktermios {
+       tcflag_t c_iflag;               /* input mode flags */
+       tcflag_t c_oflag;               /* output mode flags */
+       tcflag_t c_cflag;               /* control mode flags */
+       tcflag_t c_lflag;               /* local mode flags */
+       cc_t c_line;                    /* line discipline */
+       cc_t c_cc[NCCS];                /* control characters */
+       speed_t c_ispeed;               /* input speed */
+       speed_t c_ospeed;               /* output speed */
+};
+
+/* c_cc characters */
+#define VINTR 0
+#define VQUIT 1
+#define VERASE 2
+#define VKILL 3
+#define VEOF 4
+#define VTIME 5
+#define VMIN 6
+#define VSWTC 7
+#define VSTART 8
+#define VSTOP 9
+#define VSUSP 10
+#define VEOL 11
+#define VREPRINT 12
+#define VDISCARD 13
+#define VWERASE 14
+#define VLNEXT 15
+#define VEOL2 16
+
+
+/* c_iflag bits */
+#define IGNBRK 0000001
+#define BRKINT 0000002
+#define IGNPAR 0000004
+#define PARMRK 0000010
+#define INPCK  0000020
+#define ISTRIP 0000040
+#define INLCR  0000100
+#define IGNCR  0000200
+#define ICRNL  0000400
+#define IUCLC  0001000
+#define IXON   0002000
+#define IXANY  0004000
+#define IXOFF  0010000
+#define IMAXBEL        0020000
+#define IUTF8  0040000
+
+/* c_oflag bits */
+#define OPOST  0000001
+#define OLCUC  0000002
+#define ONLCR  0000004
+#define OCRNL  0000010
+#define ONOCR  0000020
+#define ONLRET 0000040
+#define OFILL  0000100
+#define OFDEL  0000200
+#define NLDLY  0000400
+#define   NL0  0000000
+#define   NL1  0000400
+#define CRDLY  0003000
+#define   CR0  0000000
+#define   CR1  0001000
+#define   CR2  0002000
+#define   CR3  0003000
+#define TABDLY 0014000
+#define   TAB0 0000000
+#define   TAB1 0004000
+#define   TAB2 0010000
+#define   TAB3 0014000
+#define   XTABS        0014000
+#define BSDLY  0020000
+#define   BS0  0000000
+#define   BS1  0020000
+#define VTDLY  0040000
+#define   VT0  0000000
+#define   VT1  0040000
+#define FFDLY  0100000
+#define   FF0  0000000
+#define   FF1  0100000
+
+/* c_cflag bit meaning */
+#define CBAUD  0010017
+#define  B0    0000000         /* hang up */
+#define  B50   0000001
+#define  B75   0000002
+#define  B110  0000003
+#define  B134  0000004
+#define  B150  0000005
+#define  B200  0000006
+#define  B300  0000007
+#define  B600  0000010
+#define  B1200 0000011
+#define  B1800 0000012
+#define  B2400 0000013
+#define  B4800 0000014
+#define  B9600 0000015
+#define  B19200        0000016
+#define  B38400        0000017
+#define EXTA B19200
+#define EXTB B38400
+#define CSIZE  0000060
+#define   CS5  0000000
+#define   CS6  0000020
+#define   CS7  0000040
+#define   CS8  0000060
+#define CSTOPB 0000100
+#define CREAD  0000200
+#define PARENB 0000400
+#define PARODD 0001000
+#define HUPCL  0002000
+#define CLOCAL 0004000
+#define CBAUDEX 0010000
+#define    BOTHER 0010000
+#define    B57600 0010001
+#define   B115200 0010002
+#define   B230400 0010003
+#define   B460800 0010004
+#define   B500000 0010005
+#define   B576000 0010006
+#define   B921600 0010007
+#define  B1000000 0010010
+#define  B1152000 0010011
+#define  B1500000 0010012
+#define  B2000000 0010013
+#define  B2500000 0010014
+#define  B3000000 0010015
+#define  B3500000 0010016
+#define  B4000000 0010017
+#define CIBAUD   002003600000          /* input baud rate */
+#define CMSPAR   010000000000          /* mark or space (stick) parity */
+#define CRTSCTS          020000000000          /* flow control */
+
+#define IBSHIFT        16                      /* Shift from CBAUD to CIBAUD */
+
+/* c_lflag bits */
+#define ISIG   0000001
+#define ICANON 0000002
+#define XCASE  0000004
+#define ECHO   0000010
+#define ECHOE  0000020
+#define ECHOK  0000040
+#define ECHONL 0000100
+#define NOFLSH 0000200
+#define TOSTOP 0000400
+#define ECHOCTL        0001000
+#define ECHOPRT        0002000
+#define ECHOKE 0004000
+#define FLUSHO 0010000
+#define PENDIN 0040000
+#define IEXTEN 0100000
+#define EXTPROC        0200000
+
+
+/* tcflow() and TCXONC use these */
+#define        TCOOFF          0
+#define        TCOON           1
+#define        TCIOFF          2
+#define        TCION           3
+
+/* tcflush() and TCFLSH use these */
+#define        TCIFLUSH        0
+#define        TCOFLUSH        1
+#define        TCIOFLUSH       2
+
+/* tcsetattr uses these */
+#define        TCSANOW         0
+#define        TCSADRAIN       1
+#define        TCSAFLUSH       2
+
+#endif /* __ARCH_M68K_TERMBITS_H__ */
diff --git a/arch/m68k/include/uapi/asm/termios.h b/arch/m68k/include/uapi/asm/termios.h
new file mode 100644 (file)
index 0000000..ce2142c
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef _UAPI_M68K_TERMIOS_H
+#define _UAPI_M68K_TERMIOS_H
+
+#include <asm/termbits.h>
+#include <asm/ioctls.h>
+
+struct winsize {
+       unsigned short ws_row;
+       unsigned short ws_col;
+       unsigned short ws_xpixel;
+       unsigned short ws_ypixel;
+};
+
+#define NCC 8
+struct termio {
+       unsigned short c_iflag;         /* input mode flags */
+       unsigned short c_oflag;         /* output mode flags */
+       unsigned short c_cflag;         /* control mode flags */
+       unsigned short c_lflag;         /* local mode flags */
+       unsigned char c_line;           /* line discipline */
+       unsigned char c_cc[NCC];        /* control characters */
+};
+
+
+/* modem lines */
+#define TIOCM_LE       0x001
+#define TIOCM_DTR      0x002
+#define TIOCM_RTS      0x004
+#define TIOCM_ST       0x008
+#define TIOCM_SR       0x010
+#define TIOCM_CTS      0x020
+#define TIOCM_CAR      0x040
+#define TIOCM_RNG      0x080
+#define TIOCM_DSR      0x100
+#define TIOCM_CD       TIOCM_CAR
+#define TIOCM_RI       TIOCM_RNG
+#define TIOCM_OUT1     0x2000
+#define TIOCM_OUT2     0x4000
+#define TIOCM_LOOP     0x8000
+
+/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
+
+
+#endif /* _UAPI_M68K_TERMIOS_H */
diff --git a/arch/m68k/include/uapi/asm/unistd.h b/arch/m68k/include/uapi/asm/unistd.h
new file mode 100644 (file)
index 0000000..b94bfbf
--- /dev/null
@@ -0,0 +1,357 @@
+#ifndef _UAPI_ASM_M68K_UNISTD_H_
+#define _UAPI_ASM_M68K_UNISTD_H_
+
+/*
+ * This file contains the system call numbers.
+ */
+
+#define __NR_restart_syscall     0
+#define __NR_exit                1
+#define __NR_fork                2
+#define __NR_read                3
+#define __NR_write               4
+#define __NR_open                5
+#define __NR_close               6
+#define __NR_waitpid             7
+#define __NR_creat               8
+#define __NR_link                9
+#define __NR_unlink             10
+#define __NR_execve             11
+#define __NR_chdir              12
+#define __NR_time               13
+#define __NR_mknod              14
+#define __NR_chmod              15
+#define __NR_chown              16
+/*#define __NR_break            17*/
+#define __NR_oldstat            18
+#define __NR_lseek              19
+#define __NR_getpid             20
+#define __NR_mount              21
+#define __NR_umount             22
+#define __NR_setuid             23
+#define __NR_getuid             24
+#define __NR_stime              25
+#define __NR_ptrace             26
+#define __NR_alarm              27
+#define __NR_oldfstat           28
+#define __NR_pause              29
+#define __NR_utime              30
+/*#define __NR_stty             31*/
+/*#define __NR_gtty             32*/
+#define __NR_access             33
+#define __NR_nice               34
+/*#define __NR_ftime            35*/
+#define __NR_sync               36
+#define __NR_kill               37
+#define __NR_rename             38
+#define __NR_mkdir              39
+#define __NR_rmdir              40
+#define __NR_dup                41
+#define __NR_pipe               42
+#define __NR_times              43
+/*#define __NR_prof             44*/
+#define __NR_brk                45
+#define __NR_setgid             46
+#define __NR_getgid             47
+#define __NR_signal             48
+#define __NR_geteuid            49
+#define __NR_getegid            50
+#define __NR_acct               51
+#define __NR_umount2            52
+/*#define __NR_lock             53*/
+#define __NR_ioctl              54
+#define __NR_fcntl              55
+/*#define __NR_mpx              56*/
+#define __NR_setpgid            57
+/*#define __NR_ulimit           58*/
+/*#define __NR_oldolduname      59*/
+#define __NR_umask              60
+#define __NR_chroot             61
+#define __NR_ustat              62
+#define __NR_dup2               63
+#define __NR_getppid            64
+#define __NR_getpgrp            65
+#define __NR_setsid             66
+#define __NR_sigaction          67
+#define __NR_sgetmask           68
+#define __NR_ssetmask           69
+#define __NR_setreuid           70
+#define __NR_setregid           71
+#define __NR_sigsuspend                 72
+#define __NR_sigpending                 73
+#define __NR_sethostname        74
+#define __NR_setrlimit          75
+#define __NR_getrlimit          76
+#define __NR_getrusage          77
+#define __NR_gettimeofday       78
+#define __NR_settimeofday       79
+#define __NR_getgroups          80
+#define __NR_setgroups          81
+#define __NR_select             82
+#define __NR_symlink            83
+#define __NR_oldlstat           84
+#define __NR_readlink           85
+#define __NR_uselib             86
+#define __NR_swapon             87
+#define __NR_reboot             88
+#define __NR_readdir            89
+#define __NR_mmap               90
+#define __NR_munmap             91
+#define __NR_truncate           92
+#define __NR_ftruncate          93
+#define __NR_fchmod             94
+#define __NR_fchown             95
+#define __NR_getpriority        96
+#define __NR_setpriority        97
+/*#define __NR_profil           98*/
+#define __NR_statfs             99
+#define __NR_fstatfs           100
+/*#define __NR_ioperm          101*/
+#define __NR_socketcall                102
+#define __NR_syslog            103
+#define __NR_setitimer         104
+#define __NR_getitimer         105
+#define __NR_stat              106
+#define __NR_lstat             107
+#define __NR_fstat             108
+/*#define __NR_olduname                109*/
+/*#define __NR_iopl            110*/ /* not supported */
+#define __NR_vhangup           111
+/*#define __NR_idle            112*/ /* Obsolete */
+/*#define __NR_vm86            113*/ /* not supported */
+#define __NR_wait4             114
+#define __NR_swapoff           115
+#define __NR_sysinfo           116
+#define __NR_ipc               117
+#define __NR_fsync             118
+#define __NR_sigreturn         119
+#define __NR_clone             120
+#define __NR_setdomainname     121
+#define __NR_uname             122
+#define __NR_cacheflush                123
+#define __NR_adjtimex          124
+#define __NR_mprotect          125
+#define __NR_sigprocmask       126
+#define __NR_create_module     127
+#define __NR_init_module       128
+#define __NR_delete_module     129
+#define __NR_get_kernel_syms   130
+#define __NR_quotactl          131
+#define __NR_getpgid           132
+#define __NR_fchdir            133
+#define __NR_bdflush           134
+#define __NR_sysfs             135
+#define __NR_personality       136
+/*#define __NR_afs_syscall     137*/ /* Syscall for Andrew File System */
+#define __NR_setfsuid          138
+#define __NR_setfsgid          139
+#define __NR__llseek           140
+#define __NR_getdents          141
+#define __NR__newselect                142
+#define __NR_flock             143
+#define __NR_msync             144
+#define __NR_readv             145
+#define __NR_writev            146
+#define __NR_getsid            147
+#define __NR_fdatasync         148
+#define __NR__sysctl           149
+#define __NR_mlock             150
+#define __NR_munlock           151
+#define __NR_mlockall          152
+#define __NR_munlockall                153
+#define __NR_sched_setparam            154
+#define __NR_sched_getparam            155
+#define __NR_sched_setscheduler                156
+#define __NR_sched_getscheduler                157
+#define __NR_sched_yield               158
+#define __NR_sched_get_priority_max    159
+#define __NR_sched_get_priority_min    160
+#define __NR_sched_rr_get_interval     161
+#define __NR_nanosleep         162
+#define __NR_mremap            163
+#define __NR_setresuid         164
+#define __NR_getresuid         165
+#define __NR_getpagesize       166
+#define __NR_query_module      167
+#define __NR_poll              168
+#define __NR_nfsservctl                169
+#define __NR_setresgid         170
+#define __NR_getresgid         171
+#define __NR_prctl             172
+#define __NR_rt_sigreturn      173
+#define __NR_rt_sigaction      174
+#define __NR_rt_sigprocmask    175
+#define __NR_rt_sigpending     176
+#define __NR_rt_sigtimedwait   177
+#define __NR_rt_sigqueueinfo   178
+#define __NR_rt_sigsuspend     179
+#define __NR_pread64           180
+#define __NR_pwrite64          181
+#define __NR_lchown            182
+#define __NR_getcwd            183
+#define __NR_capget            184
+#define __NR_capset            185
+#define __NR_sigaltstack       186
+#define __NR_sendfile          187
+#define __NR_getpmsg           188     /* some people actually want streams */
+#define __NR_putpmsg           189     /* some people actually want streams */
+#define __NR_vfork             190
+#define __NR_ugetrlimit                191
+#define __NR_mmap2             192
+#define __NR_truncate64                193
+#define __NR_ftruncate64       194
+#define __NR_stat64            195
+#define __NR_lstat64           196
+#define __NR_fstat64           197
+#define __NR_chown32           198
+#define __NR_getuid32          199
+#define __NR_getgid32          200
+#define __NR_geteuid32         201
+#define __NR_getegid32         202
+#define __NR_setreuid32                203
+#define __NR_setregid32                204
+#define __NR_getgroups32       205
+#define __NR_setgroups32       206
+#define __NR_fchown32          207
+#define __NR_setresuid32       208
+#define __NR_getresuid32       209
+#define __NR_setresgid32       210
+#define __NR_getresgid32       211
+#define __NR_lchown32          212
+#define __NR_setuid32          213
+#define __NR_setgid32          214
+#define __NR_setfsuid32                215
+#define __NR_setfsgid32                216
+#define __NR_pivot_root                217
+/* 218*/
+/* 219*/
+#define __NR_getdents64                220
+#define __NR_gettid            221
+#define __NR_tkill             222
+#define __NR_setxattr          223
+#define __NR_lsetxattr         224
+#define __NR_fsetxattr         225
+#define __NR_getxattr          226
+#define __NR_lgetxattr         227
+#define __NR_fgetxattr         228
+#define __NR_listxattr         229
+#define __NR_llistxattr                230
+#define __NR_flistxattr                231
+#define __NR_removexattr       232
+#define __NR_lremovexattr      233
+#define __NR_fremovexattr      234
+#define __NR_futex             235
+#define __NR_sendfile64                236
+#define __NR_mincore           237
+#define __NR_madvise           238
+#define __NR_fcntl64           239
+#define __NR_readahead         240
+#define __NR_io_setup          241
+#define __NR_io_destroy                242
+#define __NR_io_getevents      243
+#define __NR_io_submit         244
+#define __NR_io_cancel         245
+#define __NR_fadvise64         246
+#define __NR_exit_group                247
+#define __NR_lookup_dcookie    248
+#define __NR_epoll_create      249
+#define __NR_epoll_ctl         250
+#define __NR_epoll_wait                251
+#define __NR_remap_file_pages  252
+#define __NR_set_tid_address   253
+#define __NR_timer_create      254
+#define __NR_timer_settime     255
+#define __NR_timer_gettime     256
+#define __NR_timer_getoverrun  257
+#define __NR_timer_delete      258
+#define __NR_clock_settime     259
+#define __NR_clock_gettime     260
+#define __NR_clock_getres      261
+#define __NR_clock_nanosleep   262
+#define __NR_statfs64          263
+#define __NR_fstatfs64         264
+#define __NR_tgkill            265
+#define __NR_utimes            266
+#define __NR_fadvise64_64      267
+#define __NR_mbind             268
+#define __NR_get_mempolicy     269
+#define __NR_set_mempolicy     270
+#define __NR_mq_open           271
+#define __NR_mq_unlink         272
+#define __NR_mq_timedsend      273
+#define __NR_mq_timedreceive   274
+#define __NR_mq_notify         275
+#define __NR_mq_getsetattr     276
+#define __NR_waitid            277
+/*#define __NR_vserver         278*/
+#define __NR_add_key           279
+#define __NR_request_key       280
+#define __NR_keyctl            281
+#define __NR_ioprio_set                282
+#define __NR_ioprio_get                283
+#define __NR_inotify_init      284
+#define __NR_inotify_add_watch 285
+#define __NR_inotify_rm_watch  286
+#define __NR_migrate_pages     287
+#define __NR_openat            288
+#define __NR_mkdirat           289
+#define __NR_mknodat           290
+#define __NR_fchownat          291
+#define __NR_futimesat         292
+#define __NR_fstatat64         293
+#define __NR_unlinkat          294
+#define __NR_renameat          295
+#define __NR_linkat            296
+#define __NR_symlinkat         297
+#define __NR_readlinkat                298
+#define __NR_fchmodat          299
+#define __NR_faccessat         300
+#define __NR_pselect6          301
+#define __NR_ppoll             302
+#define __NR_unshare           303
+#define __NR_set_robust_list   304
+#define __NR_get_robust_list   305
+#define __NR_splice            306
+#define __NR_sync_file_range   307
+#define __NR_tee               308
+#define __NR_vmsplice          309
+#define __NR_move_pages                310
+#define __NR_sched_setaffinity 311
+#define __NR_sched_getaffinity 312
+#define __NR_kexec_load                313
+#define __NR_getcpu            314
+#define __NR_epoll_pwait       315
+#define __NR_utimensat         316
+#define __NR_signalfd          317
+#define __NR_timerfd_create    318
+#define __NR_eventfd           319
+#define __NR_fallocate         320
+#define __NR_timerfd_settime   321
+#define __NR_timerfd_gettime   322
+#define __NR_signalfd4         323
+#define __NR_eventfd2          324
+#define __NR_epoll_create1     325
+#define __NR_dup3              326
+#define __NR_pipe2             327
+#define __NR_inotify_init1     328
+#define __NR_preadv            329
+#define __NR_pwritev           330
+#define __NR_rt_tgsigqueueinfo 331
+#define __NR_perf_event_open   332
+#define __NR_get_thread_area   333
+#define __NR_set_thread_area   334
+#define __NR_atomic_cmpxchg_32 335
+#define __NR_atomic_barrier    336
+#define __NR_fanotify_init     337
+#define __NR_fanotify_mark     338
+#define __NR_prlimit64         339
+#define __NR_name_to_handle_at 340
+#define __NR_open_by_handle_at 341
+#define __NR_clock_adjtime     342
+#define __NR_syncfs            343
+#define __NR_setns             344
+#define __NR_process_vm_readv  345
+#define __NR_process_vm_writev 346
+#define __NR_kcmp              347
+
+#endif /* _UAPI_ASM_M68K_UNISTD_H_ */
index ce827b376110a6a815b4ccece0a066e5ad66cc59..4fc2e29b771b51eb2e2189a4c050c5e05510bc2b 100644 (file)
@@ -367,4 +367,5 @@ ENTRY(sys_call_table)
        .long sys_setns
        .long sys_process_vm_readv      /* 345 */
        .long sys_process_vm_writev
+       .long sys_kcmp
 
index d38246e33ddb9f1eacb7f885f809db54057c5203..9f883bf769530d18c880416850060cd738bb0fa8 100644 (file)
@@ -30,6 +30,7 @@
  * measurement, and debugging facilities.
  */
 
+#include <linux/irqflags.h>
 #include <asm/octeon/cvmx.h>
 #include <asm/octeon/cvmx-l2c.h>
 #include <asm/octeon/cvmx-spinlock.h>
index 7cf80ca2c1d2117c239ba574406c6814ecb91961..f9f5307434c276a35624f5c137333867e2357794 100644 (file)
@@ -11,6 +11,7 @@
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/irqflags.h>
 
 #include <asm/bcache.h>
 
index 82ad35ce2b45d975705e90a90db8cf82b7189255..46ac73abd5ee950b2bd14e57ad07d1b08ff7e010 100644 (file)
@@ -14,7 +14,6 @@
 #endif
 
 #include <linux/compiler.h>
-#include <linux/irqflags.h>
 #include <linux/types.h>
 #include <asm/barrier.h>
 #include <asm/byteorder.h>             /* sigh ... */
 #define smp_mb__before_clear_bit()     smp_mb__before_llsc()
 #define smp_mb__after_clear_bit()      smp_llsc_mb()
 
+
+/*
+ * These are the "slower" versions of the functions and are in bitops.c.
+ * These functions call raw_local_irq_{save,restore}().
+ */
+void __mips_set_bit(unsigned long nr, volatile unsigned long *addr);
+void __mips_clear_bit(unsigned long nr, volatile unsigned long *addr);
+void __mips_change_bit(unsigned long nr, volatile unsigned long *addr);
+int __mips_test_and_set_bit(unsigned long nr,
+                           volatile unsigned long *addr);
+int __mips_test_and_set_bit_lock(unsigned long nr,
+                                volatile unsigned long *addr);
+int __mips_test_and_clear_bit(unsigned long nr,
+                             volatile unsigned long *addr);
+int __mips_test_and_change_bit(unsigned long nr,
+                              volatile unsigned long *addr);
+
+
 /*
  * set_bit - Atomically set a bit in memory
  * @nr: the bit to set
@@ -57,7 +74,7 @@
 static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
 {
        unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
-       unsigned short bit = nr & SZLONG_MASK;
+       int bit = nr & SZLONG_MASK;
        unsigned long temp;
 
        if (kernel_uses_llsc && R10000_LLSC_WAR) {
@@ -92,17 +109,8 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
                        : "=&r" (temp), "+m" (*m)
                        : "ir" (1UL << bit));
                } while (unlikely(!temp));
-       } else {
-               volatile unsigned long *a = addr;
-               unsigned long mask;
-               unsigned long flags;
-
-               a += nr >> SZLONG_LOG;
-               mask = 1UL << bit;
-               raw_local_irq_save(flags);
-               *a |= mask;
-               raw_local_irq_restore(flags);
-       }
+       } else
+               __mips_set_bit(nr, addr);
 }
 
 /*
@@ -118,7 +126,7 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
 static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
 {
        unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
-       unsigned short bit = nr & SZLONG_MASK;
+       int bit = nr & SZLONG_MASK;
        unsigned long temp;
 
        if (kernel_uses_llsc && R10000_LLSC_WAR) {
@@ -153,17 +161,8 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
                        : "=&r" (temp), "+m" (*m)
                        : "ir" (~(1UL << bit)));
                } while (unlikely(!temp));
-       } else {
-               volatile unsigned long *a = addr;
-               unsigned long mask;
-               unsigned long flags;
-
-               a += nr >> SZLONG_LOG;
-               mask = 1UL << bit;
-               raw_local_irq_save(flags);
-               *a &= ~mask;
-               raw_local_irq_restore(flags);
-       }
+       } else
+               __mips_clear_bit(nr, addr);
 }
 
 /*
@@ -191,7 +190,7 @@ static inline void clear_bit_unlock(unsigned long nr, volatile unsigned long *ad
  */
 static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
 {
-       unsigned short bit = nr & SZLONG_MASK;
+       int bit = nr & SZLONG_MASK;
 
        if (kernel_uses_llsc && R10000_LLSC_WAR) {
                unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
@@ -220,17 +219,8 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
                        : "=&r" (temp), "+m" (*m)
                        : "ir" (1UL << bit));
                } while (unlikely(!temp));
-       } else {
-               volatile unsigned long *a = addr;
-               unsigned long mask;
-               unsigned long flags;
-
-               a += nr >> SZLONG_LOG;
-               mask = 1UL << bit;
-               raw_local_irq_save(flags);
-               *a ^= mask;
-               raw_local_irq_restore(flags);
-       }
+       } else
+               __mips_change_bit(nr, addr);
 }
 
 /*
@@ -244,7 +234,7 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
 static inline int test_and_set_bit(unsigned long nr,
        volatile unsigned long *addr)
 {
-       unsigned short bit = nr & SZLONG_MASK;
+       int bit = nr & SZLONG_MASK;
        unsigned long res;
 
        smp_mb__before_llsc();
@@ -281,18 +271,8 @@ static inline int test_and_set_bit(unsigned long nr,
                } while (unlikely(!res));
 
                res = temp & (1UL << bit);
-       } else {
-               volatile unsigned long *a = addr;
-               unsigned long mask;
-               unsigned long flags;
-
-               a += nr >> SZLONG_LOG;
-               mask = 1UL << bit;
-               raw_local_irq_save(flags);
-               res = (mask & *a);
-               *a |= mask;
-               raw_local_irq_restore(flags);
-       }
+       } else
+               res = __mips_test_and_set_bit(nr, addr);
 
        smp_llsc_mb();
 
@@ -310,7 +290,7 @@ static inline int test_and_set_bit(unsigned long nr,
 static inline int test_and_set_bit_lock(unsigned long nr,
        volatile unsigned long *addr)
 {
-       unsigned short bit = nr & SZLONG_MASK;
+       int bit = nr & SZLONG_MASK;
        unsigned long res;
 
        if (kernel_uses_llsc && R10000_LLSC_WAR) {
@@ -345,18 +325,8 @@ static inline int test_and_set_bit_lock(unsigned long nr,
                } while (unlikely(!res));
 
                res = temp & (1UL << bit);
-       } else {
-               volatile unsigned long *a = addr;
-               unsigned long mask;
-               unsigned long flags;
-
-               a += nr >> SZLONG_LOG;
-               mask = 1UL << bit;
-               raw_local_irq_save(flags);
-               res = (mask & *a);
-               *a |= mask;
-               raw_local_irq_restore(flags);
-       }
+       } else
+               res = __mips_test_and_set_bit_lock(nr, addr);
 
        smp_llsc_mb();
 
@@ -373,7 +343,7 @@ static inline int test_and_set_bit_lock(unsigned long nr,
 static inline int test_and_clear_bit(unsigned long nr,
        volatile unsigned long *addr)
 {
-       unsigned short bit = nr & SZLONG_MASK;
+       int bit = nr & SZLONG_MASK;
        unsigned long res;
 
        smp_mb__before_llsc();
@@ -428,18 +398,8 @@ static inline int test_and_clear_bit(unsigned long nr,
                } while (unlikely(!res));
 
                res = temp & (1UL << bit);
-       } else {
-               volatile unsigned long *a = addr;
-               unsigned long mask;
-               unsigned long flags;
-
-               a += nr >> SZLONG_LOG;
-               mask = 1UL << bit;
-               raw_local_irq_save(flags);
-               res = (mask & *a);
-               *a &= ~mask;
-               raw_local_irq_restore(flags);
-       }
+       } else
+               res = __mips_test_and_clear_bit(nr, addr);
 
        smp_llsc_mb();
 
@@ -457,7 +417,7 @@ static inline int test_and_clear_bit(unsigned long nr,
 static inline int test_and_change_bit(unsigned long nr,
        volatile unsigned long *addr)
 {
-       unsigned short bit = nr & SZLONG_MASK;
+       int bit = nr & SZLONG_MASK;
        unsigned long res;
 
        smp_mb__before_llsc();
@@ -494,18 +454,8 @@ static inline int test_and_change_bit(unsigned long nr,
                } while (unlikely(!res));
 
                res = temp & (1UL << bit);
-       } else {
-               volatile unsigned long *a = addr;
-               unsigned long mask;
-               unsigned long flags;
-
-               a += nr >> SZLONG_LOG;
-               mask = 1UL << bit;
-               raw_local_irq_save(flags);
-               res = (mask & *a);
-               *a ^= mask;
-               raw_local_irq_restore(flags);
-       }
+       } else
+               res = __mips_test_and_change_bit(nr, addr);
 
        smp_llsc_mb();
 
index 58277e0e9cd4075e001f79e48fcaaf928dd53064..3c5d1464b7bde4d93f5d4345fbedd31ccda7e47a 100644 (file)
@@ -290,7 +290,7 @@ struct compat_shmid64_ds {
 
 static inline int is_compat_task(void)
 {
-       return test_thread_flag(TIF_32BIT);
+       return test_thread_flag(TIF_32BIT_ADDR);
 }
 
 #endif /* _ASM_COMPAT_H */
index 29d9c23c20c72d87f847f28772666448cdd2711a..ff2e0345e0132744eb57fcfc12969c950bc97bf0 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/compiler.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
+#include <linux/irqflags.h>
 
 #include <asm/addrspace.h>
 #include <asm/bug.h>
index 309cbcd6909cd808b92941e53deea0e3e3a5a756..9f3384c789d7bfdff5511706b0dffc3d2962c96c 100644 (file)
 #include <linux/compiler.h>
 #include <asm/hazards.h>
 
-__asm__(
-       "       .macro  arch_local_irq_enable                           \n"
-       "       .set    push                                            \n"
-       "       .set    reorder                                         \n"
-       "       .set    noat                                            \n"
-#ifdef CONFIG_MIPS_MT_SMTC
-       "       mfc0    $1, $2, 1       # SMTC - clear TCStatus.IXMT    \n"
-       "       ori     $1, 0x400                                       \n"
-       "       xori    $1, 0x400                                       \n"
-       "       mtc0    $1, $2, 1                                       \n"
-#elif defined(CONFIG_CPU_MIPSR2)
-       "       ei                                                      \n"
-#else
-       "       mfc0    $1,$12                                          \n"
-       "       ori     $1,0x1f                                         \n"
-       "       xori    $1,0x1e                                         \n"
-       "       mtc0    $1,$12                                          \n"
-#endif
-       "       irq_enable_hazard                                       \n"
-       "       .set    pop                                             \n"
-       "       .endm");
+#if defined(CONFIG_CPU_MIPSR2) && !defined(CONFIG_MIPS_MT_SMTC)
 
-extern void smtc_ipi_replay(void);
-
-static inline void arch_local_irq_enable(void)
-{
-#ifdef CONFIG_MIPS_MT_SMTC
-       /*
-        * SMTC kernel needs to do a software replay of queued
-        * IPIs, at the cost of call overhead on each local_irq_enable()
-        */
-       smtc_ipi_replay();
-#endif
-       __asm__ __volatile__(
-               "arch_local_irq_enable"
-               : /* no outputs */
-               : /* no inputs */
-               : "memory");
-}
-
-
-/*
- * For cli() we have to insert nops to make sure that the new value
- * has actually arrived in the status register before the end of this
- * macro.
- * R4000/R4400 need three nops, the R4600 two nops and the R10000 needs
- * no nops at all.
- */
-/*
- * For TX49, operating only IE bit is not enough.
- *
- * If mfc0 $12 follows store and the mfc0 is last instruction of a
- * page and fetching the next instruction causes TLB miss, the result
- * of the mfc0 might wrongly contain EXL bit.
- *
- * ERT-TX49H2-027, ERT-TX49H3-012, ERT-TX49HL3-006, ERT-TX49H4-008
- *
- * Workaround: mask EXL bit of the result or place a nop before mfc0.
- */
 __asm__(
        "       .macro  arch_local_irq_disable\n"
        "       .set    push                                            \n"
        "       .set    noat                                            \n"
-#ifdef CONFIG_MIPS_MT_SMTC
-       "       mfc0    $1, $2, 1                                       \n"
-       "       ori     $1, 0x400                                       \n"
-       "       .set    noreorder                                       \n"
-       "       mtc0    $1, $2, 1                                       \n"
-#elif defined(CONFIG_CPU_MIPSR2)
        "       di                                                      \n"
-#else
-       "       mfc0    $1,$12                                          \n"
-       "       ori     $1,0x1f                                         \n"
-       "       xori    $1,0x1f                                         \n"
-       "       .set    noreorder                                       \n"
-       "       mtc0    $1,$12                                          \n"
-#endif
        "       irq_disable_hazard                                      \n"
        "       .set    pop                                             \n"
        "       .endm                                                   \n");
@@ -106,46 +36,14 @@ static inline void arch_local_irq_disable(void)
                : "memory");
 }
 
-__asm__(
-       "       .macro  arch_local_save_flags flags                     \n"
-       "       .set    push                                            \n"
-       "       .set    reorder                                         \n"
-#ifdef CONFIG_MIPS_MT_SMTC
-       "       mfc0    \\flags, $2, 1                                  \n"
-#else
-       "       mfc0    \\flags, $12                                    \n"
-#endif
-       "       .set    pop                                             \n"
-       "       .endm                                                   \n");
-
-static inline unsigned long arch_local_save_flags(void)
-{
-       unsigned long flags;
-       asm volatile("arch_local_save_flags %0" : "=r" (flags));
-       return flags;
-}
 
 __asm__(
        "       .macro  arch_local_irq_save result                      \n"
        "       .set    push                                            \n"
        "       .set    reorder                                         \n"
        "       .set    noat                                            \n"
-#ifdef CONFIG_MIPS_MT_SMTC
-       "       mfc0    \\result, $2, 1                                 \n"
-       "       ori     $1, \\result, 0x400                             \n"
-       "       .set    noreorder                                       \n"
-       "       mtc0    $1, $2, 1                                       \n"
-       "       andi    \\result, \\result, 0x400                       \n"
-#elif defined(CONFIG_CPU_MIPSR2)
        "       di      \\result                                        \n"
        "       andi    \\result, 1                                     \n"
-#else
-       "       mfc0    \\result, $12                                   \n"
-       "       ori     $1, \\result, 0x1f                              \n"
-       "       xori    $1, 0x1f                                        \n"
-       "       .set    noreorder                                       \n"
-       "       mtc0    $1, $12                                         \n"
-#endif
        "       irq_disable_hazard                                      \n"
        "       .set    pop                                             \n"
        "       .endm                                                   \n");
@@ -160,61 +58,37 @@ static inline unsigned long arch_local_irq_save(void)
        return flags;
 }
 
+
 __asm__(
        "       .macro  arch_local_irq_restore flags                    \n"
        "       .set    push                                            \n"
        "       .set    noreorder                                       \n"
        "       .set    noat                                            \n"
-#ifdef CONFIG_MIPS_MT_SMTC
-       "mfc0   $1, $2, 1                                               \n"
-       "andi   \\flags, 0x400                                          \n"
-       "ori    $1, 0x400                                               \n"
-       "xori   $1, 0x400                                               \n"
-       "or     \\flags, $1                                             \n"
-       "mtc0   \\flags, $2, 1                                          \n"
-#elif defined(CONFIG_CPU_MIPSR2) && defined(CONFIG_IRQ_CPU)
+#if defined(CONFIG_IRQ_CPU)
        /*
         * Slow, but doesn't suffer from a relatively unlikely race
         * condition we're having since days 1.
         */
        "       beqz    \\flags, 1f                                     \n"
-       "        di                                                     \n"
+       "       di                                                      \n"
        "       ei                                                      \n"
        "1:                                                             \n"
-#elif defined(CONFIG_CPU_MIPSR2)
+#else
        /*
         * Fast, dangerous.  Life is fun, life is good.
         */
        "       mfc0    $1, $12                                         \n"
        "       ins     $1, \\flags, 0, 1                               \n"
        "       mtc0    $1, $12                                         \n"
-#else
-       "       mfc0    $1, $12                                         \n"
-       "       andi    \\flags, 1                                      \n"
-       "       ori     $1, 0x1f                                        \n"
-       "       xori    $1, 0x1f                                        \n"
-       "       or      \\flags, $1                                     \n"
-       "       mtc0    \\flags, $12                                    \n"
 #endif
        "       irq_disable_hazard                                      \n"
        "       .set    pop                                             \n"
        "       .endm                                                   \n");
 
-
 static inline void arch_local_irq_restore(unsigned long flags)
 {
        unsigned long __tmp1;
 
-#ifdef CONFIG_MIPS_MT_SMTC
-       /*
-        * SMTC kernel needs to do a software replay of queued
-        * IPIs, at the cost of branch and call overhead on each
-        * local_irq_restore()
-        */
-       if (unlikely(!(flags & 0x0400)))
-               smtc_ipi_replay();
-#endif
-
        __asm__ __volatile__(
                "arch_local_irq_restore\t%0"
                : "=r" (__tmp1)
@@ -232,6 +106,75 @@ static inline void __arch_local_irq_restore(unsigned long flags)
                : "0" (flags)
                : "memory");
 }
+#else
+/* Functions that require preempt_{dis,en}able() are in mips-atomic.c */
+void arch_local_irq_disable(void);
+unsigned long arch_local_irq_save(void);
+void arch_local_irq_restore(unsigned long flags);
+void __arch_local_irq_restore(unsigned long flags);
+#endif /* if defined(CONFIG_CPU_MIPSR2) && !defined(CONFIG_MIPS_MT_SMTC) */
+
+
+__asm__(
+       "       .macro  arch_local_irq_enable                           \n"
+       "       .set    push                                            \n"
+       "       .set    reorder                                         \n"
+       "       .set    noat                                            \n"
+#ifdef CONFIG_MIPS_MT_SMTC
+       "       mfc0    $1, $2, 1       # SMTC - clear TCStatus.IXMT    \n"
+       "       ori     $1, 0x400                                       \n"
+       "       xori    $1, 0x400                                       \n"
+       "       mtc0    $1, $2, 1                                       \n"
+#elif defined(CONFIG_CPU_MIPSR2)
+       "       ei                                                      \n"
+#else
+       "       mfc0    $1,$12                                          \n"
+       "       ori     $1,0x1f                                         \n"
+       "       xori    $1,0x1e                                         \n"
+       "       mtc0    $1,$12                                          \n"
+#endif
+       "       irq_enable_hazard                                       \n"
+       "       .set    pop                                             \n"
+       "       .endm");
+
+extern void smtc_ipi_replay(void);
+
+static inline void arch_local_irq_enable(void)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+       /*
+        * SMTC kernel needs to do a software replay of queued
+        * IPIs, at the cost of call overhead on each local_irq_enable()
+        */
+       smtc_ipi_replay();
+#endif
+       __asm__ __volatile__(
+               "arch_local_irq_enable"
+               : /* no outputs */
+               : /* no inputs */
+               : "memory");
+}
+
+
+__asm__(
+       "       .macro  arch_local_save_flags flags                     \n"
+       "       .set    push                                            \n"
+       "       .set    reorder                                         \n"
+#ifdef CONFIG_MIPS_MT_SMTC
+       "       mfc0    \\flags, $2, 1                                  \n"
+#else
+       "       mfc0    \\flags, $12                                    \n"
+#endif
+       "       .set    pop                                             \n"
+       "       .endm                                                   \n");
+
+static inline unsigned long arch_local_save_flags(void)
+{
+       unsigned long flags;
+       asm volatile("arch_local_save_flags %0" : "=r" (flags));
+       return flags;
+}
+
 
 static inline int arch_irqs_disabled_flags(unsigned long flags)
 {
@@ -245,7 +188,7 @@ static inline int arch_irqs_disabled_flags(unsigned long flags)
 #endif
 }
 
-#endif
+#endif /* #ifndef __ASSEMBLY__ */
 
 /*
  * Do the CPU's IRQ-state tracing from assembly code.
index 8debe9e917549097d09f5083489714605066a1cc..18806a52061c3c6869ed03c101ccabe740b64ac8 100644 (file)
@@ -112,12 +112,6 @@ register struct thread_info *__current_thread_info __asm__("$28");
 #define TIF_LOAD_WATCH         25      /* If set, load watch registers */
 #define TIF_SYSCALL_TRACE      31      /* syscall trace active */
 
-#ifdef CONFIG_MIPS32_O32
-#define TIF_32BIT TIF_32BIT_REGS
-#elif defined(CONFIG_MIPS32_N32)
-#define TIF_32BIT _TIF_32BIT_ADDR
-#endif /* CONFIG_MIPS32_O32 */
-
 #define _TIF_SYSCALL_TRACE     (1<<TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING                (1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED      (1<<TIF_NEED_RESCHED)
index a53f8ec37aac68beef41b905b88cf1fe92e805d9..290dc6a1d7a344413e36f00fdacfa86e9d1bcbe3 100644 (file)
@@ -79,7 +79,7 @@ static struct resource data_resource = { .name = "Kernel data", };
 void __init add_memory_region(phys_t start, phys_t size, long type)
 {
        int x = boot_mem_map.nr_map;
-       struct boot_mem_map_entry *prev = boot_mem_map.map + x - 1;
+       int i;
 
        /* Sanity check */
        if (start + size < start) {
@@ -88,15 +88,29 @@ void __init add_memory_region(phys_t start, phys_t size, long type)
        }
 
        /*
-        * Try to merge with previous entry if any.  This is far less than
-        * perfect but is sufficient for most real world cases.
+        * Try to merge with existing entry, if any.
         */
-       if (x && prev->addr + prev->size == start && prev->type == type) {
-               prev->size += size;
+       for (i = 0; i < boot_mem_map.nr_map; i++) {
+               struct boot_mem_map_entry *entry = boot_mem_map.map + i;
+               unsigned long top;
+
+               if (entry->type != type)
+                       continue;
+
+               if (start + size < entry->addr)
+                       continue;                       /* no overlap */
+
+               if (entry->addr + entry->size < start)
+                       continue;                       /* no overlap */
+
+               top = max(entry->addr + entry->size, start + size);
+               entry->addr = min(entry->addr, start);
+               entry->size = top - entry->addr;
+
                return;
        }
 
-       if (x == BOOT_MEM_MAP_MAX) {
+       if (boot_mem_map.nr_map == BOOT_MEM_MAP_MAX) {
                pr_err("Ooops! Too many entries in the memory map!\n");
                return;
        }
index c4a82e841c7309d1659ceeac4e708e6796ee8c2c..eeddc58802e11a57595ee7d123e0538577af0c67 100644 (file)
@@ -2,8 +2,9 @@
 # Makefile for MIPS-specific library files..
 #
 
-lib-y  += csum_partial.o delay.o memcpy.o memset.o \
-          strlen_user.o strncpy_user.o strnlen_user.o uncached.o
+lib-y  += bitops.o csum_partial.o delay.o memcpy.o memset.o \
+          mips-atomic.o strlen_user.o strncpy_user.o \
+          strnlen_user.o uncached.o
 
 obj-y                  += iomap.o
 obj-$(CONFIG_PCI)      += iomap-pci.o
diff --git a/arch/mips/lib/bitops.c b/arch/mips/lib/bitops.c
new file mode 100644 (file)
index 0000000..239a9c9
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * 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) 1994-1997, 99, 2000, 06, 07 Ralf Baechle (ralf@linux-mips.org)
+ * Copyright (c) 1999, 2000  Silicon Graphics, Inc.
+ */
+#include <linux/bitops.h>
+#include <linux/irqflags.h>
+#include <linux/export.h>
+
+
+/**
+ * __mips_set_bit - Atomically set a bit in memory.  This is called by
+ * set_bit() if it cannot find a faster solution.
+ * @nr: the bit to set
+ * @addr: the address to start counting from
+ */
+void __mips_set_bit(unsigned long nr, volatile unsigned long *addr)
+{
+       volatile unsigned long *a = addr;
+       unsigned bit = nr & SZLONG_MASK;
+       unsigned long mask;
+       unsigned long flags;
+
+       a += nr >> SZLONG_LOG;
+       mask = 1UL << bit;
+       raw_local_irq_save(flags);
+       *a |= mask;
+       raw_local_irq_restore(flags);
+}
+EXPORT_SYMBOL(__mips_set_bit);
+
+
+/**
+ * __mips_clear_bit - Clears a bit in memory.  This is called by clear_bit() if
+ * it cannot find a faster solution.
+ * @nr: Bit to clear
+ * @addr: Address to start counting from
+ */
+void __mips_clear_bit(unsigned long nr, volatile unsigned long *addr)
+{
+       volatile unsigned long *a = addr;
+       unsigned bit = nr & SZLONG_MASK;
+       unsigned long mask;
+       unsigned long flags;
+
+       a += nr >> SZLONG_LOG;
+       mask = 1UL << bit;
+       raw_local_irq_save(flags);
+       *a &= ~mask;
+       raw_local_irq_restore(flags);
+}
+EXPORT_SYMBOL(__mips_clear_bit);
+
+
+/**
+ * __mips_change_bit - Toggle a bit in memory.  This is called by change_bit()
+ * if it cannot find a faster solution.
+ * @nr: Bit to change
+ * @addr: Address to start counting from
+ */
+void __mips_change_bit(unsigned long nr, volatile unsigned long *addr)
+{
+       volatile unsigned long *a = addr;
+       unsigned bit = nr & SZLONG_MASK;
+       unsigned long mask;
+       unsigned long flags;
+
+       a += nr >> SZLONG_LOG;
+       mask = 1UL << bit;
+       raw_local_irq_save(flags);
+       *a ^= mask;
+       raw_local_irq_restore(flags);
+}
+EXPORT_SYMBOL(__mips_change_bit);
+
+
+/**
+ * __mips_test_and_set_bit - Set a bit and return its old value.  This is
+ * called by test_and_set_bit() if it cannot find a faster solution.
+ * @nr: Bit to set
+ * @addr: Address to count from
+ */
+int __mips_test_and_set_bit(unsigned long nr,
+                           volatile unsigned long *addr)
+{
+       volatile unsigned long *a = addr;
+       unsigned bit = nr & SZLONG_MASK;
+       unsigned long mask;
+       unsigned long flags;
+       unsigned long res;
+
+       a += nr >> SZLONG_LOG;
+       mask = 1UL << bit;
+       raw_local_irq_save(flags);
+       res = (mask & *a);
+       *a |= mask;
+       raw_local_irq_restore(flags);
+       return res;
+}
+EXPORT_SYMBOL(__mips_test_and_set_bit);
+
+
+/**
+ * __mips_test_and_set_bit_lock - Set a bit and return its old value.  This is
+ * called by test_and_set_bit_lock() if it cannot find a faster solution.
+ * @nr: Bit to set
+ * @addr: Address to count from
+ */
+int __mips_test_and_set_bit_lock(unsigned long nr,
+                                volatile unsigned long *addr)
+{
+       volatile unsigned long *a = addr;
+       unsigned bit = nr & SZLONG_MASK;
+       unsigned long mask;
+       unsigned long flags;
+       unsigned long res;
+
+       a += nr >> SZLONG_LOG;
+       mask = 1UL << bit;
+       raw_local_irq_save(flags);
+       res = (mask & *a);
+       *a |= mask;
+       raw_local_irq_restore(flags);
+       return res;
+}
+EXPORT_SYMBOL(__mips_test_and_set_bit_lock);
+
+
+/**
+ * __mips_test_and_clear_bit - Clear a bit and return its old value.  This is
+ * called by test_and_clear_bit() if it cannot find a faster solution.
+ * @nr: Bit to clear
+ * @addr: Address to count from
+ */
+int __mips_test_and_clear_bit(unsigned long nr, volatile unsigned long *addr)
+{
+       volatile unsigned long *a = addr;
+       unsigned bit = nr & SZLONG_MASK;
+       unsigned long mask;
+       unsigned long flags;
+       unsigned long res;
+
+       a += nr >> SZLONG_LOG;
+       mask = 1UL << bit;
+       raw_local_irq_save(flags);
+       res = (mask & *a);
+       *a &= ~mask;
+       raw_local_irq_restore(flags);
+       return res;
+}
+EXPORT_SYMBOL(__mips_test_and_clear_bit);
+
+
+/**
+ * __mips_test_and_change_bit - Change a bit and return its old value.  This is
+ * called by test_and_change_bit() if it cannot find a faster solution.
+ * @nr: Bit to change
+ * @addr: Address to count from
+ */
+int __mips_test_and_change_bit(unsigned long nr, volatile unsigned long *addr)
+{
+       volatile unsigned long *a = addr;
+       unsigned bit = nr & SZLONG_MASK;
+       unsigned long mask;
+       unsigned long flags;
+       unsigned long res;
+
+       a += nr >> SZLONG_LOG;
+       mask = 1UL << bit;
+       raw_local_irq_save(flags);
+       res = (mask & *a);
+       *a ^= mask;
+       raw_local_irq_restore(flags);
+       return res;
+}
+EXPORT_SYMBOL(__mips_test_and_change_bit);
diff --git a/arch/mips/lib/mips-atomic.c b/arch/mips/lib/mips-atomic.c
new file mode 100644 (file)
index 0000000..cd160be
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * 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) 1994, 95, 96, 97, 98, 99, 2003 by Ralf Baechle
+ * Copyright (C) 1996 by Paul M. Antoine
+ * Copyright (C) 1999 Silicon Graphics
+ * Copyright (C) 2000 MIPS Technologies, Inc.
+ */
+#include <asm/irqflags.h>
+#include <asm/hazards.h>
+#include <linux/compiler.h>
+#include <linux/preempt.h>
+#include <linux/export.h>
+
+#if !defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_MIPS_MT_SMTC)
+
+/*
+ * For cli() we have to insert nops to make sure that the new value
+ * has actually arrived in the status register before the end of this
+ * macro.
+ * R4000/R4400 need three nops, the R4600 two nops and the R10000 needs
+ * no nops at all.
+ */
+/*
+ * For TX49, operating only IE bit is not enough.
+ *
+ * If mfc0 $12 follows store and the mfc0 is last instruction of a
+ * page and fetching the next instruction causes TLB miss, the result
+ * of the mfc0 might wrongly contain EXL bit.
+ *
+ * ERT-TX49H2-027, ERT-TX49H3-012, ERT-TX49HL3-006, ERT-TX49H4-008
+ *
+ * Workaround: mask EXL bit of the result or place a nop before mfc0.
+ */
+__asm__(
+       "       .macro  arch_local_irq_disable\n"
+       "       .set    push                                            \n"
+       "       .set    noat                                            \n"
+#ifdef CONFIG_MIPS_MT_SMTC
+       "       mfc0    $1, $2, 1                                       \n"
+       "       ori     $1, 0x400                                       \n"
+       "       .set    noreorder                                       \n"
+       "       mtc0    $1, $2, 1                                       \n"
+#elif defined(CONFIG_CPU_MIPSR2)
+       /* see irqflags.h for inline function */
+#else
+       "       mfc0    $1,$12                                          \n"
+       "       ori     $1,0x1f                                         \n"
+       "       xori    $1,0x1f                                         \n"
+       "       .set    noreorder                                       \n"
+       "       mtc0    $1,$12                                          \n"
+#endif
+       "       irq_disable_hazard                                      \n"
+       "       .set    pop                                             \n"
+       "       .endm                                                   \n");
+
+notrace void arch_local_irq_disable(void)
+{
+       preempt_disable();
+       __asm__ __volatile__(
+               "arch_local_irq_disable"
+               : /* no outputs */
+               : /* no inputs */
+               : "memory");
+       preempt_enable();
+}
+EXPORT_SYMBOL(arch_local_irq_disable);
+
+
+__asm__(
+       "       .macro  arch_local_irq_save result                      \n"
+       "       .set    push                                            \n"
+       "       .set    reorder                                         \n"
+       "       .set    noat                                            \n"
+#ifdef CONFIG_MIPS_MT_SMTC
+       "       mfc0    \\result, $2, 1                                 \n"
+       "       ori     $1, \\result, 0x400                             \n"
+       "       .set    noreorder                                       \n"
+       "       mtc0    $1, $2, 1                                       \n"
+       "       andi    \\result, \\result, 0x400                       \n"
+#elif defined(CONFIG_CPU_MIPSR2)
+       /* see irqflags.h for inline function */
+#else
+       "       mfc0    \\result, $12                                   \n"
+       "       ori     $1, \\result, 0x1f                              \n"
+       "       xori    $1, 0x1f                                        \n"
+       "       .set    noreorder                                       \n"
+       "       mtc0    $1, $12                                         \n"
+#endif
+       "       irq_disable_hazard                                      \n"
+       "       .set    pop                                             \n"
+       "       .endm                                                   \n");
+
+notrace unsigned long arch_local_irq_save(void)
+{
+       unsigned long flags;
+       preempt_disable();
+       asm volatile("arch_local_irq_save\t%0"
+                    : "=r" (flags)
+                    : /* no inputs */
+                    : "memory");
+       preempt_enable();
+       return flags;
+}
+EXPORT_SYMBOL(arch_local_irq_save);
+
+
+__asm__(
+       "       .macro  arch_local_irq_restore flags                    \n"
+       "       .set    push                                            \n"
+       "       .set    noreorder                                       \n"
+       "       .set    noat                                            \n"
+#ifdef CONFIG_MIPS_MT_SMTC
+       "mfc0   $1, $2, 1                                               \n"
+       "andi   \\flags, 0x400                                          \n"
+       "ori    $1, 0x400                                               \n"
+       "xori   $1, 0x400                                               \n"
+       "or     \\flags, $1                                             \n"
+       "mtc0   \\flags, $2, 1                                          \n"
+#elif defined(CONFIG_CPU_MIPSR2) && defined(CONFIG_IRQ_CPU)
+       /* see irqflags.h for inline function */
+#elif defined(CONFIG_CPU_MIPSR2)
+       /* see irqflags.h for inline function */
+#else
+       "       mfc0    $1, $12                                         \n"
+       "       andi    \\flags, 1                                      \n"
+       "       ori     $1, 0x1f                                        \n"
+       "       xori    $1, 0x1f                                        \n"
+       "       or      \\flags, $1                                     \n"
+       "       mtc0    \\flags, $12                                    \n"
+#endif
+       "       irq_disable_hazard                                      \n"
+       "       .set    pop                                             \n"
+       "       .endm                                                   \n");
+
+notrace void arch_local_irq_restore(unsigned long flags)
+{
+       unsigned long __tmp1;
+
+#ifdef CONFIG_MIPS_MT_SMTC
+       /*
+        * SMTC kernel needs to do a software replay of queued
+        * IPIs, at the cost of branch and call overhead on each
+        * local_irq_restore()
+        */
+       if (unlikely(!(flags & 0x0400)))
+               smtc_ipi_replay();
+#endif
+       preempt_disable();
+       __asm__ __volatile__(
+               "arch_local_irq_restore\t%0"
+               : "=r" (__tmp1)
+               : "0" (flags)
+               : "memory");
+       preempt_enable();
+}
+EXPORT_SYMBOL(arch_local_irq_restore);
+
+
+notrace void __arch_local_irq_restore(unsigned long flags)
+{
+       unsigned long __tmp1;
+
+       preempt_disable();
+       __asm__ __volatile__(
+               "arch_local_irq_restore\t%0"
+               : "=r" (__tmp1)
+               : "0" (flags)
+               : "memory");
+       preempt_enable();
+}
+EXPORT_SYMBOL(__arch_local_irq_restore);
+
+#endif /* !defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_MIPS_MT_SMTC) */
index 80562b81f0f2a2036fbf0a28781601b420c5d872..74732177851c31843add1f2259dab3233932726a 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/physmap.h>
 #include <linux/platform_device.h>
+#include <asm/mips-boards/maltaint.h>
 #include <mtd/mtd-abi.h>
 
 #define SMC_PORT(base, int)                                            \
@@ -48,7 +49,7 @@ static struct plat_serial8250_port uart8250_data[] = {
        SMC_PORT(0x2F8, 3),
        {
                .mapbase        = 0x1f000900,   /* The CBUS UART */
-               .irq            = MIPS_CPU_IRQ_BASE + 2,
+               .irq            = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_MB2,
                .uartclk        = 3686400,      /* Twice the usual clk! */
                .iotype         = UPIO_MEM32,
                .flags          = CBUS_UART_FLAGS,
index fd49aeda9eb8b0c4fef656e3dc00228c59251b99..5dede04f2f3ead372752fdbaaafceca5708b6902 100644 (file)
@@ -65,7 +65,8 @@ put_sigset32(compat_sigset_t __user *up, sigset_t *set, size_t sz)
 {
        compat_sigset_t s;
 
-       if (sz != sizeof *set) panic("put_sigset32()");
+       if (sz != sizeof *set)
+               return -EINVAL;
        sigset_64to32(&s, set);
 
        return copy_to_user(up, &s, sizeof s);
@@ -77,7 +78,8 @@ get_sigset32(compat_sigset_t __user *up, sigset_t *set, size_t sz)
        compat_sigset_t s;
        int r;
 
-       if (sz != sizeof *set) panic("put_sigset32()");
+       if (sz != sizeof *set)
+               return -EINVAL;
 
        if ((r = copy_from_user(&s, up, sz)) == 0) {
                sigset_32to64(set, &s);
index 7426e40699bdbf08575d0b69722e6594a1535076..f76c10863c6266c5a4fe6a3fbbe22d022a11e8c2 100644 (file)
@@ -73,6 +73,8 @@ static unsigned long get_shared_area(struct address_space *mapping,
        struct vm_area_struct *vma;
        int offset = mapping ? get_offset(mapping) : 0;
 
+       offset = (offset + (pgoff << PAGE_SHIFT)) & 0x3FF000;
+
        addr = DCACHE_ALIGN(addr - offset) + offset;
 
        for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) {
index 7ab286ab5300accb706fb72a2e343153cae85d18..39ed65a44c5fac5fc996b2d5ec25effbbf9853fa 100644 (file)
                        interrupts = <2 7 0>;
                };
 
+               sclpc@3c00 {
+                       compatible = "fsl,mpc5200-lpbfifo";
+                       reg = <0x3c00 0x60>;
+                       interrupts = <2 23 0>;
+               };
+
                i2c@3d00 {
                        #address-cells = <1>;
                        #size-cells = <0>;
index 3444eb8f0ade62305d0a935ca50a02d1fca16933..24f668039295b1b95ff279ff91974a7ad65582ff 100644 (file)
                                reg = <0>;
                        };
                };
-
-               sclpc@3c00 {
-                       compatible = "fsl,mpc5200-lpbfifo";
-                       reg = <0x3c00 0x60>;
-                       interrupts = <3 23 0>;
-               };
        };
 
        localbus {
index 9e354997eb7e3ccc29ac70ee5e7a31c3ce319b01..96512c05803336d937cabcf5b06aa86e43bc538b 100644 (file)
@@ -59,7 +59,7 @@
                        #gpio-cells = <2>;
                };
 
-               psc@2000 { /* PSC1 in ac97 mode */
+               audioplatform: psc@2000 { /* PSC1 in ac97 mode */
                        compatible = "mpc5200b-psc-ac97","fsl,mpc5200b-psc-ac97";
                        cell-index = <0>;
                };
        localbus {
                status = "disabled";
        };
+
+       sound {
+               compatible = "phytec,pcm030-audio-fabric";
+               asoc-platform = <&audioplatform>;
+       };
 };
index 8520b58a5e9a0f0027a95f0df2662cbab898c5cc..b89ef65392dc229b4ec026e23ddd9c5228ed05f1 100644 (file)
@@ -372,10 +372,11 @@ static int mpc52xx_irqhost_map(struct irq_domain *h, unsigned int virq,
        case MPC52xx_IRQ_L1_MAIN: irqchip = &mpc52xx_main_irqchip; break;
        case MPC52xx_IRQ_L1_PERP: irqchip = &mpc52xx_periph_irqchip; break;
        case MPC52xx_IRQ_L1_SDMA: irqchip = &mpc52xx_sdma_irqchip; break;
-       default:
-               pr_err("%s: invalid irq: virq=%i, l1=%i, l2=%i\n",
-                      __func__, virq, l1irq, l2irq);
-               return -EINVAL;
+       case MPC52xx_IRQ_L1_CRIT:
+               pr_warn("%s: Critical IRQ #%d is unsupported! Nopping it.\n",
+                       __func__, l2irq);
+               irq_set_chip(virq, &no_irq_chip);
+               return 0;
        }
 
        irq_set_chip_and_handler(virq, irqchip, handle_level_irq);
index 797cd181dc3f615fab312df9ccce4813263eedf4..d16c8ded10847ce19d67f26a39179587707ddbf0 100644 (file)
@@ -449,7 +449,7 @@ int eeh_rmv_from_parent_pe(struct eeh_dev *edev, int purge_pe)
                        if (list_empty(&pe->edevs)) {
                                cnt = 0;
                                list_for_each_entry(child, &pe->child_list, child) {
-                                       if (!(pe->type & EEH_PE_INVALID)) {
+                                       if (!(child->type & EEH_PE_INVALID)) {
                                                cnt++;
                                                break;
                                        }
index d19f4977c83492e1174be5456e1d0ff7ee33ca33..e5b084723131cc1ef0b6260f2a571f7071ee5995 100644 (file)
@@ -220,7 +220,8 @@ static struct device_node *find_pe_dn(struct pci_dev *dev, int *total)
 
        /* Get the top level device in the PE */
        edev = of_node_to_eeh_dev(dn);
-       edev = list_first_entry(&edev->pe->edevs, struct eeh_dev, list);
+       if (edev->pe)
+               edev = list_first_entry(&edev->pe->edevs, struct eeh_dev, list);
        dn = eeh_dev_to_of_node(edev);
        if (!dn)
                return NULL;
index 3f3d9ca7a5b68fefdb333818fe6189d8c6cbf3ae..d385f396dfee90172e5a984702cd9ded8a76387d 100644 (file)
@@ -96,6 +96,7 @@ config S390
        select HAVE_MEMBLOCK_NODE_MAP
        select HAVE_CMPXCHG_LOCAL
        select HAVE_CMPXCHG_DOUBLE
+       select HAVE_ALIGNED_STRUCT_PAGE if SLUB
        select HAVE_VIRT_CPU_ACCOUNTING
        select VIRT_CPU_ACCOUNTING
        select ARCH_DISCARD_MEMBLOCK
@@ -130,6 +131,7 @@ config S390
        select ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE
        select HAVE_UID16 if 32BIT
        select ARCH_WANT_IPC_PARSE_VERSION
+       select HAVE_ARCH_TRANSPARENT_HUGEPAGE if 64BIT
        select GENERIC_SMP_IDLE_THREAD
        select GENERIC_TIME_VSYSCALL_OLD
        select GENERIC_CLOCKEVENTS
index d80f79d8dd9cd03d237ee2e7af1531abba69f2b2..8e1fb82392873669ce34b03ed34f18b64cc5b2de 100644 (file)
@@ -5,7 +5,7 @@ OUTPUT_FORMAT("elf64-s390", "elf64-s390", "elf64-s390")
 OUTPUT_ARCH(s390:64-bit)
 #else
 OUTPUT_FORMAT("elf32-s390", "elf32-s390", "elf32-s390")
-OUTPUT_ARCH(s390)
+OUTPUT_ARCH(s390:31-bit)
 #endif
 
 ENTRY(startup)
index 55bde6035216f35c5dc265b14366471cc1ce2b33..ad2b924167d799f4b410a1bc38e4350656f3da4c 100644 (file)
@@ -9,6 +9,8 @@
 
 #define LPM_ANYPATH 0xff
 #define __MAX_CSSID 0
+#define __MAX_SUBCHANNEL 65535
+#define __MAX_SSID 3
 
 #include <asm/scsw.h>
 
index a34a9d612fc0f2d4ecc9a4bfbcef2794fba7de41..18cd6b592650962010b7c72f32b0d401cf572a57 100644 (file)
@@ -20,7 +20,7 @@
 #define PSW32_MASK_CC          0x00003000UL
 #define PSW32_MASK_PM          0x00000f00UL
 
-#define PSW32_MASK_USER                0x00003F00UL
+#define PSW32_MASK_USER                0x0000FF00UL
 
 #define PSW32_ADDR_AMODE       0x80000000UL
 #define PSW32_ADDR_INSN                0x7FFFFFFFUL
index 7941968e12b48ced12b4122918f111485de1dc4e..5f0173a31693b19700b8afa92b60db199bfcb749 100644 (file)
@@ -9,7 +9,7 @@
 #include <asm/cpu_mf.h>
 
 /* CPU-measurement counter facility */
-#define PERF_CPUM_CF_MAX_CTR           160
+#define PERF_CPUM_CF_MAX_CTR           256
 
 /* Per-CPU flags for PMU states */
 #define PMU_F_RESERVED                 0x1000
index dd647c919a66c766a75a8114588f1cd51afdafd7..2d3b7cb2600593f102b23dc8094fe384aa151b28 100644 (file)
@@ -506,12 +506,15 @@ static inline int pud_bad(pud_t pud)
 
 static inline int pmd_present(pmd_t pmd)
 {
-       return (pmd_val(pmd) & _SEGMENT_ENTRY_ORIGIN) != 0UL;
+       unsigned long mask = _SEGMENT_ENTRY_INV | _SEGMENT_ENTRY_RO;
+       return (pmd_val(pmd) & mask) == _HPAGE_TYPE_NONE ||
+              !(pmd_val(pmd) & _SEGMENT_ENTRY_INV);
 }
 
 static inline int pmd_none(pmd_t pmd)
 {
-       return (pmd_val(pmd) & _SEGMENT_ENTRY_INV) != 0UL;
+       return (pmd_val(pmd) & _SEGMENT_ENTRY_INV) &&
+              !(pmd_val(pmd) & _SEGMENT_ENTRY_RO);
 }
 
 static inline int pmd_large(pmd_t pmd)
@@ -1223,6 +1226,11 @@ static inline void __pmd_idte(unsigned long address, pmd_t *pmdp)
 }
 
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
+
+#define SEGMENT_NONE   __pgprot(_HPAGE_TYPE_NONE)
+#define SEGMENT_RO     __pgprot(_HPAGE_TYPE_RO)
+#define SEGMENT_RW     __pgprot(_HPAGE_TYPE_RW)
+
 #define __HAVE_ARCH_PGTABLE_DEPOSIT
 extern void pgtable_trans_huge_deposit(struct mm_struct *mm, pgtable_t pgtable);
 
@@ -1242,16 +1250,15 @@ static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr,
 
 static inline unsigned long massage_pgprot_pmd(pgprot_t pgprot)
 {
-       unsigned long pgprot_pmd = 0;
-
-       if (pgprot_val(pgprot) & _PAGE_INVALID) {
-               if (pgprot_val(pgprot) & _PAGE_SWT)
-                       pgprot_pmd |= _HPAGE_TYPE_NONE;
-               pgprot_pmd |= _SEGMENT_ENTRY_INV;
-       }
-       if (pgprot_val(pgprot) & _PAGE_RO)
-               pgprot_pmd |= _SEGMENT_ENTRY_RO;
-       return pgprot_pmd;
+       /*
+        * pgprot is PAGE_NONE, PAGE_RO, or PAGE_RW (see __Pxxx / __Sxxx)
+        * Convert to segment table entry format.
+        */
+       if (pgprot_val(pgprot) == pgprot_val(PAGE_NONE))
+               return pgprot_val(SEGMENT_NONE);
+       if (pgprot_val(pgprot) == pgprot_val(PAGE_RO))
+               return pgprot_val(SEGMENT_RO);
+       return pgprot_val(SEGMENT_RW);
 }
 
 static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
@@ -1269,7 +1276,9 @@ static inline pmd_t pmd_mkhuge(pmd_t pmd)
 
 static inline pmd_t pmd_mkwrite(pmd_t pmd)
 {
-       pmd_val(pmd) &= ~_SEGMENT_ENTRY_RO;
+       /* Do not clobber _HPAGE_TYPE_NONE pages! */
+       if (!(pmd_val(pmd) & _SEGMENT_ENTRY_INV))
+               pmd_val(pmd) &= ~_SEGMENT_ENTRY_RO;
        return pmd;
 }
 
index 9ca30538376001ffe6b07e9cac9db311707e195f..9935cbd6a46fdee89e8cdfd65c7f9acc0de474b9 100644 (file)
@@ -8,6 +8,9 @@ struct cpu;
 
 #ifdef CONFIG_SCHED_BOOK
 
+extern unsigned char cpu_socket_id[NR_CPUS];
+#define topology_physical_package_id(cpu) (cpu_socket_id[cpu])
+
 extern unsigned char cpu_core_id[NR_CPUS];
 extern cpumask_t cpu_core_map[NR_CPUS];
 
index 59b67ed423b422bb6ed353f516b796278f5bcb38..7bf68fff7c5d28cd2255d8d86189eb55368ddd71 100644 (file)
@@ -1,8 +1,6 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
 
-generic-y += kvm_para.h
-
 header-y += auxvec.h
 header-y += bitsperlong.h
 header-y += byteorder.h
index 581992dfae27b605e49a8a6f5d2972cc0646fadc..6b4fb29cc197e5d9544fd124e61a742a41114464 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *    Copyright IBM Corp. 2007
+ *    Copyright IBM Corp. 2007, 2012
  *    Author(s): Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
  */
 
 #define __MAX_CHPID 255
 
 struct chp_id {
-       u8 reserved1;
-       u8 cssid;
-       u8 reserved2;
-       u8 id;
+       __u8 reserved1;
+       __u8 cssid;
+       __u8 reserved2;
+       __u8 id;
 } __attribute__((packed));
 
 
diff --git a/arch/s390/include/uapi/asm/kvm_para.h b/arch/s390/include/uapi/asm/kvm_para.h
new file mode 100644 (file)
index 0000000..ff1f4e7
--- /dev/null
@@ -0,0 +1,11 @@
+/*
+ * User API definitions for paravirtual devices on s390
+ *
+ * Copyright IBM Corp. 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License (version 2 only)
+ * as published by the Free Software Foundation.
+ *
+ *    Author(s): Christian Borntraeger <borntraeger@de.ibm.com>
+ */
index 705588a16d70da6322ca349074a1b30de92f658a..a5ca214b34fdb1271e4fad48d9c7c7fb8c5a9437 100644 (file)
@@ -239,7 +239,7 @@ typedef struct
 #define PSW_MASK_EA            0x00000000UL
 #define PSW_MASK_BA            0x00000000UL
 
-#define PSW_MASK_USER          0x00003F00UL
+#define PSW_MASK_USER          0x0000FF00UL
 
 #define PSW_ADDR_AMODE         0x80000000UL
 #define PSW_ADDR_INSN          0x7FFFFFFFUL
@@ -269,7 +269,7 @@ typedef struct
 #define PSW_MASK_EA            0x0000000100000000UL
 #define PSW_MASK_BA            0x0000000080000000UL
 
-#define PSW_MASK_USER          0x00003F8180000000UL
+#define PSW_MASK_USER          0x0000FF8180000000UL
 
 #define PSW_ADDR_AMODE         0x0000000000000000UL
 #define PSW_ADDR_INSN          0xFFFFFFFFFFFFFFFFUL
index 8df8d8a19c986e1b2fea8db91cf59d329fc3b877..64b24650e4f8c1d43f5cf151b46478f5a602e277 100644 (file)
@@ -59,8 +59,8 @@ enum {
 
 enum {
        CACHE_TI_UNIFIED = 0,
-       CACHE_TI_INSTRUCTION = 0,
-       CACHE_TI_DATA,
+       CACHE_TI_DATA = 0,
+       CACHE_TI_INSTRUCTION,
 };
 
 struct cache_info {
@@ -121,7 +121,10 @@ static int __init cache_add(int level, int private, int type)
        cache = kzalloc(sizeof(*cache), GFP_KERNEL);
        if (!cache)
                return -ENOMEM;
-       ti = type == CACHE_TYPE_DATA ? CACHE_TI_DATA : CACHE_TI_UNIFIED;
+       if (type == CACHE_TYPE_INSTRUCTION)
+               ti = CACHE_TI_INSTRUCTION;
+       else
+               ti = CACHE_TI_UNIFIED;
        cache->size = ecag(EXTRACT_SIZE, level, ti);
        cache->line_size = ecag(EXTRACT_LINE_SIZE, level, ti);
        cache->associativity = ecag(EXTRACT_ASSOCIATIVITY, level, ti);
index a1e8a8694bb70561a8c78c35558ff3a635e2203e..593fcc9253fc433650e54fbc8f8f829f5d961e98 100644 (file)
@@ -309,6 +309,10 @@ static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs)
        regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) |
                (__u64)(regs32.psw.mask & PSW32_MASK_USER) << 32 |
                (__u64)(regs32.psw.addr & PSW32_ADDR_AMODE);
+       /* Check for invalid user address space control. */
+       if ((regs->psw.mask & PSW_MASK_ASC) >= (psw_kernel_bits & PSW_MASK_ASC))
+               regs->psw.mask = (psw_user_bits & PSW_MASK_ASC) |
+                       (regs->psw.mask & ~PSW_MASK_ASC);
        regs->psw.addr = (__u64)(regs32.psw.addr & PSW32_ADDR_INSN);
        for (i = 0; i < NUM_GPRS; i++)
                regs->gprs[i] = (__u64) regs32.gprs[i];
@@ -481,7 +485,10 @@ static int setup_frame32(int sig, struct k_sigaction *ka,
 
        /* Set up registers for signal handler */
        regs->gprs[15] = (__force __u64) frame;
-       regs->psw.mask |= PSW_MASK_BA;          /* force amode 31 */
+       /* Force 31 bit amode and default user address space control. */
+       regs->psw.mask = PSW_MASK_BA |
+               (psw_user_bits & PSW_MASK_ASC) |
+               (regs->psw.mask & ~PSW_MASK_ASC);
        regs->psw.addr = (__force __u64) ka->sa.sa_handler;
 
        regs->gprs[2] = map_signal(sig);
@@ -549,7 +556,10 @@ static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
 
        /* Set up registers for signal handler */
        regs->gprs[15] = (__force __u64) frame;
-       regs->psw.mask |= PSW_MASK_BA;          /* force amode 31 */
+       /* Force 31 bit amode and default user address space control. */
+       regs->psw.mask = PSW_MASK_BA |
+               (psw_user_bits & PSW_MASK_ASC) |
+               (regs->psw.mask & ~PSW_MASK_ASC);
        regs->psw.addr = (__u64) ka->sa.sa_handler;
 
        regs->gprs[2] = map_signal(sig);
index acaaaf4b7055e2d50122f43e6f695771a6f781cd..085a95eb315f480dc2edb492fc58a80dde0ae7d5 100644 (file)
 .align 2
 startup_kdump_relocated:
        basr    %r13,0
-0:
-       mvc     0(8,%r0),.Lrestart_psw-0b(%r13) # Setup restart PSW
-       sam31                                   # Switch to 31 bit addr mode
-       sr      %r1,%r1                         # Erase register r1
-       sr      %r2,%r2                         # Erase register r2
-       sigp    %r1,%r2,SIGP_SET_ARCHITECTURE   # Switch to 31 bit arch mode
-       lpsw    0                               # Start new kernel...
+0:     lpswe   .Lrestart_psw-0b(%r13)          # Start new kernel...
 .align 8
 .Lrestart_psw:
-       .long   0x00080000,0x80000000 + startup
+       .quad   0x0000000080000000,0x0000000000000000 + startup
 #else
 .align 2
 .Lep_startup_kdump:
index 9871b1971ed7602a7efef88fc62d019dde3b98c4..c4e7269d4a0980d8736c5a9c32e916cb581b0a58 100644 (file)
@@ -94,7 +94,7 @@ static int get_counter_set(u64 event)
                set = CPUMF_CTR_SET_USER;
        else if (event < 128)
                set = CPUMF_CTR_SET_CRYPTO;
-       else if (event < 160)
+       else if (event < 256)
                set = CPUMF_CTR_SET_EXT;
 
        return set;
@@ -138,6 +138,10 @@ static int validate_ctr_version(const struct hw_perf_event *hwc)
        case CPUMF_CTR_SET_EXT:
                if (cpuhw->info.csvn < 1)
                        err = -EOPNOTSUPP;
+               if ((cpuhw->info.csvn == 1 && hwc->config > 159) ||
+                   (cpuhw->info.csvn == 2 && hwc->config > 175) ||
+                   (cpuhw->info.csvn  > 2 && hwc->config > 255))
+                       err = -EOPNOTSUPP;
                break;
        }
 
index bf053898630de935aa4bcbd875c62a405169384c..b6506ee32a363749c5effc99d81d551b90b9fc3d 100644 (file)
@@ -44,6 +44,12 @@ _sclp_wait_int:
 #endif
        mvc     .LoldpswS1-.LbaseS1(16,%r13),0(%r8)
        mvc     0(16,%r8),0(%r9)
+#ifdef CONFIG_64BIT
+       epsw    %r6,%r7                         # set current addressing mode
+       nill    %r6,0x1                         # in new psw (31 or 64 bit mode)
+       nilh    %r7,0x8000
+       stm     %r6,%r7,0(%r8)
+#endif
        lhi     %r6,0x0200                      # cr mask for ext int (cr0.54)
        ltr     %r2,%r2
        jz      .LsetctS1
@@ -87,7 +93,7 @@ _sclp_wait_int:
        .long   0x00080000, 0x80000000+.LwaitS1 # PSW to handle ext int
 #ifdef CONFIG_64BIT
 .LextpswS1_64:
-       .quad   0x0000000180000000, .LwaitS1    # PSW to handle ext int, 64 bit
+       .quad   0, .LwaitS1                     # PSW to handle ext int, 64 bit
 #endif
 .LwaitpswS1:
        .long   0x010a0000, 0x00000000+.LloopS1 # PSW to wait for ext int
index c13a2a37ef007b2634a508b7053b0c3cc12e30b2..d1259d875074179ff11b232258fcc36ef98b90c3 100644 (file)
@@ -136,6 +136,10 @@ static int restore_sigregs(struct pt_regs *regs, _sigregs __user *sregs)
        /* Use regs->psw.mask instead of psw_user_bits to preserve PER bit. */
        regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) |
                (user_sregs.regs.psw.mask & PSW_MASK_USER);
+       /* Check for invalid user address space control. */
+       if ((regs->psw.mask & PSW_MASK_ASC) >= (psw_kernel_bits & PSW_MASK_ASC))
+               regs->psw.mask = (psw_user_bits & PSW_MASK_ASC) |
+                       (regs->psw.mask & ~PSW_MASK_ASC);
        /* Check for invalid amode */
        if (regs->psw.mask & PSW_MASK_EA)
                regs->psw.mask |= PSW_MASK_BA;
@@ -273,7 +277,10 @@ static int setup_frame(int sig, struct k_sigaction *ka,
 
        /* Set up registers for signal handler */
        regs->gprs[15] = (unsigned long) frame;
-       regs->psw.mask |= PSW_MASK_EA | PSW_MASK_BA;    /* 64 bit amode */
+       /* Force default amode and default user address space control. */
+       regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA |
+               (psw_user_bits & PSW_MASK_ASC) |
+               (regs->psw.mask & ~PSW_MASK_ASC);
        regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE;
 
        regs->gprs[2] = map_signal(sig);
@@ -346,7 +353,10 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 
        /* Set up registers for signal handler */
        regs->gprs[15] = (unsigned long) frame;
-       regs->psw.mask |= PSW_MASK_EA | PSW_MASK_BA;    /* 64 bit amode */
+       /* Force default amode and default user address space control. */
+       regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA |
+               (psw_user_bits & PSW_MASK_ASC) |
+               (regs->psw.mask & ~PSW_MASK_ASC);
        regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE;
 
        regs->gprs[2] = map_signal(sig);
index 54d93f4b681813927aabd8adbffbeb6204387d4b..dd55f7c2010448a5b842c741ac6d93fc673591da 100644 (file)
@@ -40,6 +40,7 @@ static DEFINE_SPINLOCK(topology_lock);
 static struct mask_info core_info;
 cpumask_t cpu_core_map[NR_CPUS];
 unsigned char cpu_core_id[NR_CPUS];
+unsigned char cpu_socket_id[NR_CPUS];
 
 static struct mask_info book_info;
 cpumask_t cpu_book_map[NR_CPUS];
@@ -83,11 +84,12 @@ static struct mask_info *add_cpus_to_mask(struct topology_cpu *tl_cpu,
                        cpumask_set_cpu(lcpu, &book->mask);
                        cpu_book_id[lcpu] = book->id;
                        cpumask_set_cpu(lcpu, &core->mask);
+                       cpu_core_id[lcpu] = rcpu;
                        if (one_core_per_cpu) {
-                               cpu_core_id[lcpu] = rcpu;
+                               cpu_socket_id[lcpu] = rcpu;
                                core = core->next;
                        } else {
-                               cpu_core_id[lcpu] = core->id;
+                               cpu_socket_id[lcpu] = core->id;
                        }
                        smp_cpu_set_polarization(lcpu, tl_cpu->pp);
                }
index de8fa9bbd35ee9787537e93c18b561b75cacf72f..79cb51adc7419b52245d444c74e2c9378eaf99ab 100644 (file)
@@ -8,7 +8,7 @@
 
 #ifndef CONFIG_64BIT
 OUTPUT_FORMAT("elf32-s390", "elf32-s390", "elf32-s390")
-OUTPUT_ARCH(s390)
+OUTPUT_ARCH(s390:31-bit)
 ENTRY(startup)
 jiffies = jiffies_64 + 4;
 #else
index 2d37bb861faf69cf43e30971881fae771322158a..9017a63dda3dd21df684563770819af53a2cb370 100644 (file)
@@ -39,7 +39,7 @@ static __always_inline unsigned long follow_table(struct mm_struct *mm,
        pmd = pmd_offset(pud, addr);
        if (pmd_none(*pmd))
                return -0x10UL;
-       if (pmd_huge(*pmd)) {
+       if (pmd_large(*pmd)) {
                if (write && (pmd_val(*pmd) & _SEGMENT_ENTRY_RO))
                        return -0x04UL;
                return (pmd_val(*pmd) & HPAGE_MASK) + (addr & ~HPAGE_MASK);
index 60acb93a46809065b0d454e65f3837aa37e70aee..1f5315d1215c2640f5691555801e9ff7885c7fcf 100644 (file)
@@ -126,7 +126,7 @@ static inline int gup_pmd_range(pud_t *pudp, pud_t pud, unsigned long addr,
                 */
                if (pmd_none(pmd) || pmd_trans_splitting(pmd))
                        return 0;
-               if (unlikely(pmd_huge(pmd))) {
+               if (unlikely(pmd_large(pmd))) {
                        if (!gup_huge_pmd(pmdp, pmd, addr, next,
                                          write, pages, nr))
                                return 0;
@@ -180,8 +180,7 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write,
        addr = start;
        len = (unsigned long) nr_pages << PAGE_SHIFT;
        end = start + len;
-       if (unlikely(!access_ok(write ? VERIFY_WRITE : VERIFY_READ,
-                                       (void __user *)start, len)))
+       if ((end < start) || (end > TASK_SIZE))
                return 0;
 
        local_irq_save(flags);
@@ -229,7 +228,7 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write,
        addr = start;
        len = (unsigned long) nr_pages << PAGE_SHIFT;
        end = start + len;
-       if (end < start)
+       if ((end < start) || (end > TASK_SIZE))
                goto slow_irqon;
 
        /*
index b6b442b0d793daeff8caea90418458618a7ce506..9f2edb5c555179de8d00ee5d2031546df35f8a9d 100644 (file)
@@ -20,6 +20,7 @@ config SPARC
        select HAVE_ARCH_TRACEHOOK
        select SYSCTL_EXCEPTION_TRACE
        select ARCH_WANT_OPTIONAL_GPIOLIB
+       select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
        select RTC_CLASS
        select RTC_DRV_M48T59
        select HAVE_IRQ_WORK
index 6ae1ad5e502bda9de0833ebec5ee2d5758c5ceed..5d469d81761fcb039b44245b813d9f3a21310cad 100644 (file)
@@ -13,13 +13,13 @@ obj-$(CONFIG_CRYPTO_DES_SPARC64) += camellia-sparc64.o
 
 obj-$(CONFIG_CRYPTO_CRC32C_SPARC64) += crc32c-sparc64.o
 
-sha1-sparc64-y := sha1_asm.o sha1_glue.o crop_devid.o
-sha256-sparc64-y := sha256_asm.o sha256_glue.o crop_devid.o
-sha512-sparc64-y := sha512_asm.o sha512_glue.o crop_devid.o
-md5-sparc64-y := md5_asm.o md5_glue.o crop_devid.o
+sha1-sparc64-y := sha1_asm.o sha1_glue.o
+sha256-sparc64-y := sha256_asm.o sha256_glue.o
+sha512-sparc64-y := sha512_asm.o sha512_glue.o
+md5-sparc64-y := md5_asm.o md5_glue.o
 
-aes-sparc64-y := aes_asm.o aes_glue.o crop_devid.o
-des-sparc64-y := des_asm.o des_glue.o crop_devid.o
-camellia-sparc64-y := camellia_asm.o camellia_glue.o crop_devid.o
+aes-sparc64-y := aes_asm.o aes_glue.o
+des-sparc64-y := des_asm.o des_glue.o
+camellia-sparc64-y := camellia_asm.o camellia_glue.o
 
-crc32c-sparc64-y := crc32c_asm.o crc32c_glue.o crop_devid.o
+crc32c-sparc64-y := crc32c_asm.o crc32c_glue.o
index 8f1c9980f63767254e2133f0218fc449754f3b0f..3965d1d36dfaa84e4634a7918bfdb9626f4bfe1a 100644 (file)
@@ -475,3 +475,5 @@ MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("AES Secure Hash Algorithm, sparc64 aes opcode accelerated");
 
 MODULE_ALIAS("aes");
+
+#include "crop_devid.c"
index 42905c084299ebc962925cce691900bfd9fcad4a..62c89af3fd3fb3793a9dc0af63244fd94e7d808e 100644 (file)
@@ -320,3 +320,5 @@ MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Camellia Cipher Algorithm, sparc64 camellia opcode accelerated");
 
 MODULE_ALIAS("aes");
+
+#include "crop_devid.c"
index 0bd89cea8d8ed2798db52215b1d9810a07bf9cbc..5162fad912ce09faf6fcf5979e2ef60cadc03ba4 100644 (file)
@@ -177,3 +177,5 @@ MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("CRC32c (Castagnoli), sparc64 crc32c opcode accelerated");
 
 MODULE_ALIAS("crc32c");
+
+#include "crop_devid.c"
index c4940c2d307391dd47dbe04447ccc749b5b40962..41524cebcc49e4dfb48e0628efd67b9aa50619ac 100644 (file)
@@ -527,3 +527,5 @@ MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms, sparc64 des opcode accelerated");
 
 MODULE_ALIAS("des");
+
+#include "crop_devid.c"
index 603d723038ce2f6d909d2ff5d53a7d0a54197aa1..09a9ea1dfb697381a410cdaf043262d2e4e24898 100644 (file)
@@ -186,3 +186,5 @@ MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("MD5 Secure Hash Algorithm, sparc64 md5 opcode accelerated");
 
 MODULE_ALIAS("md5");
+
+#include "crop_devid.c"
index 2bbb20bee9f15c2404f1458a1815a901d3fb8828..6cd5f29e1e0d592050602afff567598d1062b713 100644 (file)
@@ -181,3 +181,5 @@ MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm, sparc64 sha1 opcode accelerated");
 
 MODULE_ALIAS("sha1");
+
+#include "crop_devid.c"
index 591e656bd891c4653ecf2c11d440eaf8f6a2593d..04f555ab268002d16ca0d1d1bf69e6e8829d4d04 100644 (file)
@@ -239,3 +239,5 @@ MODULE_DESCRIPTION("SHA-224 and SHA-256 Secure Hash Algorithm, sparc64 sha256 op
 
 MODULE_ALIAS("sha224");
 MODULE_ALIAS("sha256");
+
+#include "crop_devid.c"
index 486f0a2b7001fcda4d24edcfc5bea8ed78139080..f04d1994d19aa3acfc9286a82265a4a031b8ea5f 100644 (file)
@@ -224,3 +224,5 @@ MODULE_DESCRIPTION("SHA-384 and SHA-512 Secure Hash Algorithm, sparc64 sha512 op
 
 MODULE_ALIAS("sha384");
 MODULE_ALIAS("sha512");
+
+#include "crop_devid.c"
index ce35a1cf1a20b0b6f2ab7ae424c7ced8cc3da2f2..be56a244c9cf00de10e47b6d7933676791c8c4a8 100644 (file)
@@ -1,7 +1,7 @@
 /* atomic.h: Thankfully the V9 is at least reasonable for this
  *           stuff.
  *
- * Copyright (C) 1996, 1997, 2000 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1996, 1997, 2000, 2012 David S. Miller (davem@redhat.com)
  */
 
 #ifndef __ARCH_SPARC64_ATOMIC__
@@ -106,6 +106,8 @@ static inline long atomic64_add_unless(atomic64_t *v, long a, long u)
 
 #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
 
+extern long atomic64_dec_if_positive(atomic64_t *v);
+
 /* Atomic operations are already serializing */
 #define smp_mb__before_atomic_dec()    barrier()
 #define smp_mb__after_atomic_dec()     barrier()
index db3af0d30fb10129124c594d1f1195bb59f2a6f2..4e02086b839cf2146431265ce77dbb984840d33e 100644 (file)
@@ -1,6 +1,46 @@
 #ifndef _SPARC64_BACKOFF_H
 #define _SPARC64_BACKOFF_H
 
+/* The macros in this file implement an exponential backoff facility
+ * for atomic operations.
+ *
+ * When multiple threads compete on an atomic operation, it is
+ * possible for one thread to be continually denied a successful
+ * completion of the compare-and-swap instruction.  Heavily
+ * threaded cpu implementations like Niagara can compound this
+ * problem even further.
+ *
+ * When an atomic operation fails and needs to be retried, we spin a
+ * certain number of times.  At each subsequent failure of the same
+ * operation we double the spin count, realizing an exponential
+ * backoff.
+ *
+ * When we spin, we try to use an operation that will cause the
+ * current cpu strand to block, and therefore make the core fully
+ * available to any other other runnable strands.  There are two
+ * options, based upon cpu capabilities.
+ *
+ * On all cpus prior to SPARC-T4 we do three dummy reads of the
+ * condition code register.  Each read blocks the strand for something
+ * between 40 and 50 cpu cycles.
+ *
+ * For SPARC-T4 and later we have a special "pause" instruction
+ * available.  This is implemented using writes to register %asr27.
+ * The cpu will block the number of cycles written into the register,
+ * unless a disrupting trap happens first.  SPARC-T4 specifically
+ * implements pause with a granularity of 8 cycles.  Each strand has
+ * an internal pause counter which decrements every 8 cycles.  So the
+ * chip shifts the %asr27 value down by 3 bits, and writes the result
+ * into the pause counter.  If a value smaller than 8 is written, the
+ * chip blocks for 1 cycle.
+ *
+ * To achieve the same amount of backoff as the three %ccr reads give
+ * on earlier chips, we shift the backoff value up by 7 bits.  (Three
+ * %ccr reads block for about 128 cycles, 1 << 7 == 128) We write the
+ * whole amount we want to block into the pause register, rather than
+ * loop writing 128 each time.
+ */
+
 #define BACKOFF_LIMIT  (4 * 1024)
 
 #ifdef CONFIG_SMP
 #define BACKOFF_LABEL(spin_label, continue_label) \
        spin_label
 
-#define BACKOFF_SPIN(reg, tmp, label)  \
-       mov     reg, tmp; \
-88:    brnz,pt tmp, 88b; \
-        sub    tmp, 1, tmp; \
-       set     BACKOFF_LIMIT, tmp; \
-       cmp     reg, tmp; \
-       bg,pn   %xcc, label; \
-        nop; \
-       ba,pt   %xcc, label; \
-        sllx   reg, 1, reg;
+#define BACKOFF_SPIN(reg, tmp, label)          \
+       mov             reg, tmp;               \
+88:    rd              %ccr, %g0;              \
+       rd              %ccr, %g0;              \
+       rd              %ccr, %g0;              \
+       .section        .pause_3insn_patch,"ax";\
+       .word           88b;                    \
+       sllx            tmp, 7, tmp;            \
+       wr              tmp, 0, %asr27;         \
+       clr             tmp;                    \
+       .previous;                              \
+       brnz,pt         tmp, 88b;               \
+        sub            tmp, 1, tmp;            \
+       set             BACKOFF_LIMIT, tmp;     \
+       cmp             reg, tmp;               \
+       bg,pn           %xcc, label;            \
+        nop;                                   \
+       ba,pt           %xcc, label;            \
+        sllx           reg, 1, reg;
 
 #else
 
index cef99fbc0a214b80721029fd826d1733f066868e..830502fe62b4e6a3d334abaf4076a5957deb2d9c 100644 (file)
@@ -232,9 +232,10 @@ static inline void __user *arch_compat_alloc_user_space(long len)
        struct pt_regs *regs = current_thread_info()->kregs;
        unsigned long usp = regs->u_regs[UREG_I6];
 
-       if (!(test_thread_flag(TIF_32BIT)))
+       if (test_thread_64bit_stack(usp))
                usp += STACK_BIAS;
-       else
+
+       if (test_thread_flag(TIF_32BIT))
                usp &= 0xffffffffUL;
 
        usp -= len;
index 4e5a483122a043a7eeba9e42001d32cdf56c0015..721e25f0e2ea80f19d4a7868791d4653097a2124 100644 (file)
@@ -196,7 +196,22 @@ extern unsigned long get_wchan(struct task_struct *task);
 #define KSTK_EIP(tsk)  (task_pt_regs(tsk)->tpc)
 #define KSTK_ESP(tsk)  (task_pt_regs(tsk)->u_regs[UREG_FP])
 
-#define cpu_relax()    barrier()
+/* Please see the commentary in asm/backoff.h for a description of
+ * what these instructions are doing and how they have been choosen.
+ * To make a long story short, we are trying to yield the current cpu
+ * strand during busy loops.
+ */
+#define cpu_relax()    asm volatile("\n99:\n\t"                        \
+                                    "rd        %%ccr, %%g0\n\t"        \
+                                    "rd        %%ccr, %%g0\n\t"        \
+                                    "rd        %%ccr, %%g0\n\t"        \
+                                    ".section  .pause_3insn_patch,\"ax\"\n\t"\
+                                    ".word     99b\n\t"                \
+                                    "wr        %%g0, 128, %%asr27\n\t" \
+                                    "nop\n\t"                          \
+                                    "nop\n\t"                          \
+                                    ".previous"                        \
+                                    ::: "memory")
 
 /* Prefetch support.  This is tuned for UltraSPARC-III and later.
  * UltraSPARC-I will treat these as nops, and UltraSPARC-II has
index c287651107069c58999381ba442bce84f2a6ed1f..67c62578d17043bbff42e1880f1f7e8986cb971c 100644 (file)
@@ -63,5 +63,13 @@ extern char *of_console_options;
 extern void irq_trans_init(struct device_node *dp);
 extern char *build_path_component(struct device_node *dp);
 
+/* SPARC has local implementations */
+extern int of_address_to_resource(struct device_node *dev, int index,
+                                 struct resource *r);
+#define of_address_to_resource of_address_to_resource
+
+void __iomem *of_iomap(struct device_node *node, int index);
+#define of_iomap of_iomap
+
 #endif /* __KERNEL__ */
 #endif /* _SPARC_PROM_H */
index 4e227663108181b45700b0cb879d5043ee1da64b..a3fe4dcc0aa6c5d25c7fa67ce3c74390b3a01876 100644 (file)
@@ -259,6 +259,11 @@ static inline bool test_and_clear_restore_sigmask(void)
 
 #define tsk_is_polling(t) test_tsk_thread_flag(t, TIF_POLLING_NRFLAG)
 
+#define thread32_stack_is_64bit(__SP) (((__SP) & 0x1) != 0)
+#define test_thread_64bit_stack(__SP) \
+       ((test_thread_flag(TIF_32BIT) && !thread32_stack_is_64bit(__SP)) ? \
+        false : true)
+
 #endif /* !__ASSEMBLY__ */
 
 #endif /* __KERNEL__ */
index 48f2807d326563da2bc95be4f870517685331aaf..71b5a67522abb2bb0d8457819612aa26e948fdc8 100644 (file)
@@ -372,7 +372,9 @@ etrap_spill_fixup_64bit:                            \
 
 /* Normal 32bit spill */
 #define SPILL_2_GENERIC(ASI)                           \
-       srl     %sp, 0, %sp;                            \
+       and     %sp, 1, %g3;                            \
+       brnz,pn %g3, (. - (128 + 4));                   \
+        srl    %sp, 0, %sp;                            \
        stwa    %l0, [%sp + %g0] ASI;                   \
        mov     0x04, %g3;                              \
        stwa    %l1, [%sp + %g3] ASI;                   \
@@ -398,14 +400,16 @@ etrap_spill_fixup_64bit:                          \
        stwa    %i6, [%g1 + %g0] ASI;                   \
        stwa    %i7, [%g1 + %g3] ASI;                   \
        saved;                                          \
-        retry; nop; nop;                               \
+        retry;                                         \
        b,a,pt  %xcc, spill_fixup_dax;                  \
        b,a,pt  %xcc, spill_fixup_mna;                  \
        b,a,pt  %xcc, spill_fixup;
 
 #define SPILL_2_GENERIC_ETRAP          \
 etrap_user_spill_32bit:                        \
-       srl     %sp, 0, %sp;            \
+       and     %sp, 1, %g3;            \
+       brnz,pn %g3, etrap_user_spill_64bit;    \
+        srl    %sp, 0, %sp;            \
        stwa    %l0, [%sp + 0x00] %asi; \
        stwa    %l1, [%sp + 0x04] %asi; \
        stwa    %l2, [%sp + 0x08] %asi; \
@@ -427,7 +431,7 @@ etrap_user_spill_32bit:                     \
        ba,pt   %xcc, etrap_save;       \
         wrpr   %g1, %cwp;              \
        nop; nop; nop; nop;             \
-       nop; nop; nop; nop;             \
+       nop; nop;                       \
        ba,a,pt %xcc, etrap_spill_fixup_32bit; \
        ba,a,pt %xcc, etrap_spill_fixup_32bit; \
        ba,a,pt %xcc, etrap_spill_fixup_32bit;
@@ -592,7 +596,9 @@ user_rtt_fill_64bit:                                        \
 
 /* Normal 32bit fill */
 #define FILL_2_GENERIC(ASI)                            \
-       srl     %sp, 0, %sp;                            \
+       and     %sp, 1, %g3;                            \
+       brnz,pn %g3, (. - (128 + 4));                   \
+        srl    %sp, 0, %sp;                            \
        lduwa   [%sp + %g0] ASI, %l0;                   \
        mov     0x04, %g2;                              \
        mov     0x08, %g3;                              \
@@ -616,14 +622,16 @@ user_rtt_fill_64bit:                                      \
        lduwa   [%g1 + %g3] ASI, %i6;                   \
        lduwa   [%g1 + %g5] ASI, %i7;                   \
        restored;                                       \
-       retry; nop; nop; nop; nop;                      \
+       retry; nop; nop;                                \
        b,a,pt  %xcc, fill_fixup_dax;                   \
        b,a,pt  %xcc, fill_fixup_mna;                   \
        b,a,pt  %xcc, fill_fixup;
 
 #define FILL_2_GENERIC_RTRAP                           \
 user_rtt_fill_32bit:                                   \
-       srl     %sp, 0, %sp;                            \
+       and     %sp, 1, %g3;                            \
+       brnz,pn %g3, user_rtt_fill_64bit;               \
+        srl    %sp, 0, %sp;                            \
        lduwa   [%sp + 0x00] %asi, %l0;                 \
        lduwa   [%sp + 0x04] %asi, %l1;                 \
        lduwa   [%sp + 0x08] %asi, %l2;                 \
@@ -643,7 +651,7 @@ user_rtt_fill_32bit:                                        \
        ba,pt   %xcc, user_rtt_pre_restore;             \
         restored;                                      \
        nop; nop; nop; nop; nop;                        \
-       nop; nop; nop; nop; nop;                        \
+       nop; nop; nop;                                  \
        ba,a,pt %xcc, user_rtt_fill_fixup;              \
        ba,a,pt %xcc, user_rtt_fill_fixup;              \
        ba,a,pt %xcc, user_rtt_fill_fixup;
index 8974ef7ae920685174f7d6427da816e4d3c7d3db..cac719d1bc5c6b8238ff0b6be5f34bc166980534 100644 (file)
 #define __NR_setns             337
 #define __NR_process_vm_readv  338
 #define __NR_process_vm_writev 339
+#define __NR_kern_features     340
+#define __NR_kcmp              341
 
-#define NR_syscalls            340
+#define NR_syscalls            342
+
+/* Bitmask values returned from kern_features system call.  */
+#define KERN_FEATURE_MIXED_MODE_STACK  0x00000001
 
 #ifdef __32bit_syscall_numbers__
 /* Sparc 32-bit only has the "setresuid32", "getresuid32" variants,
index 0c218e4c0881fba70c1748e6a4c295e0db280652..cc3c5cb47cdaa4d18e14533f5078b2dbd5f51649 100644 (file)
@@ -59,6 +59,13 @@ struct popc_6insn_patch_entry {
 extern struct popc_6insn_patch_entry __popc_6insn_patch,
        __popc_6insn_patch_end;
 
+struct pause_patch_entry {
+       unsigned int    addr;
+       unsigned int    insns[3];
+};
+extern struct pause_patch_entry __pause_3insn_patch,
+       __pause_3insn_patch_end;
+
 extern void __init per_cpu_patch(void);
 extern void sun4v_patch_1insn_range(struct sun4v_1insn_patch_entry *,
                                    struct sun4v_1insn_patch_entry *);
index f8b6eee40bde6596cdd9043e46aa9c9ef908fa4c..87f60ee6543394b4aea00d3d5e91082ef0b8a41f 100644 (file)
@@ -56,11 +56,13 @@ static inline unsigned int leon_eirq_get(int cpu)
 static void leon_handle_ext_irq(unsigned int irq, struct irq_desc *desc)
 {
        unsigned int eirq;
+       struct irq_bucket *p;
        int cpu = sparc_leon3_cpuid();
 
        eirq = leon_eirq_get(cpu);
-       if ((eirq & 0x10) && irq_map[eirq]->irq) /* bit4 tells if IRQ happened */
-               generic_handle_irq(irq_map[eirq]->irq);
+       p = irq_map[eirq];
+       if ((eirq & 0x10) && p && p->irq) /* bit4 tells if IRQ happened */
+               generic_handle_irq(p->irq);
 }
 
 /* The extended IRQ controller has been found, this function registers it */
index 885a8af74064b1425be7e424ca205996c4add704..b5c38faa4eadf423db3bc20df35d2c98cd5dabf3 100644 (file)
@@ -1762,15 +1762,25 @@ static void perf_callchain_user_32(struct perf_callchain_entry *entry,
 
        ufp = regs->u_regs[UREG_I6] & 0xffffffffUL;
        do {
-               struct sparc_stackf32 *usf, sf;
                unsigned long pc;
 
-               usf = (struct sparc_stackf32 *) ufp;
-               if (__copy_from_user_inatomic(&sf, usf, sizeof(sf)))
-                       break;
+               if (thread32_stack_is_64bit(ufp)) {
+                       struct sparc_stackf *usf, sf;
 
-               pc = sf.callers_pc;
-               ufp = (unsigned long)sf.fp;
+                       ufp += STACK_BIAS;
+                       usf = (struct sparc_stackf *) ufp;
+                       if (__copy_from_user_inatomic(&sf, usf, sizeof(sf)))
+                               break;
+                       pc = sf.callers_pc & 0xffffffff;
+                       ufp = ((unsigned long) sf.fp) & 0xffffffff;
+               } else {
+                       struct sparc_stackf32 *usf, sf;
+                       usf = (struct sparc_stackf32 *) ufp;
+                       if (__copy_from_user_inatomic(&sf, usf, sizeof(sf)))
+                               break;
+                       pc = sf.callers_pc;
+                       ufp = (unsigned long)sf.fp;
+               }
                perf_callchain_store(entry, pc);
        } while (entry->nr < PERF_MAX_STACK_DEPTH);
 }
index d778248ef3f8ea7b48de69d0a68ca586e5acfef3..c6e0c2910043556a073ba8e8f11843f09d20ca71 100644 (file)
@@ -452,13 +452,16 @@ void flush_thread(void)
 /* It's a bit more tricky when 64-bit tasks are involved... */
 static unsigned long clone_stackframe(unsigned long csp, unsigned long psp)
 {
+       bool stack_64bit = test_thread_64bit_stack(psp);
        unsigned long fp, distance, rval;
 
-       if (!(test_thread_flag(TIF_32BIT))) {
+       if (stack_64bit) {
                csp += STACK_BIAS;
                psp += STACK_BIAS;
                __get_user(fp, &(((struct reg_window __user *)psp)->ins[6]));
                fp += STACK_BIAS;
+               if (test_thread_flag(TIF_32BIT))
+                       fp &= 0xffffffff;
        } else
                __get_user(fp, &(((struct reg_window32 __user *)psp)->ins[6]));
 
@@ -472,7 +475,7 @@ static unsigned long clone_stackframe(unsigned long csp, unsigned long psp)
        rval = (csp - distance);
        if (copy_in_user((void __user *) rval, (void __user *) psp, distance))
                rval = 0;
-       else if (test_thread_flag(TIF_32BIT)) {
+       else if (!stack_64bit) {
                if (put_user(((u32)csp),
                             &(((struct reg_window32 __user *)rval)->ins[6])))
                        rval = 0;
@@ -507,18 +510,18 @@ void synchronize_user_stack(void)
 
        flush_user_windows();
        if ((window = get_thread_wsaved()) != 0) {
-               int winsize = sizeof(struct reg_window);
-               int bias = 0;
-
-               if (test_thread_flag(TIF_32BIT))
-                       winsize = sizeof(struct reg_window32);
-               else
-                       bias = STACK_BIAS;
-
                window -= 1;
                do {
-                       unsigned long sp = (t->rwbuf_stkptrs[window] + bias);
                        struct reg_window *rwin = &t->reg_window[window];
+                       int winsize = sizeof(struct reg_window);
+                       unsigned long sp;
+
+                       sp = t->rwbuf_stkptrs[window];
+
+                       if (test_thread_64bit_stack(sp))
+                               sp += STACK_BIAS;
+                       else
+                               winsize = sizeof(struct reg_window32);
 
                        if (!copy_to_user((char __user *)sp, rwin, winsize)) {
                                shift_window_buffer(window, get_thread_wsaved() - 1, t);
@@ -544,13 +547,6 @@ void fault_in_user_windows(void)
 {
        struct thread_info *t = current_thread_info();
        unsigned long window;
-       int winsize = sizeof(struct reg_window);
-       int bias = 0;
-
-       if (test_thread_flag(TIF_32BIT))
-               winsize = sizeof(struct reg_window32);
-       else
-               bias = STACK_BIAS;
 
        flush_user_windows();
        window = get_thread_wsaved();
@@ -558,8 +554,16 @@ void fault_in_user_windows(void)
        if (likely(window != 0)) {
                window -= 1;
                do {
-                       unsigned long sp = (t->rwbuf_stkptrs[window] + bias);
                        struct reg_window *rwin = &t->reg_window[window];
+                       int winsize = sizeof(struct reg_window);
+                       unsigned long sp;
+
+                       sp = t->rwbuf_stkptrs[window];
+
+                       if (test_thread_64bit_stack(sp))
+                               sp += STACK_BIAS;
+                       else
+                               winsize = sizeof(struct reg_window32);
 
                        if (unlikely(sp & 0x7UL))
                                stack_unaligned(sp);
index 484dabac7045aa2177df26f625ffabf9f6f523c7..7ff45e4ba6815080a29e02a64ad79bfdf9c1ed12 100644 (file)
@@ -151,7 +151,7 @@ static int regwindow64_get(struct task_struct *target,
 {
        unsigned long rw_addr = regs->u_regs[UREG_I6];
 
-       if (test_tsk_thread_flag(current, TIF_32BIT)) {
+       if (!test_thread_64bit_stack(rw_addr)) {
                struct reg_window32 win32;
                int i;
 
@@ -176,7 +176,7 @@ static int regwindow64_set(struct task_struct *target,
 {
        unsigned long rw_addr = regs->u_regs[UREG_I6];
 
-       if (test_tsk_thread_flag(current, TIF_32BIT)) {
+       if (!test_thread_64bit_stack(rw_addr)) {
                struct reg_window32 win32;
                int i;
 
index 0800e71d8a880242083688b385e88d564e4a681a..0eaf0059aaefa483bdbb228bf38c8154a7d9656b 100644 (file)
@@ -316,6 +316,25 @@ static void __init popc_patch(void)
        }
 }
 
+static void __init pause_patch(void)
+{
+       struct pause_patch_entry *p;
+
+       p = &__pause_3insn_patch;
+       while (p < &__pause_3insn_patch_end) {
+               unsigned long i, addr = p->addr;
+
+               for (i = 0; i < 3; i++) {
+                       *(unsigned int *) (addr +  (i * 4)) = p->insns[i];
+                       wmb();
+                       __asm__ __volatile__("flush     %0"
+                                            : : "r" (addr +  (i * 4)));
+               }
+
+               p++;
+       }
+}
+
 #ifdef CONFIG_SMP
 void __init boot_cpu_id_too_large(int cpu)
 {
@@ -528,6 +547,8 @@ static void __init init_sparc64_elf_hwcap(void)
 
        if (sparc64_elf_hwcap & AV_SPARC_POPC)
                popc_patch();
+       if (sparc64_elf_hwcap & AV_SPARC_PAUSE)
+               pause_patch();
 }
 
 void __init setup_arch(char **cmdline_p)
index 867de2f8189c32acf359fe5575cd139ede6b7048..689e1ba628097e12ab95496d60df2225817483d3 100644 (file)
@@ -295,9 +295,7 @@ void do_rt_sigreturn(struct pt_regs *regs)
                err |= restore_fpu_state(regs, fpu_save);
 
        err |= __copy_from_user(&set, &sf->mask, sizeof(sigset_t));
-       err |= do_sigaltstack(&sf->stack, NULL, (unsigned long)sf);
-
-       if (err)
+       if (err || do_sigaltstack(&sf->stack, NULL, (unsigned long)sf) == -EFAULT)
                goto segv;
 
        err |= __get_user(rwin_save, &sf->rwin_save);
index 11c6c9603e71f03995a3c17fcdf2f28957d7fa43..878ef3d5fec522d6b23d0640df962f33c2b958df 100644 (file)
@@ -751,3 +751,8 @@ int kernel_execve(const char *filename,
                      : "cc");
        return __res;
 }
+
+asmlinkage long sys_kern_features(void)
+{
+       return KERN_FEATURE_MIXED_MODE_STACK;
+}
index 63402f9e9f51f75622f9132e0b8f5372bcc806c1..5147f574f1256a7f3304a716da22bfb2ef68d42a 100644 (file)
@@ -85,3 +85,4 @@ sys_call_table:
 /*325*/        .long sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init
 /*330*/        .long sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime
 /*335*/        .long sys_syncfs, sys_sendmmsg, sys_setns, sys_process_vm_readv, sys_process_vm_writev
+/*340*/        .long sys_ni_syscall, sys_kcmp
index 3a58e0d66f51b0144ef5f9ca970bfbbbb9d01ed6..1c9af9fa38e9b0b489cb38899685e4c4c76b6584 100644 (file)
@@ -86,6 +86,7 @@ sys_call_table32:
        .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
        .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
 
 #endif /* CONFIG_COMPAT */
 
@@ -163,3 +164,4 @@ sys_call_table:
        .word sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init
 /*330*/        .word sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime
        .word sys_syncfs, sys_sendmmsg, sys_setns, sys_process_vm_readv, sys_process_vm_writev
+/*340*/        .word sys_kern_features, sys_kcmp
index f81d038f7340ce6b80cb65e0e27b2e7f2cb9edd2..8201c25e76697ad5f5a96de1b6921a3fb34372ac 100644 (file)
@@ -113,21 +113,24 @@ static inline long sign_extend_imm13(long imm)
 
 static unsigned long fetch_reg(unsigned int reg, struct pt_regs *regs)
 {
-       unsigned long value;
+       unsigned long value, fp;
        
        if (reg < 16)
                return (!reg ? 0 : regs->u_regs[reg]);
+
+       fp = regs->u_regs[UREG_FP];
+
        if (regs->tstate & TSTATE_PRIV) {
                struct reg_window *win;
-               win = (struct reg_window *)(regs->u_regs[UREG_FP] + STACK_BIAS);
+               win = (struct reg_window *)(fp + STACK_BIAS);
                value = win->locals[reg - 16];
-       } else if (test_thread_flag(TIF_32BIT)) {
+       } else if (!test_thread_64bit_stack(fp)) {
                struct reg_window32 __user *win32;
-               win32 = (struct reg_window32 __user *)((unsigned long)((u32)regs->u_regs[UREG_FP]));
+               win32 = (struct reg_window32 __user *)((unsigned long)((u32)fp));
                get_user(value, &win32->locals[reg - 16]);
        } else {
                struct reg_window __user *win;
-               win = (struct reg_window __user *)(regs->u_regs[UREG_FP] + STACK_BIAS);
+               win = (struct reg_window __user *)(fp + STACK_BIAS);
                get_user(value, &win->locals[reg - 16]);
        }
        return value;
@@ -135,19 +138,24 @@ static unsigned long fetch_reg(unsigned int reg, struct pt_regs *regs)
 
 static unsigned long *fetch_reg_addr(unsigned int reg, struct pt_regs *regs)
 {
+       unsigned long fp;
+
        if (reg < 16)
                return &regs->u_regs[reg];
+
+       fp = regs->u_regs[UREG_FP];
+
        if (regs->tstate & TSTATE_PRIV) {
                struct reg_window *win;
-               win = (struct reg_window *)(regs->u_regs[UREG_FP] + STACK_BIAS);
+               win = (struct reg_window *)(fp + STACK_BIAS);
                return &win->locals[reg - 16];
-       } else if (test_thread_flag(TIF_32BIT)) {
+       } else if (!test_thread_64bit_stack(fp)) {
                struct reg_window32 *win32;
-               win32 = (struct reg_window32 *)((unsigned long)((u32)regs->u_regs[UREG_FP]));
+               win32 = (struct reg_window32 *)((unsigned long)((u32)fp));
                return (unsigned long *)&win32->locals[reg - 16];
        } else {
                struct reg_window *win;
-               win = (struct reg_window *)(regs->u_regs[UREG_FP] + STACK_BIAS);
+               win = (struct reg_window *)(fp + STACK_BIAS);
                return &win->locals[reg - 16];
        }
 }
@@ -392,13 +400,15 @@ int handle_popc(u32 insn, struct pt_regs *regs)
                if (rd)
                        regs->u_regs[rd] = ret;
        } else {
-               if (test_thread_flag(TIF_32BIT)) {
+               unsigned long fp = regs->u_regs[UREG_FP];
+
+               if (!test_thread_64bit_stack(fp)) {
                        struct reg_window32 __user *win32;
-                       win32 = (struct reg_window32 __user *)((unsigned long)((u32)regs->u_regs[UREG_FP]));
+                       win32 = (struct reg_window32 __user *)((unsigned long)((u32)fp));
                        put_user(ret, &win32->locals[rd - 16]);
                } else {
                        struct reg_window __user *win;
-                       win = (struct reg_window __user *)(regs->u_regs[UREG_FP] + STACK_BIAS);
+                       win = (struct reg_window __user *)(fp + STACK_BIAS);
                        put_user(ret, &win->locals[rd - 16]);
                }
        }
@@ -554,7 +564,7 @@ void handle_ld_nf(u32 insn, struct pt_regs *regs)
                reg[0] = 0;
                if ((insn & 0x780000) == 0x180000)
                        reg[1] = 0;
-       } else if (test_thread_flag(TIF_32BIT)) {
+       } else if (!test_thread_64bit_stack(regs->u_regs[UREG_FP])) {
                put_user(0, (int __user *) reg);
                if ((insn & 0x780000) == 0x180000)
                        put_user(0, ((int __user *) reg) + 1);
index 08e074b7eb6a025e985700e0bf2443ef30fcb1d2..c096c624ac4d44ad6bd723b4bce88510dcdf70f5 100644 (file)
@@ -149,21 +149,24 @@ static inline void maybe_flush_windows(unsigned int rs1, unsigned int rs2,
 
 static unsigned long fetch_reg(unsigned int reg, struct pt_regs *regs)
 {
-       unsigned long value;
+       unsigned long value, fp;
        
        if (reg < 16)
                return (!reg ? 0 : regs->u_regs[reg]);
+
+       fp = regs->u_regs[UREG_FP];
+
        if (regs->tstate & TSTATE_PRIV) {
                struct reg_window *win;
-               win = (struct reg_window *)(regs->u_regs[UREG_FP] + STACK_BIAS);
+               win = (struct reg_window *)(fp + STACK_BIAS);
                value = win->locals[reg - 16];
-       } else if (test_thread_flag(TIF_32BIT)) {
+       } else if (!test_thread_64bit_stack(fp)) {
                struct reg_window32 __user *win32;
-               win32 = (struct reg_window32 __user *)((unsigned long)((u32)regs->u_regs[UREG_FP]));
+               win32 = (struct reg_window32 __user *)((unsigned long)((u32)fp));
                get_user(value, &win32->locals[reg - 16]);
        } else {
                struct reg_window __user *win;
-               win = (struct reg_window __user *)(regs->u_regs[UREG_FP] + STACK_BIAS);
+               win = (struct reg_window __user *)(fp + STACK_BIAS);
                get_user(value, &win->locals[reg - 16]);
        }
        return value;
@@ -172,16 +175,18 @@ static unsigned long fetch_reg(unsigned int reg, struct pt_regs *regs)
 static inline unsigned long __user *__fetch_reg_addr_user(unsigned int reg,
                                                          struct pt_regs *regs)
 {
+       unsigned long fp = regs->u_regs[UREG_FP];
+
        BUG_ON(reg < 16);
        BUG_ON(regs->tstate & TSTATE_PRIV);
 
-       if (test_thread_flag(TIF_32BIT)) {
+       if (!test_thread_64bit_stack(fp)) {
                struct reg_window32 __user *win32;
-               win32 = (struct reg_window32 __user *)((unsigned long)((u32)regs->u_regs[UREG_FP]));
+               win32 = (struct reg_window32 __user *)((unsigned long)((u32)fp));
                return (unsigned long __user *)&win32->locals[reg - 16];
        } else {
                struct reg_window __user *win;
-               win = (struct reg_window __user *)(regs->u_regs[UREG_FP] + STACK_BIAS);
+               win = (struct reg_window __user *)(fp + STACK_BIAS);
                return &win->locals[reg - 16];
        }
 }
@@ -204,7 +209,7 @@ static void store_reg(struct pt_regs *regs, unsigned long val, unsigned long rd)
        } else {
                unsigned long __user *rd_user = __fetch_reg_addr_user(rd, regs);
 
-               if (test_thread_flag(TIF_32BIT))
+               if (!test_thread_64bit_stack(regs->u_regs[UREG_FP]))
                        __put_user((u32)val, (u32 __user *)rd_user);
                else
                        __put_user(val, rd_user);
index 89c2c29f154b4c45114df0dce93feee4ce8330af..0bacceb19150ebff3a9e9088b11b66d8f5d4490b 100644 (file)
@@ -132,6 +132,11 @@ SECTIONS
                *(.popc_6insn_patch)
                __popc_6insn_patch_end = .;
        }
+       .pause_3insn_patch : {
+               __pause_3insn_patch = .;
+               *(.pause_3insn_patch)
+               __pause_3insn_patch_end = .;
+       }
        PERCPU_SECTION(SMP_CACHE_BYTES)
 
        . = ALIGN(PAGE_SIZE);
index a6b0863c27df48e12bfa656a83783fee6ecfa05c..1e67ce95836972d439b50c88aa77d8395a543652 100644 (file)
@@ -43,6 +43,8 @@ spill_fixup_mna:
 spill_fixup_dax:
        TRAP_LOAD_THREAD_REG(%g6, %g1)
        ldx     [%g6 + TI_FLAGS], %g1
+       andcc   %sp, 0x1, %g0
+       movne   %icc, 0, %g1
        andcc   %g1, _TIF_32BIT, %g0
        ldub    [%g6 + TI_WSAVED], %g1
        sll     %g1, 3, %g3
index 4d502da3de78f2c9e3987a8b7f2ab0f807879201..85c233d0a34003d551587c7c378bd813f64712fe 100644 (file)
@@ -1,6 +1,6 @@
 /* atomic.S: These things are too big to do inline.
  *
- * Copyright (C) 1999, 2007 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 1999, 2007 2012 David S. Miller (davem@davemloft.net)
  */
 
 #include <linux/linkage.h>
@@ -117,3 +117,17 @@ ENTRY(atomic64_sub_ret) /* %o0 = decrement, %o1 = atomic_ptr */
         sub    %g1, %o0, %o0
 2:     BACKOFF_SPIN(%o2, %o3, 1b)
 ENDPROC(atomic64_sub_ret)
+
+ENTRY(atomic64_dec_if_positive) /* %o0 = atomic_ptr */
+       BACKOFF_SETUP(%o2)
+1:     ldx     [%o0], %g1
+       brlez,pn %g1, 3f
+        sub    %g1, 1, %g7
+       casx    [%o0], %g1, %g7
+       cmp     %g1, %g7
+       bne,pn  %xcc, BACKOFF_LABEL(2f, 1b)
+        nop
+3:     retl
+        sub    %g1, 1, %o0
+2:     BACKOFF_SPIN(%o2, %o3, 1b)
+ENDPROC(atomic64_dec_if_positive)
index ee31b884c61b8390fa6a97e5d619ac4d1febe8cd..0c4e35e522fa0f5b719167cb90863e1343057968 100644 (file)
@@ -116,6 +116,7 @@ EXPORT_SYMBOL(atomic64_add);
 EXPORT_SYMBOL(atomic64_add_ret);
 EXPORT_SYMBOL(atomic64_sub);
 EXPORT_SYMBOL(atomic64_sub_ret);
+EXPORT_SYMBOL(atomic64_dec_if_positive);
 
 /* Atomic bit operations. */
 EXPORT_SYMBOL(test_and_set_bit);
index 1704068da92806d5868d0374bea669f31f21b113..034aadbff036fd617c8cae7afbcac20eee0ecaf8 100644 (file)
@@ -320,7 +320,7 @@ int do_mathemu(struct pt_regs *regs, struct fpustate *f, bool illegal_insn_trap)
                                        XR = 0;
                                else if (freg < 16)
                                        XR = regs->u_regs[freg];
-                               else if (test_thread_flag(TIF_32BIT)) {
+                               else if (!test_thread_64bit_stack(regs->u_regs[UREG_FP])) {
                                        struct reg_window32 __user *win32;
                                        flushw_user ();
                                        win32 = (struct reg_window32 __user *)((unsigned long)((u32)regs->u_regs[UREG_FP]));
index 55640cf92597b11f943173928b4d7d7437d4be14..3d15364c60714bf661da140c8f6e67cde20001b3 100644 (file)
@@ -26,6 +26,10 @@ $(error Set TILERA_ROOT or CROSS_COMPILE when building $(ARCH) on $(HOST_ARCH))
   endif
 endif
 
+# The tile compiler may emit .eh_frame information for backtracing.
+# In kernel modules, this causes load failures due to unsupported relocations.
+KBUILD_CFLAGS   += -fno-asynchronous-unwind-tables
+
 ifneq ($(CONFIG_DEBUG_EXTRA_FLAGS),"")
 KBUILD_CFLAGS   += $(CONFIG_DEBUG_EXTRA_FLAGS)
 endif
index 001cbfa10ac6364a9136b9d4440bfe69730a08be..243ffebe38d69a510f16e53083c49b46f3e6531b 100644 (file)
 #include <asm/homecache.h>
 #include <arch/opcode.h>
 
-#ifdef __tilegx__
-# define Elf_Rela Elf64_Rela
-# define ELF_R_SYM ELF64_R_SYM
-# define ELF_R_TYPE ELF64_R_TYPE
-#else
-# define Elf_Rela Elf32_Rela
-# define ELF_R_SYM ELF32_R_SYM
-# define ELF_R_TYPE ELF32_R_TYPE
-#endif
-
 #ifdef MODULE_DEBUG
 #define DEBUGP printk
 #else
index e5c5473e69cea62bc28dcc281e4fb9d1cfcca704..c4fbb21e802b15349e7bfb09d06484b6163169cc 100644 (file)
@@ -16,6 +16,8 @@ config UNICORE32
        select ARCH_WANT_FRAME_POINTERS
        select GENERIC_IOMAP
        select MODULES_USE_ELF_REL
+       select GENERIC_KERNEL_THREAD
+       select GENERIC_KERNEL_EXECVE
        help
          UniCore-32 is 32-bit Instruction Set Architecture,
          including a series of low-power-consumption RISC chip
@@ -64,6 +66,9 @@ config GENERIC_CALIBRATE_DELAY
 config ARCH_MAY_HAVE_PC_FDC
        bool
 
+config ZONE_DMA
+       def_bool y
+
 config NEED_DMA_MAP_STATE
        def_bool y
 
@@ -216,7 +221,7 @@ config PUV3_GPIO
        bool
        depends on !ARCH_FPGA
        select GENERIC_GPIO
-       select GPIO_SYSFS if EXPERIMENTAL
+       select GPIO_SYSFS
        default y
 
 if PUV3_NB0916
index c910c9857e114316991b2e9c711819a3939cdad5..601e92f18af6d85d5bb314733e409f97436df804 100644 (file)
@@ -1,4 +1,3 @@
-include include/asm-generic/Kbuild.asm
 
 generic-y += atomic.h
 generic-y += auxvec.h
index b1ff8cadb0866bf38ead0c95353c0020160a3c62..93a56f3e2344079b49de459ad08bb798ad9b7935 100644 (file)
@@ -19,9 +19,4 @@ extern void die(const char *msg, struct pt_regs *regs, int err);
 extern void uc32_notify_die(const char *str, struct pt_regs *regs,
                struct siginfo *info, unsigned long err, unsigned long trap);
 
-extern asmlinkage void __backtrace(void);
-extern asmlinkage void c_backtrace(unsigned long fp, int pmode);
-
-extern void __show_regs(struct pt_regs *);
-
 #endif /* __UNICORE_BUG_H__ */
diff --git a/arch/unicore32/include/asm/byteorder.h b/arch/unicore32/include/asm/byteorder.h
deleted file mode 100644 (file)
index ebe1b3f..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * linux/arch/unicore32/include/asm/byteorder.h
- *
- * Code specific to PKUnity SoC and UniCore ISA
- *
- * Copyright (C) 2001-2010 GUAN Xue-tao
- *
- * 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.
- *
- * UniCore ONLY support Little Endian mode, the data bus is connected such
- * that byte accesses appear as:
- *  0 = d0...d7, 1 = d8...d15, 2 = d16...d23, 3 = d24...d31
- * and word accesses (data or instruction) appear as:
- *  d0...d31
- */
-#ifndef __UNICORE_BYTEORDER_H__
-#define __UNICORE_BYTEORDER_H__
-
-#include <linux/byteorder/little_endian.h>
-
-#endif
-
index df4d5acfd19f96c9a10598a9230a0331fb7be798..8e797ad4fa24f52cbadb7b6a860a3b214d83eb3f 100644 (file)
@@ -35,7 +35,7 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
                        : "memory", "cc");
                break;
        default:
-               ret = __xchg_bad_pointer();
+               __xchg_bad_pointer();
        }
 
        return ret;
diff --git a/arch/unicore32/include/asm/kvm_para.h b/arch/unicore32/include/asm/kvm_para.h
deleted file mode 100644 (file)
index 14fab8f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/kvm_para.h>
index 14382cb09657f67333f5a32f4d95910ae10e0b1d..4eaa4216766772055849a3ffdb1b6e20d30edecb 100644 (file)
@@ -72,11 +72,6 @@ unsigned long get_wchan(struct task_struct *p);
 
 #define cpu_relax()                    barrier()
 
-/*
- * Create a new kernel thread
- */
-extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
-
 #define task_pt_regs(p) \
        ((struct pt_regs *)(THREAD_START_SP + task_stack_page(p)) - 1)
 
index b9caf9b0997b21952e5b8ecd26172e3933c8a97e..726749dab52fff679f6b787ff07498053f75e7e0 100644 (file)
 #ifndef __UNICORE_PTRACE_H__
 #define __UNICORE_PTRACE_H__
 
-#define PTRACE_GET_THREAD_AREA 22
-
-/*
- * PSR bits
- */
-#define USER_MODE      0x00000010
-#define REAL_MODE      0x00000011
-#define INTR_MODE      0x00000012
-#define PRIV_MODE      0x00000013
-#define ABRT_MODE      0x00000017
-#define EXTN_MODE      0x0000001b
-#define SUSR_MODE      0x0000001f
-#define MODE_MASK      0x0000001f
-#define PSR_R_BIT      0x00000040
-#define PSR_I_BIT      0x00000080
-#define PSR_V_BIT      0x10000000
-#define PSR_C_BIT      0x20000000
-#define PSR_Z_BIT      0x40000000
-#define PSR_S_BIT      0x80000000
-
-/*
- * Groups of PSR bits
- */
-#define PSR_f          0xff000000      /* Flags                */
-#define PSR_c          0x000000ff      /* Control              */
+#include <uapi/asm/ptrace.h>
 
 #ifndef __ASSEMBLY__
 
-/*
- * This struct defines the way the registers are stored on the
- * stack during a system call.  Note that sizeof(struct pt_regs)
- * has to be a multiple of 8.
- */
-struct pt_regs {
-       unsigned long uregs[34];
-};
-
-#define UCreg_asr              uregs[32]
-#define UCreg_pc               uregs[31]
-#define UCreg_lr               uregs[30]
-#define UCreg_sp               uregs[29]
-#define UCreg_ip               uregs[28]
-#define UCreg_fp               uregs[27]
-#define UCreg_26               uregs[26]
-#define UCreg_25               uregs[25]
-#define UCreg_24               uregs[24]
-#define UCreg_23               uregs[23]
-#define UCreg_22               uregs[22]
-#define UCreg_21               uregs[21]
-#define UCreg_20               uregs[20]
-#define UCreg_19               uregs[19]
-#define UCreg_18               uregs[18]
-#define UCreg_17               uregs[17]
-#define UCreg_16               uregs[16]
-#define UCreg_15               uregs[15]
-#define UCreg_14               uregs[14]
-#define UCreg_13               uregs[13]
-#define UCreg_12               uregs[12]
-#define UCreg_11               uregs[11]
-#define UCreg_10               uregs[10]
-#define UCreg_09               uregs[9]
-#define UCreg_08               uregs[8]
-#define UCreg_07               uregs[7]
-#define UCreg_06               uregs[6]
-#define UCreg_05               uregs[5]
-#define UCreg_04               uregs[4]
-#define UCreg_03               uregs[3]
-#define UCreg_02               uregs[2]
-#define UCreg_01               uregs[1]
-#define UCreg_00               uregs[0]
-#define UCreg_ORIG_00          uregs[33]
-
-#ifdef __KERNEL__
-
 #define user_mode(regs)        \
        (processor_mode(regs) == USER_MODE)
 
@@ -125,9 +55,5 @@ static inline int valid_user_regs(struct pt_regs *regs)
 
 #define instruction_pointer(regs)      ((regs)->UCreg_pc)
 
-#endif /* __KERNEL__ */
-
 #endif /* __ASSEMBLY__ */
-
 #endif
-
diff --git a/arch/unicore32/include/asm/sigcontext.h b/arch/unicore32/include/asm/sigcontext.h
deleted file mode 100644 (file)
index 6a2d767..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * linux/arch/unicore32/include/asm/sigcontext.h
- *
- * Code specific to PKUnity SoC and UniCore ISA
- *
- * Copyright (C) 2001-2010 GUAN Xue-tao
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#ifndef __UNICORE_SIGCONTEXT_H__
-#define __UNICORE_SIGCONTEXT_H__
-
-#include <asm/ptrace.h>
-/*
- * Signal context structure - contains all info to do with the state
- * before the signal handler was invoked.  Note: only add new entries
- * to the end of the structure.
- */
-struct sigcontext {
-       unsigned long trap_no;
-       unsigned long error_code;
-       unsigned long oldmask;
-       unsigned long fault_address;
-       struct pt_regs regs;
-};
-
-#endif
diff --git a/arch/unicore32/include/asm/unistd.h b/arch/unicore32/include/asm/unistd.h
deleted file mode 100644 (file)
index 2abcf61..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * linux/arch/unicore32/include/asm/unistd.h
- *
- * Code specific to PKUnity SoC and UniCore ISA
- *
- * Copyright (C) 2001-2010 GUAN Xue-tao
- *
- * 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.
- */
-
-/* Use the standard ABI for syscalls. */
-#include <asm-generic/unistd.h>
index baebb3da1d44160fc6f6f259886656e6f494b167..0514d7ad68551de6b0e7a7946263bfc6c6249ab0 100644 (file)
@@ -1,3 +1,10 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
 
+header-y += byteorder.h
+header-y += kvm_para.h
+header-y += ptrace.h
+header-y += sigcontext.h
+header-y += unistd.h
+
+generic-y += kvm_para.h
diff --git a/arch/unicore32/include/uapi/asm/byteorder.h b/arch/unicore32/include/uapi/asm/byteorder.h
new file mode 100644 (file)
index 0000000..ebe1b3f
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * linux/arch/unicore32/include/asm/byteorder.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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.
+ *
+ * UniCore ONLY support Little Endian mode, the data bus is connected such
+ * that byte accesses appear as:
+ *  0 = d0...d7, 1 = d8...d15, 2 = d16...d23, 3 = d24...d31
+ * and word accesses (data or instruction) appear as:
+ *  d0...d31
+ */
+#ifndef __UNICORE_BYTEORDER_H__
+#define __UNICORE_BYTEORDER_H__
+
+#include <linux/byteorder/little_endian.h>
+
+#endif
+
diff --git a/arch/unicore32/include/uapi/asm/ptrace.h b/arch/unicore32/include/uapi/asm/ptrace.h
new file mode 100644 (file)
index 0000000..187aa2e
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * linux/arch/unicore32/include/asm/ptrace.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef _UAPI__UNICORE_PTRACE_H__
+#define _UAPI__UNICORE_PTRACE_H__
+
+#define PTRACE_GET_THREAD_AREA 22
+
+/*
+ * PSR bits
+ */
+#define USER_MODE      0x00000010
+#define REAL_MODE      0x00000011
+#define INTR_MODE      0x00000012
+#define PRIV_MODE      0x00000013
+#define ABRT_MODE      0x00000017
+#define EXTN_MODE      0x0000001b
+#define SUSR_MODE      0x0000001f
+#define MODE_MASK      0x0000001f
+#define PSR_R_BIT      0x00000040
+#define PSR_I_BIT      0x00000080
+#define PSR_V_BIT      0x10000000
+#define PSR_C_BIT      0x20000000
+#define PSR_Z_BIT      0x40000000
+#define PSR_S_BIT      0x80000000
+
+/*
+ * Groups of PSR bits
+ */
+#define PSR_f          0xff000000      /* Flags                */
+#define PSR_c          0x000000ff      /* Control              */
+
+#ifndef __ASSEMBLY__
+
+/*
+ * This struct defines the way the registers are stored on the
+ * stack during a system call.  Note that sizeof(struct pt_regs)
+ * has to be a multiple of 8.
+ */
+struct pt_regs {
+       unsigned long uregs[34];
+};
+
+#define UCreg_asr              uregs[32]
+#define UCreg_pc               uregs[31]
+#define UCreg_lr               uregs[30]
+#define UCreg_sp               uregs[29]
+#define UCreg_ip               uregs[28]
+#define UCreg_fp               uregs[27]
+#define UCreg_26               uregs[26]
+#define UCreg_25               uregs[25]
+#define UCreg_24               uregs[24]
+#define UCreg_23               uregs[23]
+#define UCreg_22               uregs[22]
+#define UCreg_21               uregs[21]
+#define UCreg_20               uregs[20]
+#define UCreg_19               uregs[19]
+#define UCreg_18               uregs[18]
+#define UCreg_17               uregs[17]
+#define UCreg_16               uregs[16]
+#define UCreg_15               uregs[15]
+#define UCreg_14               uregs[14]
+#define UCreg_13               uregs[13]
+#define UCreg_12               uregs[12]
+#define UCreg_11               uregs[11]
+#define UCreg_10               uregs[10]
+#define UCreg_09               uregs[9]
+#define UCreg_08               uregs[8]
+#define UCreg_07               uregs[7]
+#define UCreg_06               uregs[6]
+#define UCreg_05               uregs[5]
+#define UCreg_04               uregs[4]
+#define UCreg_03               uregs[3]
+#define UCreg_02               uregs[2]
+#define UCreg_01               uregs[1]
+#define UCreg_00               uregs[0]
+#define UCreg_ORIG_00          uregs[33]
+
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _UAPI__UNICORE_PTRACE_H__ */
diff --git a/arch/unicore32/include/uapi/asm/sigcontext.h b/arch/unicore32/include/uapi/asm/sigcontext.h
new file mode 100644 (file)
index 0000000..6a2d767
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * linux/arch/unicore32/include/asm/sigcontext.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __UNICORE_SIGCONTEXT_H__
+#define __UNICORE_SIGCONTEXT_H__
+
+#include <asm/ptrace.h>
+/*
+ * Signal context structure - contains all info to do with the state
+ * before the signal handler was invoked.  Note: only add new entries
+ * to the end of the structure.
+ */
+struct sigcontext {
+       unsigned long trap_no;
+       unsigned long error_code;
+       unsigned long oldmask;
+       unsigned long fault_address;
+       struct pt_regs regs;
+};
+
+#endif
diff --git a/arch/unicore32/include/uapi/asm/unistd.h b/arch/unicore32/include/uapi/asm/unistd.h
new file mode 100644 (file)
index 0000000..d18a3be
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * linux/arch/unicore32/include/asm/unistd.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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.
+ */
+
+/* Use the standard ABI for syscalls. */
+#include <asm-generic/unistd.h>
+#define __ARCH_WANT_SYS_EXECVE
index dcb87ab19ddd8b5912dfa2d765c4158fa1bbad73..7049350c790fea708301996647e041431a8feef5 100644 (file)
@@ -573,17 +573,16 @@ ENDPROC(ret_to_user)
  */
 ENTRY(ret_from_fork)
        b.l     schedule_tail
-       get_thread_info tsk
-       ldw     r1, [tsk+], #TI_FLAGS           @ check for syscall tracing
-       mov     why, #1
-       cand.a  r1, #_TIF_SYSCALL_TRACE         @ are we tracing syscalls?
-       beq     ret_slow_syscall
-       mov     r1, sp
-       mov     r0, #1                          @ trace exit [IP = 1]
-       b.l     syscall_trace
        b       ret_slow_syscall
 ENDPROC(ret_from_fork)
 
+ENTRY(ret_from_kernel_thread)
+       b.l     schedule_tail
+       mov     r0, r5
+       adr     lr, ret_slow_syscall
+       mov     pc, r4
+ENDPROC(ret_from_kernel_thread)
+
 /*=============================================================================
  * SWI handler
  *-----------------------------------------------------------------------------
@@ -669,11 +668,6 @@ __cr_alignment:
 #endif
        .ltorg
 
-ENTRY(sys_execve)
-               add     r3, sp, #S_OFF
-               b       __sys_execve
-ENDPROC(sys_execve)
-
 ENTRY(sys_clone)
                add     ip, sp, #S_OFF
                stw     ip, [sp+], #4
index b008586dad753a1b29010735b95ee71e1a704900..a8fe265ce2c0fad25b2a2d330636b3ee05800392 100644 (file)
@@ -258,6 +258,7 @@ void release_thread(struct task_struct *dead_task)
 }
 
 asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
+asmlinkage void ret_from_kernel_thread(void) __asm__("ret_from_kernel_thread");
 
 int
 copy_thread(unsigned long clone_flags, unsigned long stack_start,
@@ -266,17 +267,22 @@ copy_thread(unsigned long clone_flags, unsigned long stack_start,
        struct thread_info *thread = task_thread_info(p);
        struct pt_regs *childregs = task_pt_regs(p);
 
-       *childregs = *regs;
-       childregs->UCreg_00 = 0;
-       childregs->UCreg_sp = stack_start;
-
        memset(&thread->cpu_context, 0, sizeof(struct cpu_context_save));
        thread->cpu_context.sp = (unsigned long)childregs;
-       thread->cpu_context.pc = (unsigned long)ret_from_fork;
-
-       if (clone_flags & CLONE_SETTLS)
-               childregs->UCreg_16 = regs->UCreg_03;
+       if (unlikely(!regs)) {
+               thread->cpu_context.pc = (unsigned long)ret_from_kernel_thread;
+               thread->cpu_context.r4 = stack_start;
+               thread->cpu_context.r5 = stk_sz;
+               memset(childregs, 0, sizeof(struct pt_regs));
+       } else {
+               thread->cpu_context.pc = (unsigned long)ret_from_fork;
+               *childregs = *regs;
+               childregs->UCreg_00 = 0;
+               childregs->UCreg_sp = stack_start;
 
+               if (clone_flags & CLONE_SETTLS)
+                       childregs->UCreg_16 = regs->UCreg_03;
+       }
        return 0;
 }
 
@@ -305,42 +311,6 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fp)
 }
 EXPORT_SYMBOL(dump_fpu);
 
-/*
- * Shuffle the argument into the correct register before calling the
- * thread function.  r1 is the thread argument, r2 is the pointer to
- * the thread function, and r3 points to the exit function.
- */
-asm(".pushsection .text\n"
-"      .align\n"
-"      .type   kernel_thread_helper, #function\n"
-"kernel_thread_helper:\n"
-"      mov.a   asr, r7\n"
-"      mov     r0, r4\n"
-"      mov     lr, r6\n"
-"      mov     pc, r5\n"
-"      .size   kernel_thread_helper, . - kernel_thread_helper\n"
-"      .popsection");
-
-/*
- * Create a kernel thread.
- */
-pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
-{
-       struct pt_regs regs;
-
-       memset(&regs, 0, sizeof(regs));
-
-       regs.UCreg_04 = (unsigned long)arg;
-       regs.UCreg_05 = (unsigned long)fn;
-       regs.UCreg_06 = (unsigned long)do_exit;
-       regs.UCreg_07 = PRIV_MODE;
-       regs.UCreg_pc = (unsigned long)kernel_thread_helper;
-       regs.UCreg_asr = regs.UCreg_07 | PSR_I_BIT;
-
-       return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
-}
-EXPORT_SYMBOL(kernel_thread);
-
 unsigned long get_wchan(struct task_struct *p)
 {
        struct stackframe frame;
index f23955028a183f70c0e0982ff934a06157bad659..30f749da8f7317ecf0613089ad0876f02ed533c7 100644 (file)
@@ -30,4 +30,10 @@ extern char __vectors_start[], __vectors_end[];
 extern void kernel_thread_helper(void);
 
 extern void __init early_signal_init(void);
+
+extern asmlinkage void __backtrace(void);
+extern asmlinkage void c_backtrace(unsigned long fp, int pmode);
+
+extern void __show_regs(struct pt_regs *);
+
 #endif
index fabdee96110b46821c911fa9de0be5ba30460b57..9680134b31f0ddd8a0be50f8dd2183a8392328c3 100644 (file)
@@ -42,69 +42,6 @@ asmlinkage long __sys_clone(unsigned long clone_flags, unsigned long newsp,
                        parent_tid, child_tid);
 }
 
-/* sys_execve() executes a new program.
- * This is called indirectly via a small wrapper
- */
-asmlinkage long __sys_execve(const char __user *filename,
-                         const char __user *const __user *argv,
-                         const char __user *const __user *envp,
-                         struct pt_regs *regs)
-{
-       int error;
-       struct filename *fn;
-
-       fn = getname(filename);
-       error = PTR_ERR(fn);
-       if (IS_ERR(fn))
-               goto out;
-       error = do_execve(fn->name, argv, envp, regs);
-       putname(fn);
-out:
-       return error;
-}
-
-int kernel_execve(const char *filename,
-                 const char *const argv[],
-                 const char *const envp[])
-{
-       struct pt_regs regs;
-       int ret;
-
-       memset(&regs, 0, sizeof(struct pt_regs));
-       ret = do_execve(filename,
-                       (const char __user *const __user *)argv,
-                       (const char __user *const __user *)envp, &regs);
-       if (ret < 0)
-               goto out;
-
-       /*
-        * Save argc to the register structure for userspace.
-        */
-       regs.UCreg_00 = ret;
-
-       /*
-        * We were successful.  We won't be returning to our caller, but
-        * instead to user space by manipulating the kernel stack.
-        */
-       asm("add        r0, %0, %1\n\t"
-               "mov    r1, %2\n\t"
-               "mov    r2, %3\n\t"
-               "mov    r22, #0\n\t"    /* not a syscall */
-               "mov    r23, %0\n\t"    /* thread structure */
-               "b.l    memmove\n\t"    /* copy regs to top of stack */
-               "mov    sp, r0\n\t"     /* reposition stack pointer */
-               "b      ret_to_user"
-               :
-               : "r" (current_thread_info()),
-                 "Ir" (THREAD_START_SP - sizeof(regs)),
-                 "r" (&regs),
-                 "Ir" (sizeof(regs))
-               : "r0", "r1", "r2", "r3", "ip", "lr", "memory");
-
- out:
-       return ret;
-}
-
 /* 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,
index 2eeb9c04cab057b5a2c6f542e251d6762cd6621b..f9b5c10bccee96e8838484aaf6effc39b3c89bd1 100644 (file)
@@ -168,7 +168,7 @@ static inline bool access_error(unsigned int fsr, struct vm_area_struct *vma)
 }
 
 static int __do_pf(struct mm_struct *mm, unsigned long addr, unsigned int fsr,
-               struct task_struct *tsk)
+               unsigned int flags, struct task_struct *tsk)
 {
        struct vm_area_struct *vma;
        int fault;
@@ -194,14 +194,7 @@ good_area:
         * If for any reason at all we couldn't handle the fault, make
         * sure we exit gracefully rather than endlessly redo the fault.
         */
-       fault = handle_mm_fault(mm, vma, addr & PAGE_MASK,
-                           (!(fsr ^ 0x12)) ? FAULT_FLAG_WRITE : 0);
-       if (unlikely(fault & VM_FAULT_ERROR))
-               return fault;
-       if (fault & VM_FAULT_MAJOR)
-               tsk->maj_flt++;
-       else
-               tsk->min_flt++;
+       fault = handle_mm_fault(mm, vma, addr & PAGE_MASK, flags);
        return fault;
 
 check_stack:
@@ -216,6 +209,8 @@ static int do_pf(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
        struct task_struct *tsk;
        struct mm_struct *mm;
        int fault, sig, code;
+       unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
+                                ((!(fsr ^ 0x12)) ? FAULT_FLAG_WRITE : 0);
 
        tsk = current;
        mm = tsk->mm;
@@ -236,6 +231,7 @@ static int do_pf(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
                if (!user_mode(regs)
                    && !search_exception_tables(regs->UCreg_pc))
                        goto no_context;
+retry:
                down_read(&mm->mmap_sem);
        } else {
                /*
@@ -251,7 +247,28 @@ static int do_pf(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
 #endif
        }
 
-       fault = __do_pf(mm, addr, fsr, tsk);
+       fault = __do_pf(mm, addr, fsr, flags, tsk);
+
+       /* If we need to retry but a fatal signal is pending, handle the
+        * signal first. We do not need to release the mmap_sem because
+        * it would already be released in __lock_page_or_retry in
+        * mm/filemap.c. */
+       if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
+               return 0;
+
+       if (!(fault & VM_FAULT_ERROR) && (flags & FAULT_FLAG_ALLOW_RETRY)) {
+               if (fault & VM_FAULT_MAJOR)
+                       tsk->maj_flt++;
+               else
+                       tsk->min_flt++;
+               if (fault & VM_FAULT_RETRY) {
+                       /* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk
+                       * of starvation. */
+                       flags &= ~FAULT_FLAG_ALLOW_RETRY;
+                       goto retry;
+               }
+       }
+
        up_read(&mm->mmap_sem);
 
        /*
index c760e073963ed59004f66ed65aade6355c852da9..e87b0cac14b5e5d735ab21f9f3b163db52349938 100644 (file)
@@ -12,6 +12,8 @@
 #include <asm/setup.h>
 #include <asm/desc.h>
 
+#undef memcpy                  /* Use memcpy from misc.c */
+
 #include "eboot.h"
 
 static efi_system_table_t *sys_table;
index 2a017441b8b2ebc665a24a001f5d635f7dbc9955..8c132a625b94991c179def21973bb8ad3c3a56d5 100644 (file)
@@ -476,6 +476,3 @@ die:
 setup_corrupt:
        .byte   7
        .string "No setup signature found...\n"
-
-       .data
-dummy: .long   0
index c9dcc181d4d1a814c10d6822d0801c7a1b2d7196..6e8fdf5ad1135c0100c8b7a5220bb79db2359ddb 100644 (file)
@@ -35,7 +35,7 @@ extern unsigned long asmlinkage efi_call_phys(void *, ...);
 #define efi_call_virt6(f, a1, a2, a3, a4, a5, a6)      \
        efi_call_virt(f, a1, a2, a3, a4, a5, a6)
 
-#define efi_ioremap(addr, size, type)          ioremap_cache(addr, size)
+#define efi_ioremap(addr, size, type, attr)    ioremap_cache(addr, size)
 
 #else /* !CONFIG_X86_32 */
 
@@ -89,7 +89,7 @@ extern u64 efi_call6(void *fp, u64 arg1, u64 arg2, u64 arg3,
                  (u64)(a3), (u64)(a4), (u64)(a5), (u64)(a6))
 
 extern void __iomem *efi_ioremap(unsigned long addr, unsigned long size,
-                                u32 type);
+                                u32 type, u64 attribute);
 
 #endif /* CONFIG_X86_32 */
 
@@ -98,6 +98,8 @@ extern void efi_set_executable(efi_memory_desc_t *md, bool executable);
 extern int efi_memblock_x86_reserve_range(void);
 extern void efi_call_phys_prelog(void);
 extern void efi_call_phys_epilog(void);
+extern void efi_unmap_memmap(void);
+extern void efi_memory_uc(u64 addr, unsigned long size);
 
 #ifndef CONFIG_EFI
 /*
index dcfde52979c3e63be0d42627cc567cf76c733090..19f16ebaf4fa826216c7858d224365b2fdb74670 100644 (file)
@@ -205,21 +205,14 @@ static inline bool user_64bit_mode(struct pt_regs *regs)
 }
 #endif
 
-/*
- * X86_32 CPUs don't save ss and esp if the CPU is already in kernel mode
- * when it traps.  The previous stack will be directly underneath the saved
- * registers, and 'sp/ss' won't even have been saved. Thus the '&regs->sp'.
- *
- * This is valid only for kernel mode traps.
- */
-static inline unsigned long kernel_stack_pointer(struct pt_regs *regs)
-{
 #ifdef CONFIG_X86_32
-       return (unsigned long)(&regs->sp);
+extern unsigned long kernel_stack_pointer(struct pt_regs *regs);
 #else
+static inline unsigned long kernel_stack_pointer(struct pt_regs *regs)
+{
        return regs->sp;
-#endif
 }
+#endif
 
 #define GET_IP(regs) ((regs)->ip)
 #define GET_FP(regs) ((regs)->bp)
index 59c226d120cdeccb6d8615e396f65b3ff2d4c050..c20d1ce62dc6a0a236280ab51b7ac8386fb1c32b 100644 (file)
@@ -359,18 +359,14 @@ HYPERVISOR_update_va_mapping(unsigned long va, pte_t new_val,
                return _hypercall4(int, update_va_mapping, va,
                                   new_val.pte, new_val.pte >> 32, flags);
 }
+extern int __must_check xen_event_channel_op_compat(int, void *);
 
 static inline int
 HYPERVISOR_event_channel_op(int cmd, void *arg)
 {
        int rc = _hypercall2(int, event_channel_op, cmd, arg);
-       if (unlikely(rc == -ENOSYS)) {
-               struct evtchn_op op;
-               op.cmd = cmd;
-               memcpy(&op.u, arg, sizeof(op.u));
-               rc = _hypercall1(int, event_channel_op_compat, &op);
-               memcpy(arg, &op.u, sizeof(op.u));
-       }
+       if (unlikely(rc == -ENOSYS))
+               rc = xen_event_channel_op_compat(cmd, arg);
        return rc;
 }
 
@@ -386,17 +382,14 @@ HYPERVISOR_console_io(int cmd, int count, char *str)
        return _hypercall3(int, console_io, cmd, count, str);
 }
 
+extern int __must_check HYPERVISOR_physdev_op_compat(int, void *);
+
 static inline int
 HYPERVISOR_physdev_op(int cmd, void *arg)
 {
        int rc = _hypercall2(int, physdev_op, cmd, arg);
-       if (unlikely(rc == -ENOSYS)) {
-               struct physdev_op op;
-               op.cmd = cmd;
-               memcpy(&op.u, arg, sizeof(op.u));
-               rc = _hypercall1(int, physdev_op_compat, &op);
-               memcpy(arg, &op.u, sizeof(op.u));
-       }
+       if (unlikely(rc == -ENOSYS))
+               rc = HYPERVISOR_physdev_op_compat(cmd, arg);
        return rc;
 }
 
index 66d0fff1ee8481ce0669cd5b0a137dde5d7dff8d..125f344f06a90e4d09dc4feab417042be9910e2a 100644 (file)
@@ -33,7 +33,6 @@
 #ifndef _ASM_X86_XEN_HYPERVISOR_H
 #define _ASM_X86_XEN_HYPERVISOR_H
 
-/* arch/i386/kernel/setup.c */
 extern struct shared_info *HYPERVISOR_shared_info;
 extern struct start_info *xen_start_info;
 
index 6d2f75a82a14bca62162f38cde9fff8e6404bec9..54d52ff1304a3496bc240ef193030adbb73ec4bb 100644 (file)
  * with Xen so that on ARM we can have one ABI that works for 32 and 64
  * bit guests. */
 typedef unsigned long xen_pfn_t;
+#define PRI_xen_pfn "lx"
 typedef unsigned long xen_ulong_t;
+#define PRI_xen_ulong "lx"
 /* Guest handles for primitive C types. */
 __DEFINE_GUEST_HANDLE(uchar, unsigned char);
 __DEFINE_GUEST_HANDLE(uint,  unsigned int);
-__DEFINE_GUEST_HANDLE(ulong, unsigned long);
 DEFINE_GUEST_HANDLE(char);
 DEFINE_GUEST_HANDLE(int);
-DEFINE_GUEST_HANDLE(long);
 DEFINE_GUEST_HANDLE(void);
 DEFINE_GUEST_HANDLE(uint64_t);
 DEFINE_GUEST_HANDLE(uint32_t);
index c265593ec2cdc3df35fda1586aaf91514fab62fa..1817fa911024f07151d3edf91bd350722c9f79f8 100644 (file)
@@ -2257,6 +2257,9 @@ asmlinkage void smp_irq_move_cleanup_interrupt(void)
                        continue;
 
                cfg = irq_cfg(irq);
+               if (!cfg)
+                       continue;
+
                raw_spin_lock(&desc->lock);
 
                /*
index f7e98a2c0d123ae0ebe7f61f1521f7dd7090a335..1b7d1656a042ff5e1886c6fff40bbde1ff3a472d 100644 (file)
@@ -631,6 +631,20 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
                }
        }
 
+       /*
+        * The way access filter has a performance penalty on some workloads.
+        * Disable it on the affected CPUs.
+        */
+       if ((c->x86 == 0x15) &&
+           (c->x86_model >= 0x02) && (c->x86_model < 0x20)) {
+               u64 val;
+
+               if (!rdmsrl_safe(0xc0011021, &val) && !(val & 0x1E)) {
+                       val |= 0x1E;
+                       wrmsrl_safe(0xc0011021, val);
+               }
+       }
+
        cpu_detect_cache_sizes(c);
 
        /* Multi core CPU? */
index 698b6ec12e0f40f9c292b9f84206b38214d9fe7e..1ac581f38dfa2771ba054c980cd9163546e8c9db 100644 (file)
@@ -6,7 +6,7 @@
  *
  *  Written by Jacob Shin - AMD, Inc.
  *
- *  Support: borislav.petkov@amd.com
+ *  Maintained by: Borislav Petkov <bp@alien8.de>
  *
  *  April 2006
  *     - added support for AMD Family 0x10 processors
index 5f88abf07e9ccc2237b27fea29c57b4b59315a64..4f9a3cbfc4a33fb801ab1bf2c822a83e76122897 100644 (file)
@@ -285,34 +285,39 @@ void cmci_clear(void)
        raw_spin_unlock_irqrestore(&cmci_discover_lock, flags);
 }
 
+static long cmci_rediscover_work_func(void *arg)
+{
+       int banks;
+
+       /* Recheck banks in case CPUs don't all have the same */
+       if (cmci_supported(&banks))
+               cmci_discover(banks);
+
+       return 0;
+}
+
 /*
  * After a CPU went down cycle through all the others and rediscover
  * Must run in process context.
  */
 void cmci_rediscover(int dying)
 {
-       int banks;
-       int cpu;
-       cpumask_var_t old;
+       int cpu, banks;
 
        if (!cmci_supported(&banks))
                return;
-       if (!alloc_cpumask_var(&old, GFP_KERNEL))
-               return;
-       cpumask_copy(old, &current->cpus_allowed);
 
        for_each_online_cpu(cpu) {
                if (cpu == dying)
                        continue;
-               if (set_cpus_allowed_ptr(current, cpumask_of(cpu)))
+
+               if (cpu == smp_processor_id()) {
+                       cmci_rediscover_work_func(NULL);
                        continue;
-               /* Recheck banks in case CPUs don't all have the same */
-               if (cmci_supported(&banks))
-                       cmci_discover(banks);
-       }
+               }
 
-       set_cpus_allowed_ptr(current, old);
-       free_cpumask_var(old);
+               work_on_cpu(cpu, cmci_rediscover_work_func, NULL);
+       }
 }
 
 /*
index 3373f84d139750276cf33a3a6bf757c171975a40..4a3374e61a93a033f24f03941b99c03e3906a726 100644 (file)
@@ -208,12 +208,14 @@ static bool check_hw_exists(void)
        }
 
        /*
-        * Now write a value and read it back to see if it matches,
-        * this is needed to detect certain hardware emulators (qemu/kvm)
-        * that don't trap on the MSR access and always return 0s.
+        * Read the current value, change it and read it back to see if it
+        * matches, this is needed to detect certain hardware emulators
+        * (qemu/kvm) that don't trap on the MSR access and always return 0s.
         */
-       val = 0xabcdUL;
        reg = x86_pmu_event_addr(0);
+       if (rdmsrl_safe(reg, &val))
+               goto msr_fail;
+       val ^= 0xffffUL;
        ret = wrmsrl_safe(reg, val);
        ret |= rdmsrl_safe(reg, &val_new);
        if (ret || val != val_new)
index 99d96a4978b56630115c2de5b465ca5eca0ffee0..3cf3d97cce3a7ab0b02c678f2535dc5ec03d09bb 100644 (file)
@@ -118,22 +118,24 @@ static void snbep_uncore_pci_disable_box(struct intel_uncore_box *box)
 {
        struct pci_dev *pdev = box->pci_dev;
        int box_ctl = uncore_pci_box_ctl(box);
-       u32 config;
+       u32 config = 0;
 
-       pci_read_config_dword(pdev, box_ctl, &config);
-       config |= SNBEP_PMON_BOX_CTL_FRZ;
-       pci_write_config_dword(pdev, box_ctl, config);
+       if (!pci_read_config_dword(pdev, box_ctl, &config)) {
+               config |= SNBEP_PMON_BOX_CTL_FRZ;
+               pci_write_config_dword(pdev, box_ctl, config);
+       }
 }
 
 static void snbep_uncore_pci_enable_box(struct intel_uncore_box *box)
 {
        struct pci_dev *pdev = box->pci_dev;
        int box_ctl = uncore_pci_box_ctl(box);
-       u32 config;
+       u32 config = 0;
 
-       pci_read_config_dword(pdev, box_ctl, &config);
-       config &= ~SNBEP_PMON_BOX_CTL_FRZ;
-       pci_write_config_dword(pdev, box_ctl, config);
+       if (!pci_read_config_dword(pdev, box_ctl, &config)) {
+               config &= ~SNBEP_PMON_BOX_CTL_FRZ;
+               pci_write_config_dword(pdev, box_ctl, config);
+       }
 }
 
 static void snbep_uncore_pci_enable_event(struct intel_uncore_box *box, struct perf_event *event)
@@ -156,7 +158,7 @@ static u64 snbep_uncore_pci_read_counter(struct intel_uncore_box *box, struct pe
 {
        struct pci_dev *pdev = box->pci_dev;
        struct hw_perf_event *hwc = &event->hw;
-       u64 count;
+       u64 count = 0;
 
        pci_read_config_dword(pdev, hwc->event_base, (u32 *)&count);
        pci_read_config_dword(pdev, hwc->event_base + 4, (u32 *)&count + 1);
@@ -603,11 +605,12 @@ static struct pci_driver snbep_uncore_pci_driver = {
 /*
  * build pci bus to socket mapping
  */
-static void snbep_pci2phy_map_init(void)
+static int snbep_pci2phy_map_init(void)
 {
        struct pci_dev *ubox_dev = NULL;
        int i, bus, nodeid;
-       u32 config;
+       int err = 0;
+       u32 config = 0;
 
        while (1) {
                /* find the UBOX device */
@@ -618,10 +621,14 @@ static void snbep_pci2phy_map_init(void)
                        break;
                bus = ubox_dev->bus->number;
                /* get the Node ID of the local register */
-               pci_read_config_dword(ubox_dev, 0x40, &config);
+               err = pci_read_config_dword(ubox_dev, 0x40, &config);
+               if (err)
+                       break;
                nodeid = config;
                /* get the Node ID mapping */
-               pci_read_config_dword(ubox_dev, 0x54, &config);
+               err = pci_read_config_dword(ubox_dev, 0x54, &config);
+               if (err)
+                       break;
                /*
                 * every three bits in the Node ID mapping register maps
                 * to a particular node.
@@ -633,7 +640,11 @@ static void snbep_pci2phy_map_init(void)
                        }
                }
        };
-       return;
+
+       if (ubox_dev)
+               pci_dev_put(ubox_dev);
+
+       return err ? pcibios_err_to_errno(err) : 0;
 }
 /* end of Sandy Bridge-EP uncore support */
 
@@ -1547,7 +1558,6 @@ void nhmex_rbox_alter_er(struct intel_uncore_box *box, struct perf_event *event)
 {
        struct hw_perf_event *hwc = &event->hw;
        struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
-       int port;
 
        /* adjust the main event selector and extra register index */
        if (reg1->idx % 2) {
@@ -1559,7 +1569,6 @@ void nhmex_rbox_alter_er(struct intel_uncore_box *box, struct perf_event *event)
        }
 
        /* adjust extra register config */
-       port = reg1->idx / 6 + box->pmu->pmu_idx * 4;
        switch (reg1->idx % 6) {
        case 2:
                /* shift the 8~15 bits to the 0~7 bits */
@@ -2578,9 +2587,11 @@ static int __init uncore_pci_init(void)
 
        switch (boot_cpu_data.x86_model) {
        case 45: /* Sandy Bridge-EP */
+               ret = snbep_pci2phy_map_init();
+               if (ret)
+                       return ret;
                pci_uncores = snbep_pci_uncores;
                uncore_pci_driver = &snbep_uncore_pci_driver;
-               snbep_pci2phy_map_init();
                break;
        default:
                return 0;
@@ -2926,6 +2937,9 @@ static int __init intel_uncore_init(void)
        if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
                return -ENODEV;
 
+       if (cpu_has_hypervisor)
+               return -ENODEV;
+
        ret = uncore_pci_init();
        if (ret)
                goto fail;
index 7c46bfdbc3732f87b005ecb7196a635eba5db546..4b7731bf23a812a4631aa7c53196068924b52ee7 100644 (file)
@@ -3,6 +3,8 @@
 #include <linux/perf_event.h>
 #include <linux/types.h>
 
+#include <asm/hardirq.h>
+
 #include "perf_event.h"
 
 static const u64 knc_perfmon_event_map[] =
@@ -173,30 +175,100 @@ static void knc_pmu_enable_all(int added)
 static inline void
 knc_pmu_disable_event(struct perf_event *event)
 {
-       struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
        struct hw_perf_event *hwc = &event->hw;
        u64 val;
 
        val = hwc->config;
-       if (cpuc->enabled)
-               val &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
+       val &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
 
        (void)wrmsrl_safe(hwc->config_base + hwc->idx, val);
 }
 
 static void knc_pmu_enable_event(struct perf_event *event)
 {
-       struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
        struct hw_perf_event *hwc = &event->hw;
        u64 val;
 
        val = hwc->config;
-       if (cpuc->enabled)
-               val |= ARCH_PERFMON_EVENTSEL_ENABLE;
+       val |= ARCH_PERFMON_EVENTSEL_ENABLE;
 
        (void)wrmsrl_safe(hwc->config_base + hwc->idx, val);
 }
 
+static inline u64 knc_pmu_get_status(void)
+{
+       u64 status;
+
+       rdmsrl(MSR_KNC_IA32_PERF_GLOBAL_STATUS, status);
+
+       return status;
+}
+
+static inline void knc_pmu_ack_status(u64 ack)
+{
+       wrmsrl(MSR_KNC_IA32_PERF_GLOBAL_OVF_CONTROL, ack);
+}
+
+static int knc_pmu_handle_irq(struct pt_regs *regs)
+{
+       struct perf_sample_data data;
+       struct cpu_hw_events *cpuc;
+       int handled = 0;
+       int bit, loops;
+       u64 status;
+
+       cpuc = &__get_cpu_var(cpu_hw_events);
+
+       knc_pmu_disable_all();
+
+       status = knc_pmu_get_status();
+       if (!status) {
+               knc_pmu_enable_all(0);
+               return handled;
+       }
+
+       loops = 0;
+again:
+       knc_pmu_ack_status(status);
+       if (++loops > 100) {
+               WARN_ONCE(1, "perf: irq loop stuck!\n");
+               perf_event_print_debug();
+               goto done;
+       }
+
+       inc_irq_stat(apic_perf_irqs);
+
+       for_each_set_bit(bit, (unsigned long *)&status, X86_PMC_IDX_MAX) {
+               struct perf_event *event = cpuc->events[bit];
+
+               handled++;
+
+               if (!test_bit(bit, cpuc->active_mask))
+                       continue;
+
+               if (!intel_pmu_save_and_restart(event))
+                       continue;
+
+               perf_sample_data_init(&data, 0, event->hw.last_period);
+
+               if (perf_event_overflow(event, &data, regs))
+                       x86_pmu_stop(event, 0);
+       }
+
+       /*
+        * Repeat if there is more work to be done:
+        */
+       status = knc_pmu_get_status();
+       if (status)
+               goto again;
+
+done:
+       knc_pmu_enable_all(0);
+
+       return handled;
+}
+
+
 PMU_FORMAT_ATTR(event, "config:0-7"    );
 PMU_FORMAT_ATTR(umask, "config:8-15"   );
 PMU_FORMAT_ATTR(edge,  "config:18"     );
@@ -214,7 +286,7 @@ static struct attribute *intel_knc_formats_attr[] = {
 
 static __initconst struct x86_pmu knc_pmu = {
        .name                   = "knc",
-       .handle_irq             = x86_pmu_handle_irq,
+       .handle_irq             = knc_pmu_handle_irq,
        .disable_all            = knc_pmu_disable_all,
        .enable_all             = knc_pmu_enable_all,
        .enable                 = knc_pmu_enable_event,
@@ -226,12 +298,11 @@ static __initconst struct x86_pmu knc_pmu = {
        .event_map              = knc_pmu_event_map,
        .max_events             = ARRAY_SIZE(knc_perfmon_event_map),
        .apic                   = 1,
-       .max_period             = (1ULL << 31) - 1,
+       .max_period             = (1ULL << 39) - 1,
        .version                = 0,
        .num_counters           = 2,
-       /* in theory 40 bits, early silicon is buggy though */
-       .cntval_bits            = 32,
-       .cntval_mask            = (1ULL << 32) - 1,
+       .cntval_bits            = 40,
+       .cntval_mask            = (1ULL << 40) - 1,
        .get_event_constraints  = x86_get_event_constraints,
        .event_constraints      = knc_event_constraints,
        .format_attrs           = intel_knc_formats_attr,
index e4dd0f7a04535f09b83d47d95868bcc1c152dff3..7d0270bd793ebd8580d63e21a1be521b2aeea91f 100644 (file)
  */
 static const u64 p6_perfmon_event_map[] =
 {
-  [PERF_COUNT_HW_CPU_CYCLES]           = 0x0079,
-  [PERF_COUNT_HW_INSTRUCTIONS]         = 0x00c0,
-  [PERF_COUNT_HW_CACHE_REFERENCES]     = 0x0f2e,
-  [PERF_COUNT_HW_CACHE_MISSES]         = 0x012e,
-  [PERF_COUNT_HW_BRANCH_INSTRUCTIONS]  = 0x00c4,
-  [PERF_COUNT_HW_BRANCH_MISSES]                = 0x00c5,
-  [PERF_COUNT_HW_BUS_CYCLES]           = 0x0062,
+  [PERF_COUNT_HW_CPU_CYCLES]           = 0x0079,       /* CPU_CLK_UNHALTED */
+  [PERF_COUNT_HW_INSTRUCTIONS]         = 0x00c0,       /* INST_RETIRED     */
+  [PERF_COUNT_HW_CACHE_REFERENCES]     = 0x0f2e,       /* L2_RQSTS:M:E:S:I */
+  [PERF_COUNT_HW_CACHE_MISSES]         = 0x012e,       /* L2_RQSTS:I       */
+  [PERF_COUNT_HW_BRANCH_INSTRUCTIONS]  = 0x00c4,       /* BR_INST_RETIRED  */
+  [PERF_COUNT_HW_BRANCH_MISSES]                = 0x00c5,       /* BR_MISS_PRED_RETIRED */
+  [PERF_COUNT_HW_BUS_CYCLES]           = 0x0062,       /* BUS_DRDY_CLOCKS  */
+  [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = 0x00a2,    /* RESOURCE_STALLS  */
+
+};
+
+static __initconst u64 p6_hw_cache_event_ids
+                               [PERF_COUNT_HW_CACHE_MAX]
+                               [PERF_COUNT_HW_CACHE_OP_MAX]
+                               [PERF_COUNT_HW_CACHE_RESULT_MAX] =
+{
+ [ C(L1D) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0043,  /* DATA_MEM_REFS       */
+                [ C(RESULT_MISS)   ] = 0x0045, /* DCU_LINES_IN        */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0x0f29,  /* L2_LD:M:E:S:I       */
+       },
+        [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0,
+        },
+ },
+ [ C(L1I ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0080,  /* IFU_IFETCH         */
+               [ C(RESULT_MISS)   ] = 0x0f28,  /* L2_IFETCH:M:E:S:I  */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0,
+       },
+ },
+ [ C(LL  ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0,
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0x0025,  /* L2_M_LINES_INM     */
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0,
+       },
+ },
+ [ C(DTLB) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0043,  /* DATA_MEM_REFS      */
+               [ C(RESULT_MISS)   ] = 0,
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0,
+       },
+ },
+ [ C(ITLB) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0080,  /* IFU_IFETCH         */
+               [ C(RESULT_MISS)   ] = 0x0085,  /* ITLB_MISS          */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+ },
+ [ C(BPU ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x00c4,  /* BR_INST_RETIRED      */
+               [ C(RESULT_MISS)   ] = 0x00c5,  /* BR_MISS_PRED_RETIRED */
+        },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+ },
 };
 
 static u64 p6_pmu_event_map(int hw_event)
@@ -34,7 +127,7 @@ static struct event_constraint p6_event_constraints[] =
 {
        INTEL_EVENT_CONSTRAINT(0xc1, 0x1),      /* FLOPS */
        INTEL_EVENT_CONSTRAINT(0x10, 0x1),      /* FP_COMP_OPS_EXE */
-       INTEL_EVENT_CONSTRAINT(0x11, 0x1),      /* FP_ASSIST */
+       INTEL_EVENT_CONSTRAINT(0x11, 0x2),      /* FP_ASSIST */
        INTEL_EVENT_CONSTRAINT(0x12, 0x2),      /* MUL */
        INTEL_EVENT_CONSTRAINT(0x13, 0x2),      /* DIV */
        INTEL_EVENT_CONSTRAINT(0x14, 0x1),      /* CYCLES_DIV_BUSY */
@@ -64,25 +157,25 @@ static void p6_pmu_enable_all(int added)
 static inline void
 p6_pmu_disable_event(struct perf_event *event)
 {
-       struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
        struct hw_perf_event *hwc = &event->hw;
        u64 val = P6_NOP_EVENT;
 
-       if (cpuc->enabled)
-               val |= ARCH_PERFMON_EVENTSEL_ENABLE;
-
        (void)wrmsrl_safe(hwc->config_base, val);
 }
 
 static void p6_pmu_enable_event(struct perf_event *event)
 {
-       struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
        struct hw_perf_event *hwc = &event->hw;
        u64 val;
 
        val = hwc->config;
-       if (cpuc->enabled)
-               val |= ARCH_PERFMON_EVENTSEL_ENABLE;
+
+       /*
+        * p6 only has a global event enable, set on PerfEvtSel0
+        * We "disable" events by programming P6_NOP_EVENT
+        * and we rely on p6_pmu_enable_all() being called
+        * to actually enable the events.
+        */
 
        (void)wrmsrl_safe(hwc->config_base, val);
 }
@@ -158,5 +251,9 @@ __init int p6_pmu_init(void)
 
        x86_pmu = p6_pmu;
 
+       memcpy(hw_cache_event_ids, p6_hw_cache_event_ids,
+               sizeof(hw_cache_event_ids));
+
+
        return 0;
 }
index ed858e9e9a7461aa9b4f8aa42a52c79d57d84507..df06ade26bef8485af1a66d797370385d0012e52 100644 (file)
@@ -1077,6 +1077,9 @@ void __init memblock_x86_fill(void)
                memblock_add(ei->addr, ei->size);
        }
 
+       /* throw away partial pages */
+       memblock_trim_memory(PAGE_SIZE);
+
        memblock_dump_all();
 }
 
index a1193aef6d7d2ef1af31a4b257ed0e161876ad19..88b725aa1d52463d7534882a187da4c392bf3947 100644 (file)
@@ -1035,7 +1035,7 @@ ENTRY(xen_sysenter_target)
 
 ENTRY(xen_hypervisor_callback)
        CFI_STARTPROC
-       pushl_cfi $0
+       pushl_cfi $-1 /* orig_ax = -1 => not a system call */
        SAVE_ALL
        TRACE_IRQS_OFF
 
@@ -1077,14 +1077,16 @@ ENTRY(xen_failsafe_callback)
 2:     mov 8(%esp),%es
 3:     mov 12(%esp),%fs
 4:     mov 16(%esp),%gs
+       /* EAX == 0 => Category 1 (Bad segment)
+          EAX != 0 => Category 2 (Bad IRET) */
        testl %eax,%eax
        popl_cfi %eax
        lea 16(%esp),%esp
        CFI_ADJUST_CFA_OFFSET -16
        jz 5f
        addl $16,%esp
-       jmp iret_exc            # EAX != 0 => Category 2 (Bad IRET)
-5:     pushl_cfi $0            # EAX == 0 => Category 1 (Bad segment)
+       jmp iret_exc
+5:     pushl_cfi $-1 /* orig_ax = -1 => not a system call */
        SAVE_ALL
        jmp ret_from_exception
        CFI_ENDPROC
index 0c58952d64e8723b4486ce620c8b11bcfe8d01f5..1328fe49a3f14d7a33615e892efca8d110aeb6e6 100644 (file)
@@ -995,8 +995,8 @@ END(interrupt)
         */
        .p2align CONFIG_X86_L1_CACHE_SHIFT
 common_interrupt:
-       ASM_CLAC
        XCPT_FRAME
+       ASM_CLAC
        addq $-0x80,(%rsp)              /* Adjust vector to [-256,-1] range */
        interrupt do_IRQ
        /* 0(%rsp): old_rsp-ARGOFFSET */
@@ -1135,8 +1135,8 @@ END(common_interrupt)
  */
 .macro apicinterrupt num sym do_sym
 ENTRY(\sym)
-       ASM_CLAC
        INTR_FRAME
+       ASM_CLAC
        pushq_cfi $~(\num)
 .Lcommon_\sym:
        interrupt \do_sym
@@ -1190,8 +1190,8 @@ apicinterrupt IRQ_WORK_VECTOR \
  */
 .macro zeroentry sym do_sym
 ENTRY(\sym)
-       ASM_CLAC
        INTR_FRAME
+       ASM_CLAC
        PARAVIRT_ADJUST_EXCEPTION_FRAME
        pushq_cfi $-1           /* ORIG_RAX: no syscall to restart */
        subq $ORIG_RAX-R15, %rsp
@@ -1208,8 +1208,8 @@ END(\sym)
 
 .macro paranoidzeroentry sym do_sym
 ENTRY(\sym)
-       ASM_CLAC
        INTR_FRAME
+       ASM_CLAC
        PARAVIRT_ADJUST_EXCEPTION_FRAME
        pushq_cfi $-1           /* ORIG_RAX: no syscall to restart */
        subq $ORIG_RAX-R15, %rsp
@@ -1227,8 +1227,8 @@ END(\sym)
 #define INIT_TSS_IST(x) PER_CPU_VAR(init_tss) + (TSS_ist + ((x) - 1) * 8)
 .macro paranoidzeroentry_ist sym do_sym ist
 ENTRY(\sym)
-       ASM_CLAC
        INTR_FRAME
+       ASM_CLAC
        PARAVIRT_ADJUST_EXCEPTION_FRAME
        pushq_cfi $-1           /* ORIG_RAX: no syscall to restart */
        subq $ORIG_RAX-R15, %rsp
@@ -1247,8 +1247,8 @@ END(\sym)
 
 .macro errorentry sym do_sym
 ENTRY(\sym)
-       ASM_CLAC
        XCPT_FRAME
+       ASM_CLAC
        PARAVIRT_ADJUST_EXCEPTION_FRAME
        subq $ORIG_RAX-R15, %rsp
        CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15
@@ -1266,8 +1266,8 @@ END(\sym)
        /* error code is on the stack already */
 .macro paranoiderrorentry sym do_sym
 ENTRY(\sym)
-       ASM_CLAC
        XCPT_FRAME
+       ASM_CLAC
        PARAVIRT_ADJUST_EXCEPTION_FRAME
        subq $ORIG_RAX-R15, %rsp
        CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15
@@ -1435,7 +1435,7 @@ ENTRY(xen_failsafe_callback)
        CFI_RESTORE r11
        addq $0x30,%rsp
        CFI_ADJUST_CFA_OFFSET -0x30
-       pushq_cfi $0
+       pushq_cfi $-1 /* orig_ax = -1 => not a system call */
        SAVE_ALL
        jmp error_exit
        CFI_ENDPROC
index b3e5e51bc907ef4da71549ff7e2214467721af0a..4180a874c764d4df9d514648082eee5ac6907930 100644 (file)
@@ -247,7 +247,10 @@ do_async_page_fault(struct pt_regs *regs, unsigned long error_code)
                break;
        case KVM_PV_REASON_PAGE_NOT_PRESENT:
                /* page is swapped out by the host. */
+               rcu_irq_enter();
+               exit_idle();
                kvm_async_pf_task_wait((u32)read_cr2());
+               rcu_irq_exit();
                break;
        case KVM_PV_REASON_PAGE_READY:
                rcu_irq_enter();
index 7720ff5a9ee292a449ad13a9347e603def50df53..efdec7cd8e01057aeee63c95b16713c4803c7e61 100644 (file)
@@ -8,8 +8,8 @@
  *  Tigran Aivazian <tigran@aivazian.fsnet.co.uk>
  *
  *  Maintainers:
- *  Andreas Herrmann <andreas.herrmann3@amd.com>
- *  Borislav Petkov <borislav.petkov@amd.com>
+ *  Andreas Herrmann <herrmann.der.user@googlemail.com>
+ *  Borislav Petkov <bp@alien8.de>
  *
  *  This driver allows to upgrade microcode on F10h AMD
  *  CPUs and later.
@@ -190,6 +190,7 @@ static unsigned int verify_patch_size(int cpu, u32 patch_size,
 #define F1XH_MPB_MAX_SIZE 2048
 #define F14H_MPB_MAX_SIZE 1824
 #define F15H_MPB_MAX_SIZE 4096
+#define F16H_MPB_MAX_SIZE 3458
 
        switch (c->x86) {
        case 0x14:
@@ -198,6 +199,9 @@ static unsigned int verify_patch_size(int cpu, u32 patch_size,
        case 0x15:
                max_size = F15H_MPB_MAX_SIZE;
                break;
+       case 0x16:
+               max_size = F16H_MPB_MAX_SIZE;
+               break;
        default:
                max_size = F1XH_MPB_MAX_SIZE;
                break;
index b00b33a183908bdb201aa38266e40ad87d89754d..5e0596b0632e244676c686bb0b338ea1e255473f 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/perf_event.h>
 #include <linux/hw_breakpoint.h>
 #include <linux/rcupdate.h>
+#include <linux/module.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -166,6 +167,35 @@ static inline bool invalid_selector(u16 value)
 
 #define FLAG_MASK              FLAG_MASK_32
 
+/*
+ * X86_32 CPUs don't save ss and esp if the CPU is already in kernel mode
+ * when it traps.  The previous stack will be directly underneath the saved
+ * registers, and 'sp/ss' won't even have been saved. Thus the '&regs->sp'.
+ *
+ * Now, if the stack is empty, '&regs->sp' is out of range. In this
+ * case we try to take the previous stack. To always return a non-null
+ * stack pointer we fall back to regs as stack if no previous stack
+ * exists.
+ *
+ * This is valid only for kernel mode traps.
+ */
+unsigned long kernel_stack_pointer(struct pt_regs *regs)
+{
+       unsigned long context = (unsigned long)regs & ~(THREAD_SIZE - 1);
+       unsigned long sp = (unsigned long)&regs->sp;
+       struct thread_info *tinfo;
+
+       if (context == (sp & ~(THREAD_SIZE - 1)))
+               return sp;
+
+       tinfo = (struct thread_info *)context;
+       if (tinfo->previous_esp)
+               return tinfo->previous_esp;
+
+       return (unsigned long)regs;
+}
+EXPORT_SYMBOL_GPL(kernel_stack_pointer);
+
 static unsigned long *pt_regs_access(struct pt_regs *regs, unsigned long regno)
 {
        BUILD_BUG_ON(offsetof(struct pt_regs, bx) != 0);
index 468e98dfd44e72fd7d0b29690b4bb777356a52a5..ca45696f30fb8a01a4d6852388d08ab19d4bb778 100644 (file)
@@ -921,18 +921,19 @@ void __init setup_arch(char **cmdline_p)
 #ifdef CONFIG_X86_64
        if (max_pfn > max_low_pfn) {
                int i;
-               for (i = 0; i < e820.nr_map; i++) {
-                       struct e820entry *ei = &e820.map[i];
+               unsigned long start, end;
+               unsigned long start_pfn, end_pfn;
 
-                       if (ei->addr + ei->size <= 1UL << 32)
-                               continue;
+               for_each_mem_pfn_range(i, MAX_NUMNODES, &start_pfn, &end_pfn,
+                                                        NULL) {
 
-                       if (ei->type == E820_RESERVED)
+                       end = PFN_PHYS(end_pfn);
+                       if (end <= (1UL<<32))
                                continue;
 
+                       start = PFN_PHYS(start_pfn);
                        max_pfn_mapped = init_memory_mapping(
-                               ei->addr < 1UL << 32 ? 1UL << 32 : ei->addr,
-                               ei->addr + ei->size);
+                                               max((1UL<<32), start), end);
                }
 
                /* can we preseve max_low_pfn ?*/
@@ -1048,6 +1049,18 @@ void __init setup_arch(char **cmdline_p)
        arch_init_ideal_nops();
 
        register_refined_jiffies(CLOCK_TICK_RATE);
+
+#ifdef CONFIG_EFI
+       /* Once setup is done above, disable efi_enabled on mismatched
+        * firmware/kernel archtectures since there is no support for
+        * runtime services.
+        */
+       if (efi_enabled && IS_ENABLED(CONFIG_X86_64) != efi_64bit) {
+               pr_info("efi: Setup done, disabling due to 32/64-bit mismatch\n");
+               efi_unmap_memmap();
+               efi_enabled = 0;
+       }
+#endif
 }
 
 #ifdef CONFIG_X86_32
index 29ad351804e9324d3aaf59c07c86d274958516b3..70b27ee6118e12c8411c7903e2254aeff44cd90e 100644 (file)
@@ -824,10 +824,8 @@ do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags)
                mce_notify_process();
 #endif /* CONFIG_X86_64 && CONFIG_X86_MCE */
 
-       if (thread_info_flags & _TIF_UPROBE) {
-               clear_thread_flag(TIF_UPROBE);
+       if (thread_info_flags & _TIF_UPROBE)
                uprobe_notify_resume(regs);
-       }
 
        /* deal with pending signal delivery */
        if (thread_info_flags & _TIF_SIGPENDING)
index 9538f00827a9b25257debf63aaa438ef6e40d68b..aafa5557b3964a57bf0abbdd9c849786688f1ce9 100644 (file)
@@ -651,31 +651,19 @@ void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
 
 /*
  * Skip these instructions as per the currently known x86 ISA.
- * 0x66* { 0x90 | 0x0f 0x1f | 0x0f 0x19 | 0x87 0xc0 }
+ * rep=0x66*; nop=0x90
  */
 static bool __skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
 {
        int i;
 
        for (i = 0; i < MAX_UINSN_BYTES; i++) {
-               if ((auprobe->insn[i] == 0x66))
+               if (auprobe->insn[i] == 0x66)
                        continue;
 
                if (auprobe->insn[i] == 0x90)
                        return true;
 
-               if (i == (MAX_UINSN_BYTES - 1))
-                       break;
-
-               if ((auprobe->insn[i] == 0x0f) && (auprobe->insn[i+1] == 0x1f))
-                       return true;
-
-               if ((auprobe->insn[i] == 0x0f) && (auprobe->insn[i+1] == 0x19))
-                       return true;
-
-               if ((auprobe->insn[i] == 0x87) && (auprobe->insn[i+1] == 0xc0))
-                       return true;
-
                break;
        }
        return false;
index a10e4601685135f0b5da599508be35eb754816ec..58fc5148882857c014a49b78403a597424c08e64 100644 (file)
@@ -24,6 +24,9 @@ static inline bool guest_cpuid_has_xsave(struct kvm_vcpu *vcpu)
 {
        struct kvm_cpuid_entry2 *best;
 
+       if (!static_cpu_has(X86_FEATURE_XSAVE))
+               return 0;
+
        best = kvm_find_cpuid_entry(vcpu, 1, 0);
        return best && (best->ecx & bit(X86_FEATURE_XSAVE));
 }
index c6e6b721b6ee3a38d6267ee8867bd029fbdc6d6a..43e9fadca5d080a4e98a65735cbe071102742911 100644 (file)
@@ -1311,7 +1311,7 @@ void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value)
        vcpu->arch.apic_base = value;
        if (apic_x2apic_mode(apic)) {
                u32 id = kvm_apic_id(apic);
-               u32 ldr = ((id & ~0xf) << 16) | (1 << (id & 0xf));
+               u32 ldr = ((id >> 4) << 16) | (1 << (id & 0xf));
                kvm_apic_set_ldr(apic, ldr);
        }
        apic->base_address = apic->vcpu->arch.apic_base &
index d289fee1ffb8631c0b93f663104965fe7def7b11..6f85fe0bf958987f0275f1fa25e2b9e5240aad02 100644 (file)
@@ -2497,8 +2497,7 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *sptep,
                }
        }
 
-       if (!is_error_pfn(pfn))
-               kvm_release_pfn_clean(pfn);
+       kvm_release_pfn_clean(pfn);
 }
 
 static void nonpaging_new_cr3(struct kvm_vcpu *vcpu)
index ad6b1dd06f8b967356d4f081f4cde119f2a2bfe8..f85815945fc6d62532c9735747759452cbe7c101 100644 (file)
@@ -6549,19 +6549,22 @@ static void vmx_cpuid_update(struct kvm_vcpu *vcpu)
                }
        }
 
-       exec_control = vmcs_read32(SECONDARY_VM_EXEC_CONTROL);
        /* Exposing INVPCID only when PCID is exposed */
        best = kvm_find_cpuid_entry(vcpu, 0x7, 0);
        if (vmx_invpcid_supported() &&
            best && (best->ebx & bit(X86_FEATURE_INVPCID)) &&
            guest_cpuid_has_pcid(vcpu)) {
+               exec_control = vmcs_read32(SECONDARY_VM_EXEC_CONTROL);
                exec_control |= SECONDARY_EXEC_ENABLE_INVPCID;
                vmcs_write32(SECONDARY_VM_EXEC_CONTROL,
                             exec_control);
        } else {
-               exec_control &= ~SECONDARY_EXEC_ENABLE_INVPCID;
-               vmcs_write32(SECONDARY_VM_EXEC_CONTROL,
-                            exec_control);
+               if (cpu_has_secondary_exec_ctrls()) {
+                       exec_control = vmcs_read32(SECONDARY_VM_EXEC_CONTROL);
+                       exec_control &= ~SECONDARY_EXEC_ENABLE_INVPCID;
+                       vmcs_write32(SECONDARY_VM_EXEC_CONTROL,
+                                    exec_control);
+               }
                if (best)
                        best->ebx &= ~bit(X86_FEATURE_INVPCID);
        }
index 1eefebe5d72758873df0d13e4ae8c686a7d016ee..4f7641756be2d046cd55e3d59de76e145d3c39ae 100644 (file)
@@ -3779,7 +3779,7 @@ static int write_exit_mmio(struct kvm_vcpu *vcpu, gpa_t gpa,
 {
        struct kvm_mmio_fragment *frag = &vcpu->mmio_fragments[0];
 
-       memcpy(vcpu->run->mmio.data, frag->data, frag->len);
+       memcpy(vcpu->run->mmio.data, frag->data, min(8u, frag->len));
        return X86EMUL_CONTINUE;
 }
 
@@ -3832,18 +3832,11 @@ mmio:
        bytes -= handled;
        val += handled;
 
-       while (bytes) {
-               unsigned now = min(bytes, 8U);
-
-               frag = &vcpu->mmio_fragments[vcpu->mmio_nr_fragments++];
-               frag->gpa = gpa;
-               frag->data = val;
-               frag->len = now;
-
-               gpa += now;
-               val += now;
-               bytes -= now;
-       }
+       WARN_ON(vcpu->mmio_nr_fragments >= KVM_MAX_MMIO_FRAGMENTS);
+       frag = &vcpu->mmio_fragments[vcpu->mmio_nr_fragments++];
+       frag->gpa = gpa;
+       frag->data = val;
+       frag->len = bytes;
        return X86EMUL_CONTINUE;
 }
 
@@ -3890,7 +3883,7 @@ int emulator_read_write(struct x86_emulate_ctxt *ctxt, unsigned long addr,
        vcpu->mmio_needed = 1;
        vcpu->mmio_cur_fragment = 0;
 
-       vcpu->run->mmio.len = vcpu->mmio_fragments[0].len;
+       vcpu->run->mmio.len = min(8u, vcpu->mmio_fragments[0].len);
        vcpu->run->mmio.is_write = vcpu->mmio_is_write = ops->write;
        vcpu->run->exit_reason = KVM_EXIT_MMIO;
        vcpu->run->mmio.phys_addr = gpa;
@@ -5522,28 +5515,44 @@ static int complete_emulated_pio(struct kvm_vcpu *vcpu)
  *
  * read:
  *   for each fragment
- *     write gpa, len
- *     exit
- *     copy data
+ *     for each mmio piece in the fragment
+ *       write gpa, len
+ *       exit
+ *       copy data
  *   execute insn
  *
  * write:
  *   for each fragment
- *      write gpa, len
- *      copy data
- *      exit
+ *     for each mmio piece in the fragment
+ *       write gpa, len
+ *       copy data
+ *       exit
  */
 static int complete_emulated_mmio(struct kvm_vcpu *vcpu)
 {
        struct kvm_run *run = vcpu->run;
        struct kvm_mmio_fragment *frag;
+       unsigned len;
 
        BUG_ON(!vcpu->mmio_needed);
 
        /* Complete previous fragment */
-       frag = &vcpu->mmio_fragments[vcpu->mmio_cur_fragment++];
+       frag = &vcpu->mmio_fragments[vcpu->mmio_cur_fragment];
+       len = min(8u, frag->len);
        if (!vcpu->mmio_is_write)
-               memcpy(frag->data, run->mmio.data, frag->len);
+               memcpy(frag->data, run->mmio.data, len);
+
+       if (frag->len <= 8) {
+               /* Switch to the next fragment. */
+               frag++;
+               vcpu->mmio_cur_fragment++;
+       } else {
+               /* Go forward to the next mmio piece. */
+               frag->data += len;
+               frag->gpa += len;
+               frag->len -= len;
+       }
+
        if (vcpu->mmio_cur_fragment == vcpu->mmio_nr_fragments) {
                vcpu->mmio_needed = 0;
                if (vcpu->mmio_is_write)
@@ -5551,13 +5560,12 @@ static int complete_emulated_mmio(struct kvm_vcpu *vcpu)
                vcpu->mmio_read_completed = 1;
                return complete_emulated_io(vcpu);
        }
-       /* Initiate next fragment */
-       ++frag;
+
        run->exit_reason = KVM_EXIT_MMIO;
        run->mmio.phys_addr = frag->gpa;
        if (vcpu->mmio_is_write)
-               memcpy(run->mmio.data, frag->data, frag->len);
-       run->mmio.len = frag->len;
+               memcpy(run->mmio.data, frag->data, min(8u, frag->len));
+       run->mmio.len = min(8u, frag->len);
        run->mmio.is_write = vcpu->mmio_is_write;
        vcpu->arch.complete_userspace_io = complete_emulated_mmio;
        return 0;
@@ -5773,6 +5781,9 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
        int pending_vec, max_bits, idx;
        struct desc_ptr dt;
 
+       if (!guest_cpuid_has_xsave(vcpu) && (sregs->cr4 & X86_CR4_OSXSAVE))
+               return -EINVAL;
+
        dt.size = sregs->idt.limit;
        dt.address = sregs->idt.base;
        kvm_x86_ops->set_idt(vcpu, &dt);
index ab1f6a93b527c9bd50acc12a52e9ce157f2cc48b..d7aea41563b372437eb227a499259be23d755564 100644 (file)
@@ -35,40 +35,44 @@ struct map_range {
        unsigned page_size_mask;
 };
 
-static void __init find_early_table_space(struct map_range *mr, unsigned long end,
-                                         int use_pse, int use_gbpages)
+/*
+ * First calculate space needed for kernel direct mapping page tables to cover
+ * mr[0].start to mr[nr_range - 1].end, while accounting for possible 2M and 1GB
+ * pages. Then find enough contiguous space for those page tables.
+ */
+static void __init find_early_table_space(struct map_range *mr, int nr_range)
 {
-       unsigned long puds, pmds, ptes, tables, start = 0, good_end = end;
+       int i;
+       unsigned long puds = 0, pmds = 0, ptes = 0, tables;
+       unsigned long start = 0, good_end;
        phys_addr_t base;
 
-       puds = (end + PUD_SIZE - 1) >> PUD_SHIFT;
-       tables = roundup(puds * sizeof(pud_t), PAGE_SIZE);
-
-       if (use_gbpages) {
-               unsigned long extra;
-
-               extra = end - ((end>>PUD_SHIFT) << PUD_SHIFT);
-               pmds = (extra + PMD_SIZE - 1) >> PMD_SHIFT;
-       } else
-               pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT;
+       for (i = 0; i < nr_range; i++) {
+               unsigned long range, extra;
 
-       tables += roundup(pmds * sizeof(pmd_t), PAGE_SIZE);
+               range = mr[i].end - mr[i].start;
+               puds += (range + PUD_SIZE - 1) >> PUD_SHIFT;
 
-       if (use_pse) {
-               unsigned long extra;
+               if (mr[i].page_size_mask & (1 << PG_LEVEL_1G)) {
+                       extra = range - ((range >> PUD_SHIFT) << PUD_SHIFT);
+                       pmds += (extra + PMD_SIZE - 1) >> PMD_SHIFT;
+               } else {
+                       pmds += (range + PMD_SIZE - 1) >> PMD_SHIFT;
+               }
 
-               extra = end - ((end>>PMD_SHIFT) << PMD_SHIFT);
+               if (mr[i].page_size_mask & (1 << PG_LEVEL_2M)) {
+                       extra = range - ((range >> PMD_SHIFT) << PMD_SHIFT);
 #ifdef CONFIG_X86_32
-               extra += PMD_SIZE;
+                       extra += PMD_SIZE;
 #endif
-               /* The first 2/4M doesn't use large pages. */
-               if (mr->start < PMD_SIZE)
-                       extra += mr->end - mr->start;
-
-               ptes = (extra + PAGE_SIZE - 1) >> PAGE_SHIFT;
-       } else
-               ptes = (end + PAGE_SIZE - 1) >> PAGE_SHIFT;
+                       ptes += (extra + PAGE_SIZE - 1) >> PAGE_SHIFT;
+               } else {
+                       ptes += (range + PAGE_SIZE - 1) >> PAGE_SHIFT;
+               }
+       }
 
+       tables = roundup(puds * sizeof(pud_t), PAGE_SIZE);
+       tables += roundup(pmds * sizeof(pmd_t), PAGE_SIZE);
        tables += roundup(ptes * sizeof(pte_t), PAGE_SIZE);
 
 #ifdef CONFIG_X86_32
@@ -86,7 +90,7 @@ static void __init find_early_table_space(struct map_range *mr, unsigned long en
        pgt_buf_top = pgt_buf_start + (tables >> PAGE_SHIFT);
 
        printk(KERN_DEBUG "kernel direct mapping tables up to %#lx @ [mem %#010lx-%#010lx]\n",
-               end - 1, pgt_buf_start << PAGE_SHIFT,
+               mr[nr_range - 1].end - 1, pgt_buf_start << PAGE_SHIFT,
                (pgt_buf_top << PAGE_SHIFT) - 1);
 }
 
@@ -267,7 +271,7 @@ unsigned long __init_refok init_memory_mapping(unsigned long start,
         * nodes are discovered.
         */
        if (!after_bootmem)
-               find_early_table_space(&mr[0], end, use_pse, use_gbpages);
+               find_early_table_space(mr, nr_range);
 
        for (i = 0; i < nr_range; i++)
                ret = kernel_physical_mapping_init(mr[i].start, mr[i].end,
index 2b6b4a3c8beb8727d27b1cdba22411fe0d271efb..3baff255adac6472570298d7e9ee60df75e93dfc 100644 (file)
@@ -386,7 +386,8 @@ phys_pte_init(pte_t *pte_page, unsigned long addr, unsigned long end,
                 * these mappings are more intelligent.
                 */
                if (pte_val(*pte)) {
-                       pages++;
+                       if (!after_bootmem)
+                               pages++;
                        continue;
                }
 
@@ -451,6 +452,8 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end,
                         * attributes.
                         */
                        if (page_size_mask & (1 << PG_LEVEL_2M)) {
+                               if (!after_bootmem)
+                                       pages++;
                                last_map_addr = next;
                                continue;
                        }
@@ -526,6 +529,8 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end,
                         * attributes.
                         */
                        if (page_size_mask & (1 << PG_LEVEL_1G)) {
+                               if (!after_bootmem)
+                                       pages++;
                                last_map_addr = next;
                                continue;
                        }
index 0777f042e4002e695b316c99889b594daebc5448..60f926cd8b0edbf44277a18718dd86cb4a077bd1 100644 (file)
@@ -197,7 +197,7 @@ void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
        }
 
        if (end == TLB_FLUSH_ALL || tlb_flushall_shift == -1
-                                       || vmflag == VM_HUGETLB) {
+                                       || vmflag & VM_HUGETLB) {
                local_flush_tlb();
                goto flush_all;
        }
index 26b8a8514ee566e8a7d235a06de1037c2641adec..48768df2471af2bc9e4059fad6eb8c583f93f4d0 100644 (file)
@@ -55,7 +55,7 @@ u64 op_x86_get_ctrl(struct op_x86_model_spec const *model,
        val |= counter_config->extra;
        event &= model->event_mask ? model->event_mask : 0xFF;
        val |= event & 0xFF;
-       val |= (event & 0x0F00) << 24;
+       val |= (u64)(event & 0x0F00) << 24;
 
        return val;
 }
index 41bd2a2d2c50f61a4948f954f296631c8dfd7961..b914e20b5a0033c7cb856c1e82eeea207187eb07 100644 (file)
@@ -115,6 +115,16 @@ static void sata_revid_read(struct sim_dev_reg *reg, u32 *value)
        reg_read(reg, value);
 }
 
+static void reg_noirq_read(struct sim_dev_reg *reg, u32 *value)
+{
+       unsigned long flags;
+
+       raw_spin_lock_irqsave(&pci_config_lock, flags);
+       /* force interrupt pin value to 0 */
+       *value = reg->sim_reg.value & 0xfff00ff;
+       raw_spin_unlock_irqrestore(&pci_config_lock, flags);
+}
+
 static struct sim_dev_reg bus1_fixups[] = {
        DEFINE_REG(2, 0, 0x10, (16*MB), reg_init, reg_read, reg_write)
        DEFINE_REG(2, 0, 0x14, (256), reg_init, reg_read, reg_write)
@@ -144,6 +154,7 @@ static struct sim_dev_reg bus1_fixups[] = {
        DEFINE_REG(11, 5, 0x10, (64*KB), reg_init, reg_read, reg_write)
        DEFINE_REG(11, 6, 0x10, (256), reg_init, reg_read, reg_write)
        DEFINE_REG(11, 7, 0x10, (64*KB), reg_init, reg_read, reg_write)
+       DEFINE_REG(11, 7, 0x3c, 256, reg_init, reg_noirq_read, reg_write)
        DEFINE_REG(12, 0, 0x10, (128*KB), reg_init, reg_read, reg_write)
        DEFINE_REG(12, 0, 0x14, (256), reg_init, reg_read, reg_write)
        DEFINE_REG(12, 1, 0x10, (1024), reg_init, reg_read, reg_write)
@@ -161,8 +172,10 @@ static struct sim_dev_reg bus1_fixups[] = {
        DEFINE_REG(16, 0, 0x10, (64*KB), reg_init, reg_read, reg_write)
        DEFINE_REG(16, 0, 0x14, (64*MB), reg_init, reg_read, reg_write)
        DEFINE_REG(16, 0, 0x18, (64*MB), reg_init, reg_read, reg_write)
+       DEFINE_REG(16, 0, 0x3c, 256, reg_init, reg_noirq_read, reg_write)
        DEFINE_REG(17, 0, 0x10, (128*KB), reg_init, reg_read, reg_write)
        DEFINE_REG(18, 0, 0x10, (1*KB), reg_init, reg_read, reg_write)
+       DEFINE_REG(18, 0, 0x3c, 256, reg_init, reg_noirq_read, reg_write)
 };
 
 static void __init init_sim_regs(void)
index 4c61b52191eb293bcaef2cac2380c6114cdaefcf..92525cb8e54c84c0ebe6b2caeacb47f4f8ab299b 100644 (file)
 #include <asm/i8259.h>
 #include <asm/io.h>
 #include <asm/io_apic.h>
+#include <asm/emergency-restart.h>
 
 static int ce4100_i8042_detect(void)
 {
        return 0;
 }
 
+/*
+ * The CE4100 platform has an internal 8051 Microcontroller which is
+ * responsible for signaling to the external Power Management Unit the
+ * intention to reset, reboot or power off the system. This 8051 device has
+ * its command register mapped at I/O port 0xcf9 and the value 0x4 is used
+ * to power off the system.
+ */
+static void ce4100_power_off(void)
+{
+       outb(0x4, 0xcf9);
+}
+
 #ifdef CONFIG_SERIAL_8250
 
 static unsigned int mem_serial_in(struct uart_port *p, int offset)
@@ -139,8 +152,19 @@ void __init x86_ce4100_early_setup(void)
        x86_init.mpparse.find_smp_config = x86_init_noop;
        x86_init.pci.init = ce4100_pci_init;
 
+       /*
+        * By default, the reboot method is ACPI which is supported by the
+        * CE4100 bootloader CEFDK using FADT.ResetReg Address and ResetValue
+        * the bootloader will however issue a system power off instead of
+        * reboot. By using BOOT_KBD we ensure proper system reboot as
+        * expected.
+        */
+       reboot_type = BOOT_KBD;
+
 #ifdef CONFIG_X86_IO_APIC
        x86_init.pci.init_irq = sdv_pci_init;
        x86_init.mpparse.setup_ioapic_ids = setup_ioapic_ids_from_mpc_nocheck;
 #endif
+
+       pm_power_off = ce4100_power_off;
 }
index aded2a91162a8af12ad104d047544afce91ff4c4..ad4439145f858314dfe518cf7cd9336c5fe9c96d 100644 (file)
@@ -70,11 +70,15 @@ EXPORT_SYMBOL(efi);
 struct efi_memory_map memmap;
 
 bool efi_64bit;
-static bool efi_native;
 
 static struct efi efi_phys __initdata;
 static efi_system_table_t efi_systab __initdata;
 
+static inline bool efi_is_native(void)
+{
+       return IS_ENABLED(CONFIG_X86_64) == efi_64bit;
+}
+
 static int __init setup_noefi(char *arg)
 {
        efi_enabled = 0;
@@ -420,7 +424,7 @@ void __init efi_reserve_boot_services(void)
        }
 }
 
-static void __init efi_unmap_memmap(void)
+void __init efi_unmap_memmap(void)
 {
        if (memmap.map) {
                early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size);
@@ -432,7 +436,7 @@ void __init efi_free_boot_services(void)
 {
        void *p;
 
-       if (!efi_native)
+       if (!efi_is_native())
                return;
 
        for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
@@ -684,12 +688,10 @@ void __init efi_init(void)
                return;
        }
        efi_phys.systab = (efi_system_table_t *)boot_params.efi_info.efi_systab;
-       efi_native = !efi_64bit;
 #else
        efi_phys.systab = (efi_system_table_t *)
                          (boot_params.efi_info.efi_systab |
                          ((__u64)boot_params.efi_info.efi_systab_hi<<32));
-       efi_native = efi_64bit;
 #endif
 
        if (efi_systab_init(efi_phys.systab)) {
@@ -723,7 +725,7 @@ void __init efi_init(void)
         * that doesn't match the kernel 32/64-bit mode.
         */
 
-       if (!efi_native)
+       if (!efi_is_native())
                pr_info("No EFI runtime due to 32/64-bit mismatch with kernel\n");
        else if (efi_runtime_init()) {
                efi_enabled = 0;
@@ -735,7 +737,7 @@ void __init efi_init(void)
                return;
        }
 #ifdef CONFIG_X86_32
-       if (efi_native) {
+       if (efi_is_native()) {
                x86_platform.get_wallclock = efi_get_time;
                x86_platform.set_wallclock = efi_set_rtc_mmss;
        }
@@ -810,6 +812,16 @@ void __iomem *efi_lookup_mapped_addr(u64 phys_addr)
        return NULL;
 }
 
+void efi_memory_uc(u64 addr, unsigned long size)
+{
+       unsigned long page_shift = 1UL << EFI_PAGE_SHIFT;
+       u64 npages;
+
+       npages = round_up(size, page_shift) / page_shift;
+       memrange_efi_to_native(&addr, &npages);
+       set_memory_uc(addr, npages);
+}
+
 /*
  * This function will switch the EFI runtime services to virtual mode.
  * Essentially, look through the EFI memmap and map every region that
@@ -823,7 +835,7 @@ void __init efi_enter_virtual_mode(void)
        efi_memory_desc_t *md, *prev_md = NULL;
        efi_status_t status;
        unsigned long size;
-       u64 end, systab, addr, npages, end_pfn;
+       u64 end, systab, end_pfn;
        void *p, *va, *new_memmap = NULL;
        int count = 0;
 
@@ -834,7 +846,7 @@ void __init efi_enter_virtual_mode(void)
         * non-native EFI
         */
 
-       if (!efi_native) {
+       if (!efi_is_native()) {
                efi_unmap_memmap();
                return;
        }
@@ -879,10 +891,14 @@ void __init efi_enter_virtual_mode(void)
                end_pfn = PFN_UP(end);
                if (end_pfn <= max_low_pfn_mapped
                    || (end_pfn > (1UL << (32 - PAGE_SHIFT))
-                       && end_pfn <= max_pfn_mapped))
+                       && end_pfn <= max_pfn_mapped)) {
                        va = __va(md->phys_addr);
-               else
-                       va = efi_ioremap(md->phys_addr, size, md->type);
+
+                       if (!(md->attribute & EFI_MEMORY_WB))
+                               efi_memory_uc((u64)(unsigned long)va, size);
+               } else
+                       va = efi_ioremap(md->phys_addr, size,
+                                        md->type, md->attribute);
 
                md->virt_addr = (u64) (unsigned long) va;
 
@@ -892,13 +908,6 @@ void __init efi_enter_virtual_mode(void)
                        continue;
                }
 
-               if (!(md->attribute & EFI_MEMORY_WB)) {
-                       addr = md->virt_addr;
-                       npages = md->num_pages;
-                       memrange_efi_to_native(&addr, &npages);
-                       set_memory_uc(addr, npages);
-               }
-
                systab = (u64) (unsigned long) efi_phys.systab;
                if (md->phys_addr <= systab && systab < end) {
                        systab += md->virt_addr - md->phys_addr;
index ac3aa54e26546ba5cb4121eba0c58ca00f06ea82..95fd505dfeb6e43dd37b0c41954f0b0db6535d1c 100644 (file)
@@ -82,7 +82,7 @@ void __init efi_call_phys_epilog(void)
 }
 
 void __iomem *__init efi_ioremap(unsigned long phys_addr, unsigned long size,
-                                u32 type)
+                                u32 type, u64 attribute)
 {
        unsigned long last_map_pfn;
 
@@ -92,8 +92,11 @@ void __iomem *__init efi_ioremap(unsigned long phys_addr, unsigned long size,
        last_map_pfn = init_memory_mapping(phys_addr, phys_addr + size);
        if ((last_map_pfn << PAGE_SHIFT) < phys_addr + size) {
                unsigned long top = last_map_pfn << PAGE_SHIFT;
-               efi_ioremap(top, size - (top - phys_addr), type);
+               efi_ioremap(top, size - (top - phys_addr), type, attribute);
        }
 
+       if (!(attribute & EFI_MEMORY_WB))
+               efi_memory_uc((u64)(unsigned long)__va(phys_addr), size);
+
        return (void __iomem *)__va(phys_addr);
 }
index e3497f240eabb869e6cda863036689e6b093899d..586d83812b67b64f96594f1eebdc859bdcb12adc 100644 (file)
@@ -81,8 +81,6 @@
 #include "smp.h"
 #include "multicalls.h"
 
-#include <xen/events.h>
-
 EXPORT_SYMBOL_GPL(hypercall_page);
 
 DEFINE_PER_CPU(struct vcpu_info *, xen_vcpu);
index 6226c99729b963594a2e133290cbf8f3c6e681b8..dcf5f2dd91ec4fd91d814d46c7d6dbd6c5312a61 100644 (file)
@@ -1288,6 +1288,25 @@ unsigned long xen_read_cr2_direct(void)
        return this_cpu_read(xen_vcpu_info.arch.cr2);
 }
 
+void xen_flush_tlb_all(void)
+{
+       struct mmuext_op *op;
+       struct multicall_space mcs;
+
+       trace_xen_mmu_flush_tlb_all(0);
+
+       preempt_disable();
+
+       mcs = xen_mc_entry(sizeof(*op));
+
+       op = mcs.args;
+       op->cmd = MMUEXT_TLB_FLUSH_ALL;
+       MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF);
+
+       xen_mc_issue(PARAVIRT_LAZY_MMU);
+
+       preempt_enable();
+}
 static void xen_flush_tlb(void)
 {
        struct mmuext_op *op;
@@ -2518,7 +2537,7 @@ int xen_remap_domain_mfn_range(struct vm_area_struct *vma,
        err = 0;
 out:
 
-       flush_tlb_all();
+       xen_flush_tlb_all();
 
        return err;
 }
index cdcb48adee4c6d05f65f34fb9893a55afdb4c5f1..0d1f36a22c98827ba204af46859b349ac3da91ae 100644 (file)
@@ -13,6 +13,8 @@ config XTENSA
        select GENERIC_CPU_DEVICES
        select MODULES_USE_ELF_RELA
        select GENERIC_PCI_IOMAP
+       select GENERIC_KERNEL_THREAD
+       select GENERIC_KERNEL_EXECVE
        select ARCH_WANT_OPTIONAL_GPIOLIB
        help
          Xtensa processors are 32-bit RISC machines designed by Tensilica
index e6be5b9091c2a65509f721ed3e5f92bc7c6783bc..700c2e6f2d259d454f5f8f310b431d6b20ecbc1f 100644 (file)
@@ -62,6 +62,10 @@ static inline void __iomem *ioremap(unsigned long offset, unsigned long size)
 static inline void iounmap(volatile void __iomem *addr)
 {
 }
+
+#define virt_to_bus     virt_to_phys
+#define bus_to_virt     phys_to_virt
+
 #endif /* CONFIG_MMU */
 
 /*
index 5c371d8d45284a1c35808d2b9e4928db03cc7652..2d630e7399ca4f94584a77cdf2a150d6c9ff7319 100644 (file)
@@ -152,6 +152,7 @@ struct thread_struct {
 
 /* Clearing a0 terminates the backtrace. */
 #define start_thread(regs, new_pc, new_sp) \
+       memset(regs, 0, sizeof(*regs)); \
        regs->pc = new_pc; \
        regs->ps = USER_PS_VALUE; \
        regs->areg[1] = new_sp; \
@@ -168,9 +169,6 @@ struct mm_struct;
 /* Free all resources held by a thread. */
 #define release_thread(thread) do { } while(0)
 
-/* Create a kernel thread without removing it from tasklists */
-extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
-
 /* Copy and release all segment info associated with a VM */
 #define copy_segments(p, mm)   do { } while(0)
 #define release_segments(mm)   do { } while(0)
index c1dacca312f3906374614ae4eb0a486ab8070e8a..124aeee0d3816cadf7abe7317d168b5f3b326891 100644 (file)
@@ -10,7 +10,7 @@
 
 struct pt_regs;
 struct sigaction;
-asmlinkage long xtensa_execve(char*, char**, char**, struct pt_regs*);
+asmlinkage long sys_execve(char*, char**, char**, struct pt_regs*);
 asmlinkage long xtensa_clone(unsigned long, unsigned long, struct pt_regs*);
 asmlinkage long xtensa_ptrace(long, long, long, long);
 asmlinkage long xtensa_sigreturn(struct pt_regs*);
index 9ef1c31d2c8363fdae934f157abce35d1ef21e89..f4e6eaa40d1ca86946799a1f7eab6d7047a69dd5 100644 (file)
@@ -1,16 +1,9 @@
-/*
- * include/asm-xtensa/unistd.h
- *
- * 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) 2001 - 2005 Tensilica Inc.
- */
+#ifndef _XTENSA_UNISTD_H
+#define _XTENSA_UNISTD_H
 
+#define __ARCH_WANT_SYS_EXECVE
 #include <uapi/asm/unistd.h>
 
-
 /*
  * "Conditional" syscalls
  *
@@ -37,3 +30,5 @@
 #define __IGNORE_mmap                          /* use mmap2 */
 #define __IGNORE_vfork                         /* use clone */
 #define __IGNORE_fadvise64                     /* use fadvise64_64 */
+
+#endif /* _XTENSA_UNISTD_H */
index 479abaea5aae761a41b60ef5e1861bba3aa2e605..9f36d0e3e0aca7d8fc87257be6d48cbdea16f810 100644 (file)
@@ -1,14 +1,4 @@
-/*
- * include/asm-xtensa/unistd.h
- *
- * 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) 2001 - 2012 Tensilica Inc.
- */
-
-#ifndef _UAPI_XTENSA_UNISTD_H
+#if !defined(_UAPI_XTENSA_UNISTD_H) || defined(__SYSCALL)
 #define _UAPI_XTENSA_UNISTD_H
 
 #ifndef __SYSCALL
@@ -272,7 +262,7 @@ __SYSCALL(115, sys_sendmmsg, 4)
 #define __NR_clone                             116
 __SYSCALL(116, xtensa_clone, 5)
 #define __NR_execve                            117
-__SYSCALL(117, xtensa_execve, 3)
+__SYSCALL(117, sys_execve, 3)
 #define __NR_exit                              118
 __SYSCALL(118, sys_exit, 1)
 #define __NR_exit_group                        119
@@ -759,4 +749,6 @@ __SYSCALL(331, sys_kcmp, 5)
 
 #define SYS_XTENSA_COUNT                  5     /* count */
 
+#undef __SYSCALL
+
 #endif /* _UAPI_XTENSA_UNISTD_H */
index 18453067c2582034e896adee07c0d474912a98d2..90bfc1dbc13dcf46992e4fb09bb7eab3cfe1bea3 100644 (file)
@@ -1832,50 +1832,6 @@ ENTRY(system_call)
        retw
 
 
-/*
- * Create a kernel thread
- *
- * int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
- * a2                    a2                 a3             a4
- */
-
-ENTRY(kernel_thread)
-       entry   a1, 16
-
-       mov     a5, a2                  # preserve fn over syscall
-       mov     a7, a3                  # preserve args over syscall
-
-       movi    a3, _CLONE_VM | _CLONE_UNTRACED
-       movi    a2, __NR_clone
-       or      a6, a4, a3              # arg0: flags
-       mov     a3, a1                  # arg1: sp
-       syscall
-
-       beq     a3, a1, 1f              # branch if parent
-       mov     a6, a7                  # args
-       callx4  a5                      # fn(args)
-
-       movi    a2, __NR_exit
-       syscall                         # return value of fn(args) still in a6
-
-1:     retw
-
-/*
- * Do a system call from kernel instead of calling sys_execve, so we end up
- * with proper pt_regs.
- *
- * int kernel_execve(const char *fname, char *const argv[], charg *const envp[])
- * a2                        a2               a3                  a4
- */
-
-ENTRY(kernel_execve)
-       entry   a1, 16
-       mov     a6, a2                  # arg0 is in a6
-       movi    a2, __NR_execve
-       syscall
-
-       retw
-
 /*
  * Task switch.
  *
@@ -1958,3 +1914,16 @@ ENTRY(ret_from_fork)
 
        j       common_exception_return
 
+/*
+ * Kernel thread creation helper
+ * On entry, set up by copy_thread: a2 = thread_fn, a3 = thread_fn arg
+ *           left from _switch_to: a6 = prev
+ */
+ENTRY(ret_from_kernel_thread)
+
+       call4   schedule_tail
+       mov     a6, a3
+       callx4  a2
+       j       common_exception_return
+
+ENDPROC(ret_from_kernel_thread)
index 1908f6642d31e0073c5884b0f90445641452cb75..09ae7bfab9a7a4a8ff2a6e2c55aadf07dda48024 100644 (file)
@@ -45,6 +45,7 @@
 #include <asm/regs.h>
 
 extern void ret_from_fork(void);
+extern void ret_from_kernel_thread(void);
 
 struct task_struct *current_set[NR_CPUS] = {&init_task, };
 
@@ -158,18 +159,30 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
 /*
  * Copy thread.
  *
+ * There are two modes in which this function is called:
+ * 1) Userspace thread creation,
+ *    regs != NULL, usp_thread_fn is userspace stack pointer.
+ *    It is expected to copy parent regs (in case CLONE_VM is not set
+ *    in the clone_flags) and set up passed usp in the childregs.
+ * 2) Kernel thread creation,
+ *    regs == NULL, usp_thread_fn is the function to run in the new thread
+ *    and thread_fn_arg is its parameter.
+ *    childregs are not used for the kernel threads.
+ *
  * The stack layout for the new thread looks like this:
  *
- *     +------------------------+ <- sp in childregs (= tos)
+ *     +------------------------+
  *     |       childregs        |
  *     +------------------------+ <- thread.sp = sp in dummy-frame
  *     |      dummy-frame       |    (saved in dummy-frame spill-area)
  *     +------------------------+
  *
- * We create a dummy frame to return to ret_from_fork:
- *   a0 points to ret_from_fork (simulating a call4)
+ * We create a dummy frame to return to either ret_from_fork or
+ *   ret_from_kernel_thread:
+ *   a0 points to ret_from_fork/ret_from_kernel_thread (simulating a call4)
  *   sp points to itself (thread.sp)
- *   a2, a3 are unused.
+ *   a2, a3 are unused for userspace threads,
+ *   a2 points to thread_fn, a3 holds thread_fn arg for kernel threads.
  *
  * Note: This is a pristine frame, so we don't need any spill region on top of
  *       childregs.
@@ -185,43 +198,63 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
  * involved.  Much simpler to just not copy those live frames across.
  */
 
-int copy_thread(unsigned long clone_flags, unsigned long usp,
-               unsigned long unused,
-                struct task_struct * p, struct pt_regs * regs)
+int copy_thread(unsigned long clone_flags, unsigned long usp_thread_fn,
+               unsigned long thread_fn_arg,
+               struct task_struct *p, struct pt_regs *unused)
 {
-       struct pt_regs *childregs;
-       unsigned long tos;
-       int user_mode = user_mode(regs);
+       struct pt_regs *childregs = task_pt_regs(p);
 
 #if (XTENSA_HAVE_COPROCESSORS || XTENSA_HAVE_IO_PORTS)
        struct thread_info *ti;
 #endif
 
-       /* Set up new TSS. */
-       tos = (unsigned long)task_stack_page(p) + THREAD_SIZE;
-       if (user_mode)
-               childregs = (struct pt_regs*)(tos - PT_USER_SIZE);
-       else
-               childregs = (struct pt_regs*)tos - 1;
-
-       /* This does not copy all the regs.  In a bout of brilliance or madness,
-          ARs beyond a0-a15 exist past the end of the struct. */
-       *childregs = *regs;
-
        /* Create a call4 dummy-frame: a0 = 0, a1 = childregs. */
        *((int*)childregs - 3) = (unsigned long)childregs;
        *((int*)childregs - 4) = 0;
 
-       childregs->areg[2] = 0;
-       p->set_child_tid = p->clear_child_tid = NULL;
-       p->thread.ra = MAKE_RA_FOR_CALL((unsigned long)ret_from_fork, 0x1);
        p->thread.sp = (unsigned long)childregs;
 
-       if (user_mode(regs)) {
+       if (!(p->flags & PF_KTHREAD)) {
+               struct pt_regs *regs = current_pt_regs();
+               unsigned long usp = usp_thread_fn ?
+                       usp_thread_fn : regs->areg[1];
 
+               p->thread.ra = MAKE_RA_FOR_CALL(
+                               (unsigned long)ret_from_fork, 0x1);
+
+               /* This does not copy all the regs.
+                * In a bout of brilliance or madness,
+                * ARs beyond a0-a15 exist past the end of the struct.
+                */
+               *childregs = *regs;
                childregs->areg[1] = usp;
+               childregs->areg[2] = 0;
+
+               /* When sharing memory with the parent thread, the child
+                  usually starts on a pristine stack, so we have to reset
+                  windowbase, windowstart and wmask.
+                  (Note that such a new thread is required to always create
+                  an initial call4 frame)
+                  The exception is vfork, where the new thread continues to
+                  run on the parent's stack until it calls execve. This could
+                  be a call8 or call12, which requires a legal stack frame
+                  of the previous caller for the overflow handlers to work.
+                  (Note that it's always legal to overflow live registers).
+                  In this case, ensure to spill at least the stack pointer
+                  of that frame. */
+
                if (clone_flags & CLONE_VM) {
-                       childregs->wmask = 1;   /* can't share live windows */
+                       /* check that caller window is live and same stack */
+                       int len = childregs->wmask & ~0xf;
+                       if (regs->areg[1] == usp && len != 0) {
+                               int callinc = (regs->areg[0] >> 30) & 3;
+                               int caller_ars = XCHAL_NUM_AREGS - callinc * 4;
+                               put_user(regs->areg[caller_ars+1],
+                                        (unsigned __user*)(usp - 12));
+                       }
+                       childregs->wmask = 1;
+                       childregs->windowstart = 1;
+                       childregs->windowbase = 0;
                } else {
                        int len = childregs->wmask & ~0xf;
                        memcpy(&childregs->areg[XCHAL_NUM_AREGS - len/4],
@@ -230,11 +263,19 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
 // FIXME: we need to set THREADPTR in thread_info...
                if (clone_flags & CLONE_SETTLS)
                        childregs->areg[2] = childregs->areg[6];
-
        } else {
-               /* In kernel space, we start a new thread with a new stack. */
-               childregs->wmask = 1;
-               childregs->areg[1] = tos;
+               p->thread.ra = MAKE_RA_FOR_CALL(
+                               (unsigned long)ret_from_kernel_thread, 1);
+
+               /* pass parameters to ret_from_kernel_thread:
+                * a2 = thread_fn, a3 = thread_fn arg
+                */
+               *((int *)childregs - 1) = thread_fn_arg;
+               *((int *)childregs - 2) = usp_thread_fn;
+
+               /* Childregs are only used when we're going to userspace
+                * in which case start_thread will set them up.
+                */
        }
 
 #if (XTENSA_HAVE_COPROCESSORS || XTENSA_HAVE_IO_PORTS)
@@ -330,32 +371,5 @@ long xtensa_clone(unsigned long clone_flags, unsigned long newsp,
                   void __user *child_tid, long a5,
                   struct pt_regs *regs)
 {
-        if (!newsp)
-                newsp = regs->areg[1];
         return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);
 }
-
-/*
- * xtensa_execve() executes a new program.
- */
-
-asmlinkage
-long xtensa_execve(const char __user *name,
-                  const char __user *const __user *argv,
-                   const char __user *const __user *envp,
-                   long a3, long a4, long a5,
-                   struct pt_regs *regs)
-{
-       long error;
-       struct filename *filename;
-
-       filename = getname(name);
-       error = PTR_ERR(filename);
-       if (IS_ERR(filename))
-               goto out;
-       error = do_execve(filename->name, argv, envp, regs);
-       putname(filename);
-out:
-       return error;
-}
-
index a5c01e74d5d5590f3c5287dace8f23c10c527cd9..5702065f472a88bebc4df721dec0629208957395 100644 (file)
@@ -32,10 +32,8 @@ typedef void (*syscall_t)(void);
 syscall_t sys_call_table[__NR_syscall_count] /* FIXME __cacheline_aligned */= {
        [0 ... __NR_syscall_count - 1] = (syscall_t)&sys_ni_syscall,
 
-#undef __SYSCALL
 #define __SYSCALL(nr,symbol,nargs) [ nr ] = (syscall_t)symbol,
-#undef  __KERNEL_SYSCALLS__
-#include <asm/unistd.h>
+#include <uapi/asm/unistd.h>
 };
 
 asmlinkage long xtensa_shmat(int shmid, char __user *shmaddr, int shmflg)
@@ -49,7 +47,8 @@ asmlinkage long xtensa_shmat(int shmid, char __user *shmaddr, int shmflg)
        return (long)ret;
 }
 
-asmlinkage long xtensa_fadvise64_64(int fd, int advice, unsigned long long offset, unsigned long long len)
+asmlinkage long xtensa_fadvise64_64(int fd, int advice,
+               unsigned long long offset, unsigned long long len)
 {
        return sys_fadvise64_64(fd, offset, len, advice);
 }
index a8b9f1fd1e17f63573c74bdf8c06616c1abd7481..afe058b24e6e07c83d61f1a524b30e03340d6369 100644 (file)
@@ -43,7 +43,6 @@ EXPORT_SYMBOL(__strncpy_user);
 EXPORT_SYMBOL(clear_page);
 EXPORT_SYMBOL(copy_page);
 
-EXPORT_SYMBOL(kernel_thread);
 EXPORT_SYMBOL(empty_zero_page);
 
 /*
index 09acf1b39905ced3f08164c213a6d2aed7f29cae..a7e40a7c821427cd27f6c7019411030ea00e33e8 100644 (file)
@@ -89,7 +89,7 @@ config BLK_DEV_INTEGRITY
 
 config BLK_DEV_THROTTLING
        bool "Block layer bio throttling support"
-       depends on BLK_CGROUP=y && EXPERIMENTAL
+       depends on BLK_CGROUP=y
        default n
        ---help---
        Block layer bio throttling support. It can be used to limit
index cafcd743118969daec377f52f09e41594d188347..d0b770391ad400ad0312049c84a2b522bf985bf1 100644 (file)
@@ -285,6 +285,13 @@ static void blkg_destroy_all(struct request_queue *q)
                blkg_destroy(blkg);
                spin_unlock(&blkcg->lock);
        }
+
+       /*
+        * root blkg is destroyed.  Just clear the pointer since
+        * root_rl does not take reference on root blkg.
+        */
+       q->root_blkg = NULL;
+       q->root_rl.blkg = NULL;
 }
 
 static void blkg_rcu_free(struct rcu_head *rcu_head)
@@ -326,6 +333,9 @@ struct request_list *__blk_queue_next_rl(struct request_list *rl,
         */
        if (rl == &q->root_rl) {
                ent = &q->blkg_list;
+               /* There are no more block groups, hence no request lists */
+               if (list_empty(ent))
+                       return NULL;
        } else {
                blkg = container_of(rl, struct blkcg_gq, rl);
                ent = &blkg->q_node;
index a33870b1847bb70c6ef1937f7bef4e93bdf9c980..3c95c4d6e31afe057ebabeda36868682e8188329 100644 (file)
@@ -2868,7 +2868,8 @@ static int plug_rq_cmp(void *priv, struct list_head *a, struct list_head *b)
        struct request *rqa = container_of(a, struct request, queuelist);
        struct request *rqb = container_of(b, struct request, queuelist);
 
-       return !(rqa->q <= rqb->q);
+       return !(rqa->q < rqb->q ||
+               (rqa->q == rqb->q && blk_rq_pos(rqa) < blk_rq_pos(rqb)));
 }
 
 /*
index 8b6dc5bd4dd061336172b144ae8c09da6bbc56f8..f71eac35c1b942005f3973fd9c919091b9b08bbd 100644 (file)
@@ -52,11 +52,17 @@ void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk,
                           rq_end_io_fn *done)
 {
        int where = at_head ? ELEVATOR_INSERT_FRONT : ELEVATOR_INSERT_BACK;
+       bool is_pm_resume;
 
        WARN_ON(irqs_disabled());
 
        rq->rq_disk = bd_disk;
        rq->end_io = done;
+       /*
+        * need to check this before __blk_run_queue(), because rq can
+        * be freed before that returns.
+        */
+       is_pm_resume = rq->cmd_type == REQ_TYPE_PM_RESUME;
 
        spin_lock_irq(q->queue_lock);
 
@@ -71,7 +77,7 @@ void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk,
        __elv_add_request(q, rq, where);
        __blk_run_queue(q);
        /* the queue is stopped so it won't be run */
-       if (rq->cmd_type == REQ_TYPE_PM_RESUME)
+       if (is_pm_resume)
                q->request_fn(q);
        spin_unlock_irq(q->queue_lock);
 }
index 671d4d6d14df106b3b0278364340ef3290d7a185..7bdd61b867c899901ed846ed5a229bc6ab31653b 100644 (file)
@@ -137,13 +137,18 @@ static void cryptd_queue_worker(struct work_struct *work)
        struct crypto_async_request *req, *backlog;
 
        cpu_queue = container_of(work, struct cryptd_cpu_queue, work);
-       /* Only handle one request at a time to avoid hogging crypto
-        * workqueue. preempt_disable/enable is used to prevent
-        * being preempted by cryptd_enqueue_request() */
+       /*
+        * Only handle one request at a time to avoid hogging crypto workqueue.
+        * preempt_disable/enable is used to prevent being preempted by
+        * cryptd_enqueue_request(). local_bh_disable/enable is used to prevent
+        * cryptd_enqueue_request() being accessed from software interrupts.
+        */
+       local_bh_disable();
        preempt_disable();
        backlog = crypto_get_backlog(&cpu_queue->queue);
        req = crypto_dequeue_request(&cpu_queue->queue);
        preempt_enable();
+       local_bh_enable();
 
        if (!req)
                return;
index d1a2d74033e945237afdef3fac02aea87cdebbdd..08373086cd7e883edeec356acb102bcac46147cf 100644 (file)
@@ -159,6 +159,7 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle)
        if (physical_node->node_id >= ACPI_MAX_PHYSICAL_NODE) {
                retval = -ENOSPC;
                mutex_unlock(&acpi_dev->physical_node_lock);
+               kfree(physical_node);
                goto err;
        }
 
index e78c2a52ea46665fe3ea31a7e79ba7f5cc5c38b2..bd4e5dca3ff7e81f4ce754cbaad3856bb4948a6a 100644 (file)
@@ -409,6 +409,7 @@ static void acpi_processor_notify(struct acpi_device *device, u32 event)
                acpi_bus_generate_proc_event(device, event, 0);
                acpi_bus_generate_netlink_event(device->pnp.device_class,
                                                  dev_name(&device->dev), event, 0);
+               break;
        default:
                ACPI_DEBUG_PRINT((ACPI_DB_INFO,
                                  "Unsupported event [0x%x]\n", event));
index f94d4c818fc74dc9a076e8f67fe98d7bc6620a61..0230cb6cbb3a18eda2fd323763d6594205c0ed7f 100644 (file)
@@ -1345,12 +1345,15 @@ static int
 acpi_video_bus_get_devices(struct acpi_video_bus *video,
                           struct acpi_device *device)
 {
-       int status;
+       int status = 0;
        struct acpi_device *dev;
 
-       status = acpi_video_device_enumerate(video);
-       if (status)
-               return status;
+       /*
+        * There are systems where video module known to work fine regardless
+        * of broken _DOD and ignoring returned value here doesn't cause
+        * any issues later.
+        */
+       acpi_video_device_enumerate(video);
 
        list_for_each_entry(dev, &device->children, node) {
 
index b1ae48054dc5773eab42917d5e9d10f9764602ae..b7078afddb74fe91c403642cf4679beec06c0ef9 100644 (file)
@@ -238,7 +238,7 @@ static int __devexit ahci_remove(struct platform_device *pdev)
        return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int ahci_suspend(struct device *dev)
 {
        struct ahci_platform_data *pdata = dev_get_platdata(dev);
index fd9ecf74e631afc800e56927069d97bd61774862..5b0ba3f20edcfd4603538ce7505d69dd93f8bb29 100644 (file)
@@ -1105,10 +1105,15 @@ static int ata_acpi_bind_device(struct ata_port *ap, struct scsi_device *sdev,
        struct acpi_device *acpi_dev;
        struct acpi_device_power_state *states;
 
-       if (ap->flags & ATA_FLAG_ACPI_SATA)
-               ata_dev = &ap->link.device[sdev->channel];
-       else
+       if (ap->flags & ATA_FLAG_ACPI_SATA) {
+               if (!sata_pmp_attached(ap))
+                       ata_dev = &ap->link.device[sdev->id];
+               else
+                       ata_dev = &ap->pmp_link[sdev->channel].device[sdev->id];
+       }
+       else {
                ata_dev = &ap->link.device[sdev->id];
+       }
 
        *handle = ata_dev_acpi_handle(ata_dev);
 
index 3cc7096cfda758e9b3ffd514aaf6e70928ec7f8d..f46fbd3bd3fb6b4456032a0255bad894e8fc9cdb 100644 (file)
@@ -2942,6 +2942,10 @@ const struct ata_timing *ata_timing_find_mode(u8 xfer_mode)
 
        if (xfer_mode == t->mode)
                return t;
+
+       WARN_ONCE(true, "%s: unable to find timing for xfer_mode 0x%x\n",
+                       __func__, xfer_mode);
+
        return NULL;
 }
 
index e3bda074fa12f59381f9e8911338c49a88611f36..a6df6a351d6e4ce263f717ad52bf1ebb72a1aae0 100644 (file)
@@ -1052,6 +1052,8 @@ static void ata_scsi_sdev_config(struct scsi_device *sdev)
 {
        sdev->use_10_for_rw = 1;
        sdev->use_10_for_ms = 1;
+       sdev->no_report_opcodes = 1;
+       sdev->no_write_same = 1;
 
        /* Schedule policy is determined by ->qc_defer() callback and
         * it needs to see every deferred qc.  Set dev_blocked to 1 to
index 26201ebef3ca652a16c12c6719eae2127ed212ad..371fd2c698b70ce1b283672c0c2472f8ce6ac263 100644 (file)
@@ -317,6 +317,12 @@ static int cf_init(struct arasan_cf_dev *acdev)
                return ret;
        }
 
+       ret = clk_set_rate(acdev->clk, 166000000);
+       if (ret) {
+               dev_warn(acdev->host->dev, "clock set rate failed");
+               return ret;
+       }
+
        spin_lock_irqsave(&acdev->host->lock, flags);
        /* configure CF interface clock */
        writel((pdata->cf_if_clk <= CF_IF_CLK_200M) ? pdata->cf_if_clk :
@@ -908,7 +914,7 @@ static int __devexit arasan_cf_remove(struct platform_device *pdev)
        return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int arasan_cf_suspend(struct device *dev)
 {
        struct ata_host *host = dev_get_drvdata(dev);
index 0d7c4c2cd26fed3d81ecf2bfe78a1a4939588da9..400bf1c3e982eac392652d086358858ef903ca82 100644 (file)
@@ -260,7 +260,7 @@ static const struct of_device_id ahci_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, ahci_of_match);
 
-static int __init ahci_highbank_probe(struct platform_device *pdev)
+static int __devinit ahci_highbank_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct ahci_host_priv *hpriv;
@@ -378,7 +378,7 @@ static int __devexit ahci_highbank_remove(struct platform_device *pdev)
        return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int ahci_highbank_suspend(struct device *dev)
 {
        struct ata_host *host = dev_get_drvdata(dev);
index 44a4256533e1bd4e8aef978abdfc7e34361ad053..08608de87e4e6a971e9a36ef701f343a6982d5b7 100644 (file)
@@ -142,6 +142,39 @@ static int k2_sata_scr_write(struct ata_link *link,
        return 0;
 }
 
+static int k2_sata_softreset(struct ata_link *link,
+                            unsigned int *class, unsigned long deadline)
+{
+       u8 dmactl;
+       void __iomem *mmio = link->ap->ioaddr.bmdma_addr;
+
+       dmactl = readb(mmio + ATA_DMA_CMD);
+
+       /* Clear the start bit */
+       if (dmactl & ATA_DMA_START) {
+               dmactl &= ~ATA_DMA_START;
+               writeb(dmactl, mmio + ATA_DMA_CMD);
+       }
+
+       return ata_sff_softreset(link, class, deadline);
+}
+
+static int k2_sata_hardreset(struct ata_link *link,
+                            unsigned int *class, unsigned long deadline)
+{
+       u8 dmactl;
+       void __iomem *mmio = link->ap->ioaddr.bmdma_addr;
+
+       dmactl = readb(mmio + ATA_DMA_CMD);
+
+       /* Clear the start bit */
+       if (dmactl & ATA_DMA_START) {
+               dmactl &= ~ATA_DMA_START;
+               writeb(dmactl, mmio + ATA_DMA_CMD);
+       }
+
+       return sata_sff_hardreset(link, class, deadline);
+}
 
 static void k2_sata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
 {
@@ -346,6 +379,8 @@ static struct scsi_host_template k2_sata_sht = {
 
 static struct ata_port_operations k2_sata_ops = {
        .inherits               = &ata_bmdma_port_ops,
+       .softreset              = k2_sata_softreset,
+       .hardreset              = k2_sata_hardreset,
        .sff_tf_load            = k2_sata_tf_load,
        .sff_tf_read            = k2_sata_tf_read,
        .sff_check_status       = k2_stat_check_status,
index 08b4c520938463fd989bba879d791a3e418efd39..b34b5cda5ae110aeec980b6ec7c2ec608490a093 100644 (file)
@@ -236,7 +236,7 @@ config CMA_SIZE_PERCENTAGE
 
 choice
        prompt "Selected region size"
-       default CMA_SIZE_SEL_ABSOLUTE
+       default CMA_SIZE_SEL_MBYTES
 
 config CMA_SIZE_SEL_MBYTES
        bool "Use mega bytes value only"
index 560a7173f810015a9532d25395a8ad1a57366e6c..bc256b64102710039e208ec82c513e97b223a290 100644 (file)
@@ -191,9 +191,8 @@ EXPORT_SYMBOL(dma_release_from_coherent);
  * This checks whether the memory was allocated from the per-device
  * coherent memory pool and if so, maps that memory to the provided vma.
  *
- * Returns 1 if we correctly mapped the memory, or 0 if
- * dma_release_coherent() should proceed with mapping memory from
- * generic pools.
+ * Returns 1 if we correctly mapped the memory, or 0 if the caller should
+ * proceed with mapping memory from generic pools.
  */
 int dma_mmap_from_coherent(struct device *dev, struct vm_area_struct *vma,
                           void *vaddr, size_t size, int *ret)
index 9a1469474f55addaea1ae5be1f4499187297db06..612afcc5a938f45549ed877ebd6c8ac697315fe3 100644 (file)
 #include <linux/mm.h>
 #include <linux/mutex.h>
 #include <linux/page-isolation.h>
+#include <linux/sizes.h>
 #include <linux/slab.h>
 #include <linux/swap.h>
 #include <linux/mm_types.h>
 #include <linux/dma-contiguous.h>
 
-#ifndef SZ_1M
-#define SZ_1M (1 << 20)
-#endif
-
 struct cma {
        unsigned long   base_pfn;
        unsigned long   count;
index 81541452887bd3ce5d868909e3fb753fb3d6b124..8945f4e489ed70a03cb272f57064a69330409a60 100644 (file)
@@ -36,68 +36,6 @@ MODULE_AUTHOR("Manuel Estrada Sainz");
 MODULE_DESCRIPTION("Multi purpose firmware loading support");
 MODULE_LICENSE("GPL");
 
-static const char *fw_path[] = {
-       "/lib/firmware/updates/" UTS_RELEASE,
-       "/lib/firmware/updates",
-       "/lib/firmware/" UTS_RELEASE,
-       "/lib/firmware"
-};
-
-/* Don't inline this: 'struct kstat' is biggish */
-static noinline long fw_file_size(struct file *file)
-{
-       struct kstat st;
-       if (vfs_getattr(file->f_path.mnt, file->f_path.dentry, &st))
-               return -1;
-       if (!S_ISREG(st.mode))
-               return -1;
-       if (st.size != (long)st.size)
-               return -1;
-       return st.size;
-}
-
-static bool fw_read_file_contents(struct file *file, struct firmware *fw)
-{
-       long size;
-       char *buf;
-
-       size = fw_file_size(file);
-       if (size < 0)
-               return false;
-       buf = vmalloc(size);
-       if (!buf)
-               return false;
-       if (kernel_read(file, 0, buf, size) != size) {
-               vfree(buf);
-               return false;
-       }
-       fw->data = buf;
-       fw->size = size;
-       return true;
-}
-
-static bool fw_get_filesystem_firmware(struct firmware *fw, const char *name)
-{
-       int i;
-       bool success = false;
-       char *path = __getname();
-
-       for (i = 0; i < ARRAY_SIZE(fw_path); i++) {
-               struct file *file;
-               snprintf(path, PATH_MAX, "%s/%s", fw_path[i], name);
-
-               file = filp_open(path, O_RDONLY, 0);
-               if (IS_ERR(file))
-                       continue;
-               success = fw_read_file_contents(file, fw);
-               fput(file);
-               if (success)
-                       break;
-       }
-       __putname(path);
-       return success;
-}
-
 /* Builtin firmware support */
 
 #ifdef CONFIG_FW_LOADER
@@ -150,6 +88,11 @@ enum {
        FW_STATUS_ABORT,
 };
 
+enum fw_buf_fmt {
+       VMALLOC_BUF,    /* used in direct loading */
+       PAGE_BUF,       /* used in loading via userspace */
+};
+
 static int loading_timeout = 60;       /* In seconds */
 
 static inline long firmware_loading_timeout(void)
@@ -173,8 +116,6 @@ struct firmware_cache {
        spinlock_t name_lock;
        struct list_head fw_names;
 
-       wait_queue_head_t wait_queue;
-       int cnt;
        struct delayed_work work;
 
        struct notifier_block   pm_notify;
@@ -187,6 +128,7 @@ struct firmware_buf {
        struct completion completion;
        struct firmware_cache *fwc;
        unsigned long status;
+       enum fw_buf_fmt fmt;
        void *data;
        size_t size;
        struct page **pages;
@@ -240,6 +182,7 @@ static struct firmware_buf *__allocate_fw_buf(const char *fw_name,
        strcpy(buf->fw_id, fw_name);
        buf->fwc = fwc;
        init_completion(&buf->completion);
+       buf->fmt = VMALLOC_BUF;
 
        pr_debug("%s: fw-%s buf=%p\n", __func__, fw_name, buf);
 
@@ -307,10 +250,14 @@ static void __fw_free_buf(struct kref *ref)
        list_del(&buf->list);
        spin_unlock(&fwc->lock);
 
-       vunmap(buf->data);
-       for (i = 0; i < buf->nr_pages; i++)
-               __free_page(buf->pages[i]);
-       kfree(buf->pages);
+
+       if (buf->fmt == PAGE_BUF) {
+               vunmap(buf->data);
+               for (i = 0; i < buf->nr_pages; i++)
+                       __free_page(buf->pages[i]);
+               kfree(buf->pages);
+       } else
+               vfree(buf->data);
        kfree(buf);
 }
 
@@ -319,6 +266,69 @@ static void fw_free_buf(struct firmware_buf *buf)
        kref_put(&buf->ref, __fw_free_buf);
 }
 
+/* direct firmware loading support */
+static const char *fw_path[] = {
+       "/lib/firmware/updates/" UTS_RELEASE,
+       "/lib/firmware/updates",
+       "/lib/firmware/" UTS_RELEASE,
+       "/lib/firmware"
+};
+
+/* Don't inline this: 'struct kstat' is biggish */
+static noinline long fw_file_size(struct file *file)
+{
+       struct kstat st;
+       if (vfs_getattr(file->f_path.mnt, file->f_path.dentry, &st))
+               return -1;
+       if (!S_ISREG(st.mode))
+               return -1;
+       if (st.size != (long)st.size)
+               return -1;
+       return st.size;
+}
+
+static bool fw_read_file_contents(struct file *file, struct firmware_buf *fw_buf)
+{
+       long size;
+       char *buf;
+
+       size = fw_file_size(file);
+       if (size < 0)
+               return false;
+       buf = vmalloc(size);
+       if (!buf)
+               return false;
+       if (kernel_read(file, 0, buf, size) != size) {
+               vfree(buf);
+               return false;
+       }
+       fw_buf->data = buf;
+       fw_buf->size = size;
+       return true;
+}
+
+static bool fw_get_filesystem_firmware(struct firmware_buf *buf)
+{
+       int i;
+       bool success = false;
+       char *path = __getname();
+
+       for (i = 0; i < ARRAY_SIZE(fw_path); i++) {
+               struct file *file;
+               snprintf(path, PATH_MAX, "%s/%s", fw_path[i], buf->fw_id);
+
+               file = filp_open(path, O_RDONLY, 0);
+               if (IS_ERR(file))
+                       continue;
+               success = fw_read_file_contents(file, buf);
+               fput(file);
+               if (success)
+                       break;
+       }
+       __putname(path);
+       return success;
+}
+
 static struct firmware_priv *to_firmware_priv(struct device *dev)
 {
        return container_of(dev, struct firmware_priv, dev);
@@ -423,6 +433,21 @@ static void firmware_free_data(const struct firmware *fw)
 #ifndef PAGE_KERNEL_RO
 #define PAGE_KERNEL_RO PAGE_KERNEL
 #endif
+
+/* one pages buffer should be mapped/unmapped only once */
+static int fw_map_pages_buf(struct firmware_buf *buf)
+{
+       if (buf->fmt != PAGE_BUF)
+               return 0;
+
+       if (buf->data)
+               vunmap(buf->data);
+       buf->data = vmap(buf->pages, buf->nr_pages, 0, PAGE_KERNEL_RO);
+       if (!buf->data)
+               return -ENOMEM;
+       return 0;
+}
+
 /**
  * firmware_loading_store - set value in the 'loading' control file
  * @dev: device pointer
@@ -467,6 +492,14 @@ static ssize_t firmware_loading_store(struct device *dev,
                if (test_bit(FW_STATUS_LOADING, &fw_buf->status)) {
                        set_bit(FW_STATUS_DONE, &fw_buf->status);
                        clear_bit(FW_STATUS_LOADING, &fw_buf->status);
+
+                       /*
+                        * Several loading requests may be pending on
+                        * one same firmware buf, so let all requests
+                        * see the mapped 'buf->data' once the loading
+                        * is completed.
+                        * */
+                       fw_map_pages_buf(fw_buf);
                        complete_all(&fw_buf->completion);
                        break;
                }
@@ -670,15 +703,6 @@ exit:
        return fw_priv;
 }
 
-/* one pages buffer is mapped/unmapped only once */
-static int fw_map_pages_buf(struct firmware_buf *buf)
-{
-       buf->data = vmap(buf->pages, buf->nr_pages, 0, PAGE_KERNEL_RO);
-       if (!buf->data)
-               return -ENOMEM;
-       return 0;
-}
-
 /* store the pages buffer info firmware from buf */
 static void fw_set_page_data(struct firmware_buf *buf, struct firmware *fw)
 {
@@ -778,11 +802,6 @@ _request_firmware_prepare(const struct firmware **firmware_p, const char *name,
                return NULL;
        }
 
-       if (fw_get_filesystem_firmware(firmware, name)) {
-               dev_dbg(device, "firmware: direct-loading firmware %s\n", name);
-               return NULL;
-       }
-
        ret = fw_lookup_and_allocate_buf(name, &fw_cache, &buf);
        if (!ret)
                fw_priv = fw_create_instance(firmware, name, device,
@@ -832,6 +851,21 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent,
        struct device *f_dev = &fw_priv->dev;
        struct firmware_buf *buf = fw_priv->buf;
        struct firmware_cache *fwc = &fw_cache;
+       int direct_load = 0;
+
+       /* try direct loading from fs first */
+       if (fw_get_filesystem_firmware(buf)) {
+               dev_dbg(f_dev->parent, "firmware: direct-loading"
+                       " firmware %s\n", buf->fw_id);
+
+               set_bit(FW_STATUS_DONE, &buf->status);
+               complete_all(&buf->completion);
+               direct_load = 1;
+               goto handle_fw;
+       }
+
+       /* fall back on userspace loading */
+       buf->fmt = PAGE_BUF;
 
        dev_set_uevent_suppress(f_dev, true);
 
@@ -870,6 +904,7 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent,
 
        del_timer_sync(&fw_priv->timeout);
 
+handle_fw:
        mutex_lock(&fw_lock);
        if (!buf->size || test_bit(FW_STATUS_ABORT, &buf->status))
                retval = -ENOENT;
@@ -884,9 +919,6 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent,
        if (!retval && f_dev->parent)
                fw_add_devm_name(f_dev->parent, buf->fw_id);
 
-       if (!retval)
-               retval = fw_map_pages_buf(buf);
-
        /*
         * After caching firmware image is started, let it piggyback
         * on request firmware.
@@ -902,6 +934,9 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent,
        fw_priv->buf = NULL;
        mutex_unlock(&fw_lock);
 
+       if (direct_load)
+               goto err_put_dev;
+
        device_remove_file(f_dev, &dev_attr_loading);
 err_del_bin_attr:
        device_remove_bin_file(f_dev, &firmware_attr_data);
@@ -1129,6 +1164,8 @@ int uncache_firmware(const char *fw_name)
 }
 
 #ifdef CONFIG_PM_SLEEP
+static ASYNC_DOMAIN_EXCLUSIVE(fw_cache_domain);
+
 static struct fw_cache_entry *alloc_fw_cache_entry(const char *name)
 {
        struct fw_cache_entry *fce;
@@ -1142,17 +1179,27 @@ exit:
        return fce;
 }
 
-static int fw_cache_piggyback_on_request(const char *name)
+static int __fw_entry_found(const char *name)
 {
        struct firmware_cache *fwc = &fw_cache;
        struct fw_cache_entry *fce;
-       int ret = 0;
 
-       spin_lock(&fwc->name_lock);
        list_for_each_entry(fce, &fwc->fw_names, list) {
                if (!strcmp(fce->name, name))
-                       goto found;
+                       return 1;
        }
+       return 0;
+}
+
+static int fw_cache_piggyback_on_request(const char *name)
+{
+       struct firmware_cache *fwc = &fw_cache;
+       struct fw_cache_entry *fce;
+       int ret = 0;
+
+       spin_lock(&fwc->name_lock);
+       if (__fw_entry_found(name))
+               goto found;
 
        fce = alloc_fw_cache_entry(name);
        if (fce) {
@@ -1185,12 +1232,6 @@ static void __async_dev_cache_fw_image(void *fw_entry,
 
                free_fw_cache_entry(fce);
        }
-
-       spin_lock(&fwc->name_lock);
-       fwc->cnt--;
-       spin_unlock(&fwc->name_lock);
-
-       wake_up(&fwc->wait_queue);
 }
 
 /* called with dev->devres_lock held */
@@ -1229,11 +1270,19 @@ static void dev_cache_fw_image(struct device *dev, void *data)
                list_del(&fce->list);
 
                spin_lock(&fwc->name_lock);
-               fwc->cnt++;
-               list_add(&fce->list, &fwc->fw_names);
+               /* only one cache entry for one firmware */
+               if (!__fw_entry_found(fce->name)) {
+                       list_add(&fce->list, &fwc->fw_names);
+               } else {
+                       free_fw_cache_entry(fce);
+                       fce = NULL;
+               }
                spin_unlock(&fwc->name_lock);
 
-               async_schedule(__async_dev_cache_fw_image, (void *)fce);
+               if (fce)
+                       async_schedule_domain(__async_dev_cache_fw_image,
+                                             (void *)fce,
+                                             &fw_cache_domain);
        }
 }
 
@@ -1275,6 +1324,9 @@ static void device_cache_fw_images(void)
 
        pr_debug("%s\n", __func__);
 
+       /* cancel uncache work */
+       cancel_delayed_work_sync(&fwc->work);
+
        /*
         * use small loading timeout for caching devices' firmware
         * because all these firmware images have been loaded
@@ -1292,21 +1344,7 @@ static void device_cache_fw_images(void)
        mutex_unlock(&fw_lock);
 
        /* wait for completion of caching firmware for all devices */
-       spin_lock(&fwc->name_lock);
-       for (;;) {
-               prepare_to_wait(&fwc->wait_queue, &wait,
-                               TASK_UNINTERRUPTIBLE);
-               if (!fwc->cnt)
-                       break;
-
-               spin_unlock(&fwc->name_lock);
-
-               schedule();
-
-               spin_lock(&fwc->name_lock);
-       }
-       spin_unlock(&fwc->name_lock);
-       finish_wait(&fwc->wait_queue, &wait);
+       async_synchronize_full_domain(&fw_cache_domain);
 
        loading_timeout = old_timeout;
 }
@@ -1394,9 +1432,7 @@ static void __init fw_cache_init(void)
 #ifdef CONFIG_PM_SLEEP
        spin_lock_init(&fw_cache.name_lock);
        INIT_LIST_HEAD(&fw_cache.fw_names);
-       fw_cache.cnt = 0;
 
-       init_waitqueue_head(&fw_cache.wait_queue);
        INIT_DELAYED_WORK(&fw_cache.work,
                          device_uncache_fw_images_work);
 
index 8727e9c5eea47dd78170e091635f31d29fc7cb52..72c776f2a1f528db39398a0983ae86730ebf24c1 100644 (file)
@@ -83,9 +83,16 @@ EXPORT_SYMBOL_GPL(platform_get_resource);
  */
 int platform_get_irq(struct platform_device *dev, unsigned int num)
 {
+#ifdef CONFIG_SPARC
+       /* sparc does not have irqs represented as IORESOURCE_IRQ resources */
+       if (!dev || num >= dev->archdata.num_irqs)
+               return -ENXIO;
+       return dev->archdata.irqs[num];
+#else
        struct resource *r = platform_get_resource(dev, IORESOURCE_IRQ, num);
 
        return r ? r->start : -ENXIO;
+#endif
 }
 EXPORT_SYMBOL_GPL(platform_get_irq);
 
index c22b869245d9498e7052fdc42ceacf3aaa4e332e..96b71b6536d61cef381dab119533b4a0b13f542e 100644 (file)
@@ -1862,7 +1862,7 @@ int pm_genpd_attach_cpuidle(struct generic_pm_domain *genpd, int state)
        cpuidle_drv = cpuidle_driver_ref();
        if (!cpuidle_drv) {
                ret = -ENODEV;
-               goto out;
+               goto err_drv;
        }
        if (cpuidle_drv->state_count <= state) {
                ret = -EINVAL;
@@ -1884,6 +1884,9 @@ int pm_genpd_attach_cpuidle(struct generic_pm_domain *genpd, int state)
 
  err:
        cpuidle_driver_unref();
+
+ err_drv:
+       kfree(cpu_data);
        goto out;
 }
 
index 74a67e0019a2d246820ccb2858399bca193ff789..fbbd4ed2edf288318f8d165760c91ee420f1812c 100644 (file)
@@ -451,7 +451,7 @@ int dev_pm_qos_add_ancestor_request(struct device *dev,
        if (ancestor)
                error = dev_pm_qos_add_request(ancestor, req, value);
 
-       if (error)
+       if (error < 0)
                req->dev = NULL;
 
        return error;
index 6be390bd8bd1bc3f0fa1e3bfc38cd56f36bfa6be..f0d30543fcce0944d3e619031ea0a828a179e852 100644 (file)
@@ -3,7 +3,7 @@
 # subsystems should select the appropriate symbols.
 
 config REGMAP
-       default y if (REGMAP_I2C || REGMAP_SPI)
+       default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_MMIO || REGMAP_IRQ)
        select LZO_COMPRESS
        select LZO_DECOMPRESS
        select IRQ_DOMAIN if REGMAP_IRQ
index 432aeeedfd5e6992c28ea081e4185bf88ffeed8e..d865470bc9511a12f3c4370dd12bf22c28fc2cf0 100644 (file)
@@ -158,9 +158,10 @@ static int bcma_register_cores(struct bcma_bus *bus)
 
 static void bcma_unregister_cores(struct bcma_bus *bus)
 {
-       struct bcma_device *core;
+       struct bcma_device *core, *tmp;
 
-       list_for_each_entry(core, &bus->cores, list) {
+       list_for_each_entry_safe(core, tmp, &bus->cores, list) {
+               list_del(&core->list);
                if (core->dev_registered)
                        device_unregister(&core->dev);
        }
index f529407db93ff74dbfa8b9dad13324815467fad2..824e09c4d0d7d1bcd83a00b87e37e1ca0115d5fb 100644 (file)
@@ -131,6 +131,7 @@ config BLK_CPQ_DA
 config BLK_CPQ_CISS_DA
        tristate "Compaq Smart Array 5xxx support"
        depends on PCI
+       select CHECK_SIGNATURE
        help
          This is the driver for Compaq Smart Array 5xxx controllers.
          Everyone using these boards should say Y here.
@@ -166,8 +167,8 @@ config BLK_DEV_DAC960
          module will be called DAC960.
 
 config BLK_DEV_UMEM
-       tristate "Micro Memory MM5415 Battery Backed RAM support (EXPERIMENTAL)"
-       depends on PCI && EXPERIMENTAL
+       tristate "Micro Memory MM5415 Battery Backed RAM support"
+       depends on PCI
        ---help---
          Saying Y here will include support for the MM5415 family of
          battery backed (Non-volatile) RAM cards.
@@ -430,8 +431,8 @@ config CDROM_PKTCDVD_BUFFERS
          a disc is opened for writing.
 
 config CDROM_PKTCDVD_WCACHE
-       bool "Enable write caching (EXPERIMENTAL)"
-       depends on CDROM_PKTCDVD && EXPERIMENTAL
+       bool "Enable write caching"
+       depends on CDROM_PKTCDVD
        help
          If enabled, write caching will be set for the CD-R/W device. For now
          this option is dangerous unless the CD-RW media is known good, as we
@@ -508,8 +509,8 @@ config XEN_BLKDEV_BACKEND
 
 
 config VIRTIO_BLK
-       tristate "Virtio block driver (EXPERIMENTAL)"
-       depends on EXPERIMENTAL && VIRTIO
+       tristate "Virtio block driver"
+       depends on VIRTIO
        ---help---
          This is the virtual block driver for virtio.  It can be used with
           lguest or QEMU based VMMs (like KVM or Xen).  Say Y or M.
@@ -528,7 +529,7 @@ config BLK_DEV_HD
 
 config BLK_DEV_RBD
        tristate "Rados block device (RBD)"
-       depends on INET && EXPERIMENTAL && BLOCK
+       depends on INET && BLOCK
        select CEPH_LIB
        select LIBCRC32C
        select CRYPTO_AES
index 3804a0af3ef192c441643eee425d06f747b86d97..9fe4f1865558abce9ccd7ebf1ee10a56284caf61 100644 (file)
@@ -935,7 +935,7 @@ aoe_end_request(struct aoedev *d, struct request *rq, int fastfail)
 
        /* cf. http://lkml.org/lkml/2006/10/31/28 */
        if (!fastfail)
-               q->request_fn(q);
+               __blk_run_queue(q);
 }
 
 static void
index b0f553b26d0f8d00f86f768f93aad27ebcb0529e..ca83f96756ad86b2a339971050b7378f9a9752d9 100644 (file)
@@ -5205,7 +5205,6 @@ static void cciss_shutdown(struct pci_dev *pdev)
                return;
        }
        /* write all data in the battery backed cache to disk */
-       memset(flush_buf, 0, 4);
        return_code = sendcmd_withirq(h, CCISS_CACHE_FLUSH, flush_buf,
                4, 0, CTLR_LUNID, TYPE_CMD);
        kfree(flush_buf);
index 17c675c522954cc39a210e431603aac2a3a2d946..2ddd64a9ffdee43429653806be3262a80c372240 100644 (file)
@@ -4109,12 +4109,19 @@ static struct platform_driver floppy_driver = {
 
 static struct platform_device floppy_device[N_DRIVE];
 
+static bool floppy_available(int drive)
+{
+       if (!(allowed_drive_mask & (1 << drive)))
+               return false;
+       if (fdc_state[FDC(drive)].version == FDC_NONE)
+               return false;
+       return true;
+}
+
 static struct kobject *floppy_find(dev_t dev, int *part, void *data)
 {
        int drive = (*part & 3) | ((*part & 0x80) >> 5);
-       if (drive >= N_DRIVE ||
-           !(allowed_drive_mask & (1 << drive)) ||
-           fdc_state[FDC(drive)].version == FDC_NONE)
+       if (drive >= N_DRIVE || !floppy_available(drive))
                return NULL;
        if (((*part >> 2) & 0x1f) >= ARRAY_SIZE(floppy_type))
                return NULL;
@@ -4124,8 +4131,7 @@ static struct kobject *floppy_find(dev_t dev, int *part, void *data)
 
 static int __init do_floppy_init(void)
 {
-       int i, unit, drive;
-       int err, dr;
+       int i, unit, drive, err;
 
        set_debugt();
        interruptjiffies = resultjiffies = jiffies;
@@ -4137,34 +4143,32 @@ static int __init do_floppy_init(void)
 
        raw_cmd = NULL;
 
-       for (dr = 0; dr < N_DRIVE; dr++) {
-               disks[dr] = alloc_disk(1);
-               if (!disks[dr]) {
-                       err = -ENOMEM;
-                       goto out_put_disk;
-               }
+       floppy_wq = alloc_ordered_workqueue("floppy", 0);
+       if (!floppy_wq)
+               return -ENOMEM;
 
-               floppy_wq = alloc_ordered_workqueue("floppy", 0);
-               if (!floppy_wq) {
+       for (drive = 0; drive < N_DRIVE; drive++) {
+               disks[drive] = alloc_disk(1);
+               if (!disks[drive]) {
                        err = -ENOMEM;
                        goto out_put_disk;
                }
 
-               disks[dr]->queue = blk_init_queue(do_fd_request, &floppy_lock);
-               if (!disks[dr]->queue) {
+               disks[drive]->queue = blk_init_queue(do_fd_request, &floppy_lock);
+               if (!disks[drive]->queue) {
                        err = -ENOMEM;
-                       goto out_destroy_workq;
+                       goto out_put_disk;
                }
 
-               blk_queue_max_hw_sectors(disks[dr]->queue, 64);
-               disks[dr]->major = FLOPPY_MAJOR;
-               disks[dr]->first_minor = TOMINOR(dr);
-               disks[dr]->fops = &floppy_fops;
-               sprintf(disks[dr]->disk_name, "fd%d", dr);
+               blk_queue_max_hw_sectors(disks[drive]->queue, 64);
+               disks[drive]->major = FLOPPY_MAJOR;
+               disks[drive]->first_minor = TOMINOR(drive);
+               disks[drive]->fops = &floppy_fops;
+               sprintf(disks[drive]->disk_name, "fd%d", drive);
 
-               init_timer(&motor_off_timer[dr]);
-               motor_off_timer[dr].data = dr;
-               motor_off_timer[dr].function = motor_off_callback;
+               init_timer(&motor_off_timer[drive]);
+               motor_off_timer[drive].data = drive;
+               motor_off_timer[drive].function = motor_off_callback;
        }
 
        err = register_blkdev(FLOPPY_MAJOR, "fd");
@@ -4282,9 +4286,7 @@ static int __init do_floppy_init(void)
        }
 
        for (drive = 0; drive < N_DRIVE; drive++) {
-               if (!(allowed_drive_mask & (1 << drive)))
-                       continue;
-               if (fdc_state[FDC(drive)].version == FDC_NONE)
+               if (!floppy_available(drive))
                        continue;
 
                floppy_device[drive].name = floppy_device_name;
@@ -4293,7 +4295,7 @@ static int __init do_floppy_init(void)
 
                err = platform_device_register(&floppy_device[drive]);
                if (err)
-                       goto out_release_dma;
+                       goto out_remove_drives;
 
                err = device_create_file(&floppy_device[drive].dev,
                                         &dev_attr_cmos);
@@ -4311,28 +4313,33 @@ static int __init do_floppy_init(void)
 
 out_unreg_platform_dev:
        platform_device_unregister(&floppy_device[drive]);
+out_remove_drives:
+       while (drive--) {
+               if (floppy_available(drive)) {
+                       del_gendisk(disks[drive]);
+                       device_remove_file(&floppy_device[drive].dev, &dev_attr_cmos);
+                       platform_device_unregister(&floppy_device[drive]);
+               }
+       }
 out_release_dma:
        if (atomic_read(&usage_count))
                floppy_release_irq_and_dma();
 out_unreg_region:
        blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
        platform_driver_unregister(&floppy_driver);
-out_destroy_workq:
-       destroy_workqueue(floppy_wq);
 out_unreg_blkdev:
        unregister_blkdev(FLOPPY_MAJOR, "fd");
 out_put_disk:
-       while (dr--) {
-               del_timer_sync(&motor_off_timer[dr]);
-               if (disks[dr]->queue) {
-                       blk_cleanup_queue(disks[dr]->queue);
-                       /*
-                        * put_disk() is not paired with add_disk() and
-                        * will put queue reference one extra time. fix it.
-                        */
-                       disks[dr]->queue = NULL;
+       destroy_workqueue(floppy_wq);
+       for (drive = 0; drive < N_DRIVE; drive++) {
+               if (!disks[drive])
+                       break;
+               if (disks[drive]->queue) {
+                       del_timer_sync(&motor_off_timer[drive]);
+                       blk_cleanup_queue(disks[drive]->queue);
+                       disks[drive]->queue = NULL;
                }
-               put_disk(disks[dr]);
+               put_disk(disks[drive]);
        }
        return err;
 }
@@ -4548,11 +4555,12 @@ static void __exit floppy_module_exit(void)
        unregister_blkdev(FLOPPY_MAJOR, "fd");
        platform_driver_unregister(&floppy_driver);
 
+       destroy_workqueue(floppy_wq);
+
        for (drive = 0; drive < N_DRIVE; drive++) {
                del_timer_sync(&motor_off_timer[drive]);
 
-               if ((allowed_drive_mask & (1 << drive)) &&
-                   fdc_state[FDC(drive)].version != FDC_NONE) {
+               if (floppy_available(drive)) {
                        del_gendisk(disks[drive]);
                        device_remove_file(&floppy_device[drive].dev, &dev_attr_cmos);
                        platform_device_unregister(&floppy_device[drive]);
@@ -4572,7 +4580,6 @@ static void __exit floppy_module_exit(void)
 
        cancel_delayed_work_sync(&fd_timeout);
        cancel_delayed_work_sync(&fd_timer);
-       destroy_workqueue(floppy_wq);
 
        if (atomic_read(&usage_count))
                floppy_release_irq_and_dma();
index e9d594fd12cbee408251c4ead03d1b71183ff7ae..54046e51160aef28e3ee733797fa453a0403a02a 100644 (file)
@@ -976,8 +976,21 @@ static int loop_clr_fd(struct loop_device *lo)
        if (lo->lo_state != Lo_bound)
                return -ENXIO;
 
-       if (lo->lo_refcnt > 1)  /* we needed one fd for the ioctl */
-               return -EBUSY;
+       /*
+        * If we've explicitly asked to tear down the loop device,
+        * and it has an elevated reference count, set it for auto-teardown when
+        * the last reference goes away. This stops $!~#$@ udev from
+        * preventing teardown because it decided that it needs to run blkid on
+        * the loopback device whenever they appear. xfstests is notorious for
+        * failing tests because blkid via udev races with a losetup
+        * <dev>/do something like mkfs/losetup -d <dev> causing the losetup -d
+        * command to fail with EBUSY.
+        */
+       if (lo->lo_refcnt > 1) {
+               lo->lo_flags |= LO_FLAGS_AUTOCLEAR;
+               mutex_unlock(&lo->lo_ctl_mutex);
+               return 0;
+       }
 
        if (filp == NULL)
                return -EINVAL;
index f946d31d6917e00aa0637df5d21cef35ebf82845..9694dd99bbbc7253af1c3626823899f985b1afc2 100644 (file)
@@ -559,7 +559,7 @@ static void mtip_timeout_function(unsigned long int data)
        struct mtip_cmd *command;
        int tag, cmdto_cnt = 0;
        unsigned int bit, group;
-       unsigned int num_command_slots = port->dd->slot_groups * 32;
+       unsigned int num_command_slots;
        unsigned long to, tagaccum[SLOTBITS_IN_LONGS];
 
        if (unlikely(!port))
@@ -572,6 +572,7 @@ static void mtip_timeout_function(unsigned long int data)
        }
        /* clear the tag accumulator */
        memset(tagaccum, 0, SLOTBITS_IN_LONGS * sizeof(long));
+       num_command_slots = port->dd->slot_groups * 32;
 
        for (tag = 0; tag < num_command_slots; tag++) {
                /*
@@ -2035,8 +2036,9 @@ static unsigned int implicit_sector(unsigned char command,
        }
        return rv;
 }
-
-static void mtip_set_timeout(struct host_to_dev_fis *fis, unsigned int *timeout)
+static void mtip_set_timeout(struct driver_data *dd,
+                                       struct host_to_dev_fis *fis,
+                                       unsigned int *timeout, u8 erasemode)
 {
        switch (fis->command) {
        case ATA_CMD_DOWNLOAD_MICRO:
@@ -2044,7 +2046,10 @@ static void mtip_set_timeout(struct host_to_dev_fis *fis, unsigned int *timeout)
                break;
        case ATA_CMD_SEC_ERASE_UNIT:
        case 0xFC:
-               *timeout = 240000; /* 4 minutes */
+               if (erasemode)
+                       *timeout = ((*(dd->port->identify + 90) * 2) * 60000);
+               else
+                       *timeout = ((*(dd->port->identify + 89) * 2) * 60000);
                break;
        case ATA_CMD_STANDBYNOW1:
                *timeout = 120000;  /* 2 minutes */
@@ -2087,6 +2092,7 @@ static int exec_drive_taskfile(struct driver_data *dd,
        unsigned int transfer_size;
        unsigned long task_file_data;
        int intotal = outtotal + req_task->out_size;
+       int erasemode = 0;
 
        taskout = req_task->out_size;
        taskin = req_task->in_size;
@@ -2212,7 +2218,13 @@ static int exec_drive_taskfile(struct driver_data *dd,
                fis.lba_hi,
                fis.device);
 
-       mtip_set_timeout(&fis, &timeout);
+       /* check for erase mode support during secure erase.*/
+       if ((fis.command == ATA_CMD_SEC_ERASE_UNIT) && outbuf &&
+                                       (outbuf[0] & MTIP_SEC_ERASE_MODE)) {
+               erasemode = 1;
+       }
+
+       mtip_set_timeout(dd, &fis, &timeout, erasemode);
 
        /* Determine the correct transfer size.*/
        if (force_single_sector)
@@ -2428,7 +2440,7 @@ static int mtip_hw_ioctl(struct driver_data *dd, unsigned int cmd,
  * return value
  *     None
  */
-static void mtip_hw_submit_io(struct driver_data *dd, sector_t start,
+static void mtip_hw_submit_io(struct driver_data *dd, sector_t sector,
                              int nsect, int nents, int tag, void *callback,
                              void *data, int dir)
 {
@@ -2436,6 +2448,7 @@ static void mtip_hw_submit_io(struct driver_data *dd, sector_t start,
        struct mtip_port *port = dd->port;
        struct mtip_cmd *command = &port->commands[tag];
        int dma_dir = (dir == READ) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+       u64 start = sector;
 
        /* Map the scatter list for DMA access */
        nents = dma_map_sg(&dd->pdev->dev, command->sg, nents, dma_dir);
@@ -2454,8 +2467,12 @@ static void mtip_hw_submit_io(struct driver_data *dd, sector_t start,
        fis->opts        = 1 << 7;
        fis->command     =
                (dir == READ ? ATA_CMD_FPDMA_READ : ATA_CMD_FPDMA_WRITE);
-       *((unsigned int *) &fis->lba_low) = (start & 0xFFFFFF);
-       *((unsigned int *) &fis->lba_low_ex) = ((start >> 24) & 0xFFFFFF);
+       fis->lba_low     = start & 0xFF;
+       fis->lba_mid     = (start >> 8) & 0xFF;
+       fis->lba_hi      = (start >> 16) & 0xFF;
+       fis->lba_low_ex  = (start >> 24) & 0xFF;
+       fis->lba_mid_ex  = (start >> 32) & 0xFF;
+       fis->lba_hi_ex   = (start >> 40) & 0xFF;
        fis->device      = 1 << 6;
        fis->features    = nsect & 0xFF;
        fis->features_ex = (nsect >> 8) & 0xFF;
index 18627a1d04c59eff34f7cdd2313555b10a75b283..b1742640556a782cee77701c78c4ddf7e961591a 100644 (file)
@@ -33,6 +33,9 @@
 /* offset of Device Control register in PCIe extended capabilites space */
 #define PCIE_CONFIG_EXT_DEVICE_CONTROL_OFFSET  0x48
 
+/* check for erase mode support during secure erase */
+#define MTIP_SEC_ERASE_MODE     0x2
+
 /* # of times to retry timed out/failed IOs */
 #define MTIP_MAX_RETRIES       2
 
@@ -152,14 +155,14 @@ enum {
        MTIP_DDF_REBUILD_FAILED_BIT = 8,
 };
 
-__packed struct smart_attr{
+struct smart_attr {
        u8 attr_id;
        u16 flags;
        u8 cur;
        u8 worst;
        u32 data;
        u8 res[3];
-};
+} __packed;
 
 /* Register Frame Information Structure (FIS), host to device. */
 struct host_to_dev_fis {
index 9ad3b5ec1dc1c521085db47a7928cc8cf1179701..9a54623e52d74ecc77953937bd923a9ecdb68d09 100644 (file)
@@ -158,8 +158,8 @@ struct xen_vbd {
        struct block_device     *bdev;
        /* Cached size parameter. */
        sector_t                size;
-       bool                    flush_support;
-       bool                    discard_secure;
+       unsigned int            flush_support:1;
+       unsigned int            discard_secure:1;
 };
 
 struct backend_info;
index 4f66171c668354b490f1284aec48278b8676bd84..f58434c2617cab4185b8c049804f1031f4226a6e 100644 (file)
@@ -105,11 +105,10 @@ static struct xen_blkif *xen_blkif_alloc(domid_t domid)
 {
        struct xen_blkif *blkif;
 
-       blkif = kmem_cache_alloc(xen_blkif_cachep, GFP_KERNEL);
+       blkif = kmem_cache_zalloc(xen_blkif_cachep, GFP_KERNEL);
        if (!blkif)
                return ERR_PTR(-ENOMEM);
 
-       memset(blkif, 0, sizeof(*blkif));
        blkif->domid = domid;
        spin_lock_init(&blkif->blk_ring_lock);
        atomic_set(&blkif->refcnt, 1);
@@ -196,7 +195,7 @@ static void xen_blkif_disconnect(struct xen_blkif *blkif)
        }
 }
 
-void xen_blkif_free(struct xen_blkif *blkif)
+static void xen_blkif_free(struct xen_blkif *blkif)
 {
        if (!atomic_dec_and_test(&blkif->refcnt))
                BUG();
@@ -257,7 +256,7 @@ static struct attribute_group xen_vbdstat_group = {
 VBD_SHOW(physical_device, "%x:%x\n", be->major, be->minor);
 VBD_SHOW(mode, "%s\n", be->mode);
 
-int xenvbd_sysfs_addif(struct xenbus_device *dev)
+static int xenvbd_sysfs_addif(struct xenbus_device *dev)
 {
        int error;
 
@@ -281,7 +280,7 @@ fail1:      device_remove_file(&dev->dev, &dev_attr_physical_device);
        return error;
 }
 
-void xenvbd_sysfs_delif(struct xenbus_device *dev)
+static void xenvbd_sysfs_delif(struct xenbus_device *dev)
 {
        sysfs_remove_group(&dev->dev.kobj, &xen_vbdstat_group);
        device_remove_file(&dev->dev, &dev_attr_mode);
index fc2de5528dcc94eb65537baa17b78048a5002827..b00000e8aef6f9cb06955049d3fa4faaba25e38b 100644 (file)
@@ -67,6 +67,7 @@ static struct usb_device_id ath3k_table[] = {
        { USB_DEVICE(0x13d3, 0x3304) },
        { USB_DEVICE(0x0930, 0x0215) },
        { USB_DEVICE(0x0489, 0xE03D) },
+       { USB_DEVICE(0x0489, 0xE027) },
 
        /* Atheros AR9285 Malbec with sflash firmware */
        { USB_DEVICE(0x03F0, 0x311D) },
index debda27df9b0452e3d7f3e5d2b06855c1b7af1f4..ee82f2fb65f0ab2c76135416ac8547f1d9c1fa3c 100644 (file)
@@ -124,6 +124,7 @@ static struct usb_device_id blacklist_table[] = {
        { USB_DEVICE(0x13d3, 0x3304), .driver_info = BTUSB_IGNORE },
        { USB_DEVICE(0x0930, 0x0215), .driver_info = BTUSB_IGNORE },
        { USB_DEVICE(0x0489, 0xe03d), .driver_info = BTUSB_IGNORE },
+       { USB_DEVICE(0x0489, 0xe027), .driver_info = BTUSB_IGNORE },
 
        /* Atheros AR9285 Malbec with sflash firmware */
        { USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE },
index ff63560b8467962ae781d5c3d6b64c122129a390..0c48b0e05ed6e7165a221399822e894e09c9fa18 100644 (file)
 #include <linux/pm_runtime.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
+#include <linux/platform_data/omap_ocp2scp.h>
+
+/**
+ * _count_resources - count for the number of resources
+ * @res: struct resource *
+ *
+ * Count and return the number of resources populated for the device that is
+ * connected to ocp2scp.
+ */
+static unsigned _count_resources(struct resource *res)
+{
+       int cnt = 0;
+
+       while (res->start != res->end) {
+               cnt++;
+               res++;
+       }
+
+       return cnt;
+}
 
 static int ocp2scp_remove_devices(struct device *dev, void *c)
 {
@@ -34,20 +54,62 @@ static int ocp2scp_remove_devices(struct device *dev, void *c)
 
 static int __devinit omap_ocp2scp_probe(struct platform_device *pdev)
 {
-       int                     ret;
-       struct device_node      *np = pdev->dev.of_node;
+       int ret;
+       unsigned res_cnt, i;
+       struct device_node *np = pdev->dev.of_node;
+       struct platform_device *pdev_child;
+       struct omap_ocp2scp_platform_data *pdata = pdev->dev.platform_data;
+       struct omap_ocp2scp_dev *dev;
 
        if (np) {
                ret = of_platform_populate(np, NULL, NULL, &pdev->dev);
                if (ret) {
-                       dev_err(&pdev->dev, "failed to add resources for ocp2scp child\n");
+                       dev_err(&pdev->dev,
+                           "failed to add resources for ocp2scp child\n");
                        goto err0;
                }
+       } else if (pdata) {
+               for (i = 0, dev = *pdata->devices; i < pdata->dev_cnt; i++,
+                   dev++) {
+                       res_cnt = _count_resources(dev->res);
+
+                       pdev_child = platform_device_alloc(dev->drv_name,
+                           PLATFORM_DEVID_AUTO);
+                       if (!pdev_child) {
+                               dev_err(&pdev->dev,
+                                 "failed to allocate mem for ocp2scp child\n");
+                               goto err0;
+                       }
+
+                       ret = platform_device_add_resources(pdev_child,
+                           dev->res, res_cnt);
+                       if (ret) {
+                               dev_err(&pdev->dev,
+                                "failed to add resources for ocp2scp child\n");
+                               goto err1;
+                       }
+
+                       pdev_child->dev.parent  = &pdev->dev;
+
+                       ret = platform_device_add(pdev_child);
+                       if (ret) {
+                               dev_err(&pdev->dev,
+                                  "failed to register ocp2scp child device\n");
+                               goto err1;
+                       }
+               }
+       } else {
+               dev_err(&pdev->dev, "OCP2SCP initialized without plat data\n");
+               return -EINVAL;
        }
+
        pm_runtime_enable(&pdev->dev);
 
        return 0;
 
+err1:
+       platform_device_put(pdev_child);
+
 err0:
        device_for_each_child(&pdev->dev, NULL, ocp2scp_remove_devices);
 
index 320debbe32faf74032f5117cfaf461cbd65a63a3..9b4f0116ff21c95d73d2ad2da39d7fb40dc24ee8 100644 (file)
@@ -1456,7 +1456,7 @@ static int __devexit sonypi_remove(struct platform_device *dev)
        return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int old_camera_power;
 
 static int sonypi_suspend(struct device *dev)
index ca4a25ed844c379315c2834dcd239c4b9d50940d..e2c17d187d98b7bb09fe4252258641bbd424a1c5 100644 (file)
@@ -40,7 +40,7 @@ void u8500_clk_init(void)
                                CLK_IS_ROOT|CLK_IGNORE_UNUSED,
                                32768);
        clk_register_clkdev(clk, "clk32k", NULL);
-       clk_register_clkdev(clk, NULL, "rtc-pl031");
+       clk_register_clkdev(clk, "apb_pclk", "rtc-pl031");
 
        /* PRCMU clocks */
        fw_version = prcmu_get_fw_version();
@@ -228,10 +228,17 @@ void u8500_clk_init(void)
 
        clk = clk_reg_prcc_pclk("p1_pclk2", "per1clk", U8500_CLKRST1_BASE,
                                BIT(2), 0);
+       clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.1");
+
        clk = clk_reg_prcc_pclk("p1_pclk3", "per1clk", U8500_CLKRST1_BASE,
                                BIT(3), 0);
+       clk_register_clkdev(clk, "apb_pclk", "msp0");
+       clk_register_clkdev(clk, "apb_pclk", "ux500-msp-i2s.0");
+
        clk = clk_reg_prcc_pclk("p1_pclk4", "per1clk", U8500_CLKRST1_BASE,
                                BIT(4), 0);
+       clk_register_clkdev(clk, "apb_pclk", "msp1");
+       clk_register_clkdev(clk, "apb_pclk", "ux500-msp-i2s.1");
 
        clk = clk_reg_prcc_pclk("p1_pclk5", "per1clk", U8500_CLKRST1_BASE,
                                BIT(5), 0);
@@ -239,6 +246,7 @@ void u8500_clk_init(void)
 
        clk = clk_reg_prcc_pclk("p1_pclk6", "per1clk", U8500_CLKRST1_BASE,
                                BIT(6), 0);
+       clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.2");
 
        clk = clk_reg_prcc_pclk("p1_pclk7", "per1clk", U8500_CLKRST1_BASE,
                                BIT(7), 0);
@@ -246,6 +254,7 @@ void u8500_clk_init(void)
 
        clk = clk_reg_prcc_pclk("p1_pclk8", "per1clk", U8500_CLKRST1_BASE,
                                BIT(8), 0);
+       clk_register_clkdev(clk, "apb_pclk", "slimbus0");
 
        clk = clk_reg_prcc_pclk("p1_pclk9", "per1clk", U8500_CLKRST1_BASE,
                                BIT(9), 0);
@@ -255,11 +264,16 @@ void u8500_clk_init(void)
 
        clk = clk_reg_prcc_pclk("p1_pclk10", "per1clk", U8500_CLKRST1_BASE,
                                BIT(10), 0);
+       clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.4");
+
        clk = clk_reg_prcc_pclk("p1_pclk11", "per1clk", U8500_CLKRST1_BASE,
                                BIT(11), 0);
+       clk_register_clkdev(clk, "apb_pclk", "msp3");
+       clk_register_clkdev(clk, "apb_pclk", "ux500-msp-i2s.3");
 
        clk = clk_reg_prcc_pclk("p2_pclk0", "per2clk", U8500_CLKRST2_BASE,
                                BIT(0), 0);
+       clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.3");
 
        clk = clk_reg_prcc_pclk("p2_pclk1", "per2clk", U8500_CLKRST2_BASE,
                                BIT(1), 0);
@@ -279,12 +293,13 @@ void u8500_clk_init(void)
 
        clk = clk_reg_prcc_pclk("p2_pclk5", "per2clk", U8500_CLKRST2_BASE,
                                BIT(5), 0);
+       clk_register_clkdev(clk, "apb_pclk", "msp2");
+       clk_register_clkdev(clk, "apb_pclk", "ux500-msp-i2s.2");
 
        clk = clk_reg_prcc_pclk("p2_pclk6", "per2clk", U8500_CLKRST2_BASE,
                                BIT(6), 0);
        clk_register_clkdev(clk, "apb_pclk", "sdi1");
 
-
        clk = clk_reg_prcc_pclk("p2_pclk7", "per2clk", U8500_CLKRST2_BASE,
                                BIT(7), 0);
        clk_register_clkdev(clk, "apb_pclk", "sdi3");
@@ -316,10 +331,15 @@ void u8500_clk_init(void)
 
        clk = clk_reg_prcc_pclk("p3_pclk1", "per3clk", U8500_CLKRST3_BASE,
                                BIT(1), 0);
+       clk_register_clkdev(clk, "apb_pclk", "ssp0");
+
        clk = clk_reg_prcc_pclk("p3_pclk2", "per3clk", U8500_CLKRST3_BASE,
                                BIT(2), 0);
+       clk_register_clkdev(clk, "apb_pclk", "ssp1");
+
        clk = clk_reg_prcc_pclk("p3_pclk3", "per3clk", U8500_CLKRST3_BASE,
                                BIT(3), 0);
+       clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.0");
 
        clk = clk_reg_prcc_pclk("p3_pclk4", "per3clk", U8500_CLKRST3_BASE,
                                BIT(4), 0);
@@ -401,10 +421,17 @@ void u8500_clk_init(void)
 
        clk = clk_reg_prcc_kclk("p1_i2c1_kclk", "i2cclk",
                        U8500_CLKRST1_BASE, BIT(2), CLK_SET_RATE_GATE);
+       clk_register_clkdev(clk, NULL, "nmk-i2c.1");
+
        clk = clk_reg_prcc_kclk("p1_msp0_kclk", "msp02clk",
                        U8500_CLKRST1_BASE, BIT(3), CLK_SET_RATE_GATE);
+       clk_register_clkdev(clk, NULL, "msp0");
+       clk_register_clkdev(clk, NULL, "ux500-msp-i2s.0");
+
        clk = clk_reg_prcc_kclk("p1_msp1_kclk", "msp1clk",
                        U8500_CLKRST1_BASE, BIT(4), CLK_SET_RATE_GATE);
+       clk_register_clkdev(clk, NULL, "msp1");
+       clk_register_clkdev(clk, NULL, "ux500-msp-i2s.1");
 
        clk = clk_reg_prcc_kclk("p1_sdi0_kclk", "sdmmcclk",
                        U8500_CLKRST1_BASE, BIT(5), CLK_SET_RATE_GATE);
@@ -412,17 +439,25 @@ void u8500_clk_init(void)
 
        clk = clk_reg_prcc_kclk("p1_i2c2_kclk", "i2cclk",
                        U8500_CLKRST1_BASE, BIT(6), CLK_SET_RATE_GATE);
+       clk_register_clkdev(clk, NULL, "nmk-i2c.2");
+
        clk = clk_reg_prcc_kclk("p1_slimbus0_kclk", "slimclk",
-                       U8500_CLKRST1_BASE, BIT(3), CLK_SET_RATE_GATE);
-       /* FIXME: Redefinition of BIT(3). */
+                       U8500_CLKRST1_BASE, BIT(8), CLK_SET_RATE_GATE);
+       clk_register_clkdev(clk, NULL, "slimbus0");
+
        clk = clk_reg_prcc_kclk("p1_i2c4_kclk", "i2cclk",
                        U8500_CLKRST1_BASE, BIT(9), CLK_SET_RATE_GATE);
+       clk_register_clkdev(clk, NULL, "nmk-i2c.4");
+
        clk = clk_reg_prcc_kclk("p1_msp3_kclk", "msp1clk",
                        U8500_CLKRST1_BASE, BIT(10), CLK_SET_RATE_GATE);
+       clk_register_clkdev(clk, NULL, "msp3");
+       clk_register_clkdev(clk, NULL, "ux500-msp-i2s.3");
 
        /* Periph2 */
        clk = clk_reg_prcc_kclk("p2_i2c3_kclk", "i2cclk",
                        U8500_CLKRST2_BASE, BIT(0), CLK_SET_RATE_GATE);
+       clk_register_clkdev(clk, NULL, "nmk-i2c.3");
 
        clk = clk_reg_prcc_kclk("p2_sdi4_kclk", "sdmmcclk",
                        U8500_CLKRST2_BASE, BIT(2), CLK_SET_RATE_GATE);
@@ -430,6 +465,8 @@ void u8500_clk_init(void)
 
        clk = clk_reg_prcc_kclk("p2_msp2_kclk", "msp02clk",
                        U8500_CLKRST2_BASE, BIT(3), CLK_SET_RATE_GATE);
+       clk_register_clkdev(clk, NULL, "msp2");
+       clk_register_clkdev(clk, NULL, "ux500-msp-i2s.2");
 
        clk = clk_reg_prcc_kclk("p2_sdi1_kclk", "sdmmcclk",
                        U8500_CLKRST2_BASE, BIT(4), CLK_SET_RATE_GATE);
@@ -450,10 +487,15 @@ void u8500_clk_init(void)
        /* Periph3 */
        clk = clk_reg_prcc_kclk("p3_ssp0_kclk", "sspclk",
                        U8500_CLKRST3_BASE, BIT(1), CLK_SET_RATE_GATE);
+       clk_register_clkdev(clk, NULL, "ssp0");
+
        clk = clk_reg_prcc_kclk("p3_ssp1_kclk", "sspclk",
                        U8500_CLKRST3_BASE, BIT(2), CLK_SET_RATE_GATE);
+       clk_register_clkdev(clk, NULL, "ssp1");
+
        clk = clk_reg_prcc_kclk("p3_i2c0_kclk", "i2cclk",
                        U8500_CLKRST3_BASE, BIT(3), CLK_SET_RATE_GATE);
+       clk_register_clkdev(clk, NULL, "nmk-i2c.0");
 
        clk = clk_reg_prcc_kclk("p3_sdi2_kclk", "sdmmcclk",
                        U8500_CLKRST3_BASE, BIT(4), CLK_SET_RATE_GATE);
index b40ee1403be9b657ffcabd5142650ddb926fb367..399831690fedc18a263636a89725ec7b9af7dadb 100644 (file)
@@ -328,6 +328,7 @@ static int __cpuinit cpufreq_stat_cpu_callback(struct notifier_block *nfb,
                cpufreq_update_policy(cpu);
                break;
        case CPU_DOWN_PREPARE:
+       case CPU_DOWN_PREPARE_FROZEN:
                cpufreq_stats_free_sysfs(cpu);
                break;
        case CPU_DEAD:
index 129e80bfff22e1d399fbe5320012f5721de1bcaf..e3ebb4fa2c3e5045c04f6b0b864a4499064fcbff 100644 (file)
@@ -5,7 +5,7 @@
  *  http://www.gnu.org/licenses/gpl.html
  *
  *  Maintainer:
- *  Andreas Herrmann <andreas.herrmann3@amd.com>
+ *  Andreas Herrmann <herrmann.der.user@googlemail.com>
  *
  *  Based on the powernow-k7.c module written by Dave Jones.
  *  (C) 2003 Dave Jones on behalf of SuSE Labs
@@ -1052,14 +1052,7 @@ static int powernowk8_target(struct cpufreq_policy *pol,
        struct powernowk8_target_arg pta = { .pol = pol, .targfreq = targfreq,
                                             .relation = relation };
 
-       /*
-        * Must run on @pol->cpu.  cpufreq core is responsible for ensuring
-        * that we're bound to the current CPU and pol->cpu stays online.
-        */
-       if (smp_processor_id() == pol->cpu)
-               return powernowk8_target_fn(&pta);
-       else
-               return work_on_cpu(pol->cpu, powernowk8_target_fn, &pta);
+       return work_on_cpu(pol->cpu, powernowk8_target_fn, &pta);
 }
 
 /* Driver entry point to verify the policy and range of frequencies */
index 677cd6e4e1a1c1afb387217fdc9f0f363c3149cf..d4c12180c65416043dbbf3940374ad146daad881 100644 (file)
@@ -90,6 +90,17 @@ config DW_DMAC
          Support the Synopsys DesignWare AHB DMA controller.  This
          can be integrated in chips such as the Atmel AT32ap7000.
 
+config DW_DMAC_BIG_ENDIAN_IO
+       bool "Use big endian I/O register access"
+       default y if AVR32
+       depends on DW_DMAC
+       help
+         Say yes here to use big endian I/O access when reading and writing
+         to the DMA controller registers. This is needed on some platforms,
+         like the Atmel AVR32 architecture.
+
+         If unsure, use the default setting.
+
 config AT_HDMAC
        tristate "Atmel AHB DMA support"
        depends on ARCH_AT91
index ff39fa6cd2bc443a7d96fd9d85be015f643704f5..88965597b7d08c9e2b9987957f85284cc9851f4c 100644 (file)
@@ -98,9 +98,17 @@ struct dw_dma_regs {
        u32     DW_PARAMS;
 };
 
+#ifdef CONFIG_DW_DMAC_BIG_ENDIAN_IO
+#define dma_readl_native ioread32be
+#define dma_writel_native iowrite32be
+#else
+#define dma_readl_native readl
+#define dma_writel_native writel
+#endif
+
 /* To access the registers in early stage of probe */
 #define dma_read_byaddr(addr, name) \
-       readl((addr) + offsetof(struct dw_dma_regs, name))
+       dma_readl_native((addr) + offsetof(struct dw_dma_regs, name))
 
 /* Bitfields in DW_PARAMS */
 #define DW_PARAMS_NR_CHAN      8               /* number of channels */
@@ -216,9 +224,9 @@ __dwc_regs(struct dw_dma_chan *dwc)
 }
 
 #define channel_readl(dwc, name) \
-       readl(&(__dwc_regs(dwc)->name))
+       dma_readl_native(&(__dwc_regs(dwc)->name))
 #define channel_writel(dwc, name, val) \
-       writel((val), &(__dwc_regs(dwc)->name))
+       dma_writel_native((val), &(__dwc_regs(dwc)->name))
 
 static inline struct dw_dma_chan *to_dw_dma_chan(struct dma_chan *chan)
 {
@@ -246,9 +254,9 @@ static inline struct dw_dma_regs __iomem *__dw_regs(struct dw_dma *dw)
 }
 
 #define dma_readl(dw, name) \
-       readl(&(__dw_regs(dw)->name))
+       dma_readl_native(&(__dw_regs(dw)->name))
 #define dma_writel(dw, name, val) \
-       writel((val), &(__dw_regs(dw)->name))
+       dma_writel_native((val), &(__dw_regs(dw)->name))
 
 #define channel_set_bit(dw, reg, mask) \
        dma_writel(dw, reg, ((mask) << 8) | (mask))
index f11b5b2b1a1c1e41274ed7578ba197971e209f5a..7d9554cc4976313c90604eacecf4b78227a860f7 100644 (file)
@@ -474,8 +474,10 @@ static int imxdma_xfer_desc(struct imxdma_desc *d)
                        slot = i;
                        break;
                }
-               if (slot < 0)
+               if (slot < 0) {
+                       spin_unlock_irqrestore(&imxdma->lock, flags);
                        return -EBUSY;
+               }
 
                imxdma->slots_2d[slot].xsr = d->x;
                imxdma->slots_2d[slot].ysr = d->y;
index 64385cde044b3feefcc49001edbf0e9ee647bd0d..d451caace806445428c40d3f4d5678ada4a0925d 100644 (file)
@@ -109,7 +109,7 @@ static void sirfsoc_dma_execute(struct sirfsoc_dma_chan *schan)
        sdesc = list_first_entry(&schan->queued, struct sirfsoc_dma_desc,
                node);
        /* Move the first queued descriptor to active list */
-       list_move_tail(&schan->queued, &schan->active);
+       list_move_tail(&sdesc->node, &schan->active);
 
        /* Start the DMA transfer */
        writel_relaxed(sdesc->width, sdma->base + SIRFSOC_DMA_WIDTH_0 +
@@ -428,7 +428,7 @@ static struct dma_async_tx_descriptor *sirfsoc_dma_prep_interleaved(
        unsigned long iflags;
        int ret;
 
-       if ((xt->dir != DMA_MEM_TO_DEV) || (xt->dir != DMA_DEV_TO_MEM)) {
+       if ((xt->dir != DMA_MEM_TO_DEV) && (xt->dir != DMA_DEV_TO_MEM)) {
                ret = -EINVAL;
                goto err_dir;
        }
index 5a297a26211d622b0f0ceedb0389fcbeb4223baf..cc8e7c78a23ca22972bfa570dc88d1fcf449e979 100644 (file)
@@ -170,8 +170,11 @@ static int __amd64_set_scrub_rate(struct pci_dev *ctl, u32 new_bw, u32 min_rate)
         * memory controller and apply to register. Search for the first
         * bandwidth entry that is greater or equal than the setting requested
         * and program that. If at last entry, turn off DRAM scrubbing.
+        *
+        * If no suitable bandwidth is found, turn off DRAM scrubbing entirely
+        * by falling back to the last element in scrubrates[].
         */
-       for (i = 0; i < ARRAY_SIZE(scrubrates); i++) {
+       for (i = 0; i < ARRAY_SIZE(scrubrates) - 1; i++) {
                /*
                 * skip scrub rates which aren't recommended
                 * (see F10 BKDG, F3x58)
@@ -181,12 +184,6 @@ static int __amd64_set_scrub_rate(struct pci_dev *ctl, u32 new_bw, u32 min_rate)
 
                if (scrubrates[i].bandwidth <= new_bw)
                        break;
-
-               /*
-                * if no suitable bandwidth found, turn off DRAM scrubbing
-                * entirely by falling back to the last element in the
-                * scrubrates array.
-                */
        }
 
        scrubval = scrubrates[i].scrubval;
index 8d4804732bacb77be17f07465e48f24ea513ab0c..8c4139647efc06acf50528a8d66f1e09995cc4cc 100644 (file)
@@ -33,7 +33,7 @@
  *             detection. The mods to Rev F required more family
  *             information detection.
  *
- *     Changes/Fixes by Borislav Petkov <borislav.petkov@amd.com>:
+ *     Changes/Fixes by Borislav Petkov <bp@alien8.de>:
  *             - misc fixes and code cleanups
  *
  * This module is based on the following documents
index 6c86f6e545587202d3a9f729457ef38314490f70..351945fa2ecdca3f59a691db38206a0f13795797 100644 (file)
@@ -5,7 +5,7 @@
  *
  * 2007 (c) MontaVista Software, Inc.
  * 2010 (c) Advanced Micro Devices Inc.
- *         Borislav Petkov <borislav.petkov@amd.com>
+ *         Borislav Petkov <bp@alien8.de>
  *
  * This file is licensed under the terms of the GNU General Public
  * License version 2. This program is licensed "as is" without any
index 66b5151c10807083e1e724cb58cc384cdde2f11c..2ae78f20cc28f3850cc26a9156927c7b4e8b085e 100644 (file)
@@ -6,7 +6,7 @@
  * This file may be distributed under the terms of the GNU General Public
  * License version 2.
  *
- * Copyright (c) 2010:  Borislav Petkov <borislav.petkov@amd.com>
+ * Copyright (c) 2010:  Borislav Petkov <bp@alien8.de>
  *                     Advanced Micro Devices Inc.
  */
 
@@ -168,6 +168,6 @@ module_init(edac_init_mce_inject);
 module_exit(edac_exit_mce_inject);
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Borislav Petkov <borislav.petkov@amd.com>");
+MODULE_AUTHOR("Borislav Petkov <bp@alien8.de>");
 MODULE_AUTHOR("AMD Inc.");
 MODULE_DESCRIPTION("MCE injection facility for testing MCE decoding");
index 725eb5aa8d8cb670d0e104d48557fb866947a20a..e87196f6d2d2db43f945e6317b3d14fe09e680f4 100644 (file)
@@ -14,6 +14,7 @@
  *
  */
 
+#include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/device.h>
 #include <linux/platform_device.h>
@@ -161,13 +162,12 @@ static int __devinit adc_jack_probe(struct platform_device *pdev)
        err = request_any_context_irq(data->irq, adc_jack_irq_thread,
                        pdata->irq_flags, pdata->name, data);
 
-       if (err) {
+       if (err < 0) {
                dev_err(&pdev->dev, "error: irq %d\n", data->irq);
-               err = -EINVAL;
                goto err_irq;
        }
 
-       goto out;
+       return 0;
 
 err_irq:
        extcon_dev_unregister(&data->edev);
@@ -196,3 +196,7 @@ static struct platform_driver adc_jack_driver = {
 };
 
 module_platform_driver(adc_jack_driver);
+
+MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
+MODULE_DESCRIPTION("ADC Jack extcon driver");
+MODULE_LICENSE("GPL v2");
index 946a3188b2b78a4014f84e93588e8423c41501c0..d398821097f35f181c7ad554360a127de13496d5 100644 (file)
@@ -41,7 +41,7 @@
  * every single port-type of the following cable names. Please choose cable
  * names that are actually used in your extcon device.
  */
-const char *extcon_cable_name[] = {
+const char extcon_cable_name[][CABLE_NAME_MAX + 1] = {
        [EXTCON_USB]            = "USB",
        [EXTCON_USB_HOST]       = "USB-Host",
        [EXTCON_TA]             = "TA",
@@ -62,8 +62,6 @@ const char *extcon_cable_name[] = {
        [EXTCON_VIDEO_IN]       = "Video-in",
        [EXTCON_VIDEO_OUT]      = "Video-out",
        [EXTCON_MECHANICAL]     = "Mechanical",
-
-       NULL,
 };
 
 static struct class *extcon_class;
@@ -91,17 +89,13 @@ static int check_mutually_exclusive(struct extcon_dev *edev, u32 new_state)
                return 0;
 
        for (i = 0; edev->mutually_exclusive[i]; i++) {
-               int count = 0, j;
+               int weight;
                u32 correspondants = new_state & edev->mutually_exclusive[i];
-               u32 exp = 1;
-
-               for (j = 0; j < 32; j++) {
-                       if (exp & correspondants)
-                               count++;
-                       if (count > 1)
-                               return i + 1;
-                       exp <<= 1;
-               }
+
+               /* calculate the total number of bits set */
+               weight = hweight32(correspondants);
+               if (weight > 1)
+                       return i + 1;
        }
 
        return 0;
@@ -362,7 +356,7 @@ int extcon_get_cable_state(struct extcon_dev *edev, const char *cable_name)
 EXPORT_SYMBOL_GPL(extcon_get_cable_state);
 
 /**
- * extcon_get_cable_state_() - Set the status of a specific cable.
+ * extcon_set_cable_state_() - Set the status of a specific cable.
  * @edev:      the extcon device that has the cable.
  * @index:     cable index that can be retrieved by extcon_find_cable_index().
  * @cable_state:       the new cable status. The default semantics is
@@ -382,7 +376,7 @@ int extcon_set_cable_state_(struct extcon_dev *edev,
 EXPORT_SYMBOL_GPL(extcon_set_cable_state_);
 
 /**
- * extcon_get_cable_state() - Set the status of a specific cable.
+ * extcon_set_cable_state() - Set the status of a specific cable.
  * @edev:      the extcon device that has the cable.
  * @cable_name:        cable name.
  * @cable_state:       the new cable status. The default semantics is
@@ -447,6 +441,8 @@ static int _call_per_cable(struct notifier_block *nb, unsigned long val,
  *                           extcon device.
  * @obj:       an empty extcon_specific_cable_nb object to be returned.
  * @extcon_name:       the name of extcon device.
+ *                     if NULL, extcon_register_interest will register
+ *                     every cable with the target cable_name given.
  * @cable_name:                the target cable name.
  * @nb:                the notifier block to get notified.
  *
@@ -466,22 +462,44 @@ int extcon_register_interest(struct extcon_specific_cable_nb *obj,
                             const char *extcon_name, const char *cable_name,
                             struct notifier_block *nb)
 {
-       if (!obj || !extcon_name || !cable_name || !nb)
+       if (!obj || !cable_name || !nb)
                return -EINVAL;
 
-       obj->edev = extcon_get_extcon_dev(extcon_name);
-       if (!obj->edev)
-               return -ENODEV;
+       if (extcon_name) {
+               obj->edev = extcon_get_extcon_dev(extcon_name);
+               if (!obj->edev)
+                       return -ENODEV;
 
-       obj->cable_index = extcon_find_cable_index(obj->edev, cable_name);
-       if (obj->cable_index < 0)
-               return -ENODEV;
+               obj->cable_index = extcon_find_cable_index(obj->edev, cable_name);
+               if (obj->cable_index < 0)
+                       return -ENODEV;
+
+               obj->user_nb = nb;
 
-       obj->user_nb = nb;
+               obj->internal_nb.notifier_call = _call_per_cable;
 
-       obj->internal_nb.notifier_call = _call_per_cable;
+               return raw_notifier_chain_register(&obj->edev->nh, &obj->internal_nb);
+       } else {
+               struct class_dev_iter iter;
+               struct extcon_dev *extd;
+               struct device *dev;
+
+               if (!extcon_class)
+                       return -ENODEV;
+               class_dev_iter_init(&iter, extcon_class, NULL, NULL);
+               while ((dev = class_dev_iter_next(&iter))) {
+                       extd = (struct extcon_dev *)dev_get_drvdata(dev);
+
+                       if (extcon_find_cable_index(extd, cable_name) < 0)
+                               continue;
+
+                       class_dev_iter_exit(&iter);
+                       return extcon_register_interest(obj, extd->name,
+                                               cable_name, nb);
+               }
 
-       return raw_notifier_chain_register(&obj->edev->nh, &obj->internal_nb);
+               return -ENODEV;
+       }
 }
 
 /**
@@ -551,43 +569,9 @@ static int create_extcon_class(void)
        return 0;
 }
 
-static void extcon_cleanup(struct extcon_dev *edev, bool skip)
-{
-       mutex_lock(&extcon_dev_list_lock);
-       list_del(&edev->entry);
-       mutex_unlock(&extcon_dev_list_lock);
-
-       if (!skip && get_device(edev->dev)) {
-               int index;
-
-               if (edev->mutually_exclusive && edev->max_supported) {
-                       for (index = 0; edev->mutually_exclusive[index];
-                            index++)
-                               kfree(edev->d_attrs_muex[index].attr.name);
-                       kfree(edev->d_attrs_muex);
-                       kfree(edev->attrs_muex);
-               }
-
-               for (index = 0; index < edev->max_supported; index++)
-                       kfree(edev->cables[index].attr_g.name);
-
-               if (edev->max_supported) {
-                       kfree(edev->extcon_dev_type.groups);
-                       kfree(edev->cables);
-               }
-
-               device_unregister(edev->dev);
-               put_device(edev->dev);
-       }
-
-       kfree(edev->dev);
-}
-
 static void extcon_dev_release(struct device *dev)
 {
-       struct extcon_dev *edev = (struct extcon_dev *) dev_get_drvdata(dev);
-
-       extcon_cleanup(edev, true);
+       kfree(dev);
 }
 
 static const char *muex_name = "mutually_exclusive";
@@ -813,7 +797,40 @@ EXPORT_SYMBOL_GPL(extcon_dev_register);
  */
 void extcon_dev_unregister(struct extcon_dev *edev)
 {
-       extcon_cleanup(edev, false);
+       int index;
+
+       mutex_lock(&extcon_dev_list_lock);
+       list_del(&edev->entry);
+       mutex_unlock(&extcon_dev_list_lock);
+
+       if (IS_ERR_OR_NULL(get_device(edev->dev))) {
+               dev_err(edev->dev, "Failed to unregister extcon_dev (%s)\n",
+                               dev_name(edev->dev));
+               return;
+       }
+
+       if (edev->mutually_exclusive && edev->max_supported) {
+               for (index = 0; edev->mutually_exclusive[index];
+                               index++)
+                       kfree(edev->d_attrs_muex[index].attr.name);
+               kfree(edev->d_attrs_muex);
+               kfree(edev->attrs_muex);
+       }
+
+       for (index = 0; index < edev->max_supported; index++)
+               kfree(edev->cables[index].attr_g.name);
+
+       if (edev->max_supported) {
+               kfree(edev->extcon_dev_type.groups);
+               kfree(edev->cables);
+       }
+
+#if defined(CONFIG_ANDROID)
+       if (switch_class)
+               class_compat_remove_link(switch_class, edev->dev, NULL);
+#endif
+       device_unregister(edev->dev);
+       put_device(edev->dev);
 }
 EXPORT_SYMBOL_GPL(extcon_dev_unregister);
 
@@ -825,6 +842,9 @@ module_init(extcon_class_init);
 
 static void __exit extcon_class_exit(void)
 {
+#if defined(CONFIG_ANDROID)
+       class_compat_unregister(switch_class);
+#endif
        class_destroy(extcon_class);
 }
 module_exit(extcon_class_exit);
index 3cc152e690b06087c8374bf35cb72106f9bfde32..71d3ab7b3d8d72c8c477250e25b8ec93ce7842e8 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
-#include <linux/extcon.h>
 #include <linux/workqueue.h>
 #include <linux/gpio.h>
 #include <linux/extcon.h>
index e21387e2da5c25d2c9fdd19dae94108f9e9455da..a17d0d91ada26865d580768b293f2bbd936e4d10 100644 (file)
@@ -239,25 +239,19 @@ const char *max77693_extcon_cable[] = {
 static int max77693_muic_set_debounce_time(struct max77693_muic_info *info,
                enum max77693_muic_adc_debounce_time time)
 {
-       int ret = 0;
-       u8 ctrl3;
+       int ret;
 
        switch (time) {
        case ADC_DEBOUNCE_TIME_5MS:
        case ADC_DEBOUNCE_TIME_10MS:
        case ADC_DEBOUNCE_TIME_25MS:
        case ADC_DEBOUNCE_TIME_38_62MS:
-               ret = max77693_read_reg(info->max77693->regmap_muic,
-                               MAX77693_MUIC_REG_CTRL3, &ctrl3);
-               ctrl3 &= ~CONTROL3_ADCDBSET_MASK;
-               ctrl3 |= (time << CONTROL3_ADCDBSET_SHIFT);
-
-               ret = max77693_write_reg(info->max77693->regmap_muic,
-                               MAX77693_MUIC_REG_CTRL3, ctrl3);
-               if (ret) {
+               ret = max77693_update_reg(info->max77693->regmap_muic,
+                                         MAX77693_MUIC_REG_CTRL3,
+                                         time << CONTROL3_ADCDBSET_SHIFT,
+                                         CONTROL3_ADCDBSET_MASK);
+               if (ret)
                        dev_err(info->dev, "failed to set ADC debounce time\n");
-                       ret = -EINVAL;
-               }
                break;
        default:
                dev_err(info->dev, "invalid ADC debounce time\n");
@@ -657,6 +651,8 @@ out:
 static int __devinit max77693_muic_probe(struct platform_device *pdev)
 {
        struct max77693_dev *max77693 = dev_get_drvdata(pdev->dev.parent);
+       struct max77693_platform_data *pdata = dev_get_platdata(max77693->dev);
+       struct max77693_muic_platform_data *muic_pdata = pdata->muic_data;
        struct max77693_muic_info *info;
        int ret, i;
        u8 id;
@@ -727,6 +723,31 @@ static int __devinit max77693_muic_probe(struct platform_device *pdev)
                goto err_extcon;
        }
 
+       /* Initialize MUIC register by using platform data */
+       for (i = 0 ; i < muic_pdata->num_init_data ; i++) {
+               enum max77693_irq_source irq_src = MAX77693_IRQ_GROUP_NR;
+
+               max77693_write_reg(info->max77693->regmap_muic,
+                               muic_pdata->init_data[i].addr,
+                               muic_pdata->init_data[i].data);
+
+               switch (muic_pdata->init_data[i].addr) {
+               case MAX77693_MUIC_REG_INTMASK1:
+                       irq_src = MUIC_INT1;
+                       break;
+               case MAX77693_MUIC_REG_INTMASK2:
+                       irq_src = MUIC_INT2;
+                       break;
+               case MAX77693_MUIC_REG_INTMASK3:
+                       irq_src = MUIC_INT3;
+                       break;
+               }
+
+               if (irq_src < MAX77693_IRQ_GROUP_NR)
+                       info->max77693->irq_masks_cur[irq_src]
+                               = muic_pdata->init_data[i].data;
+       }
+
        /* Check revision number of MUIC device*/
        ret = max77693_read_reg(info->max77693->regmap_muic,
                        MAX77693_MUIC_REG_ID, &id);
@@ -762,6 +783,7 @@ static int __devexit max77693_muic_remove(struct platform_device *pdev)
                free_irq(muic_irqs[i].virq, info);
        cancel_work_sync(&info->irq_work);
        extcon_dev_unregister(info->edev);
+       kfree(info->edev);
        kfree(info);
 
        return 0;
index ef9090a4271ddc00ee6d735c2c4b48051e5c09f3..77b66b0cc8f54b117280e951daf81b17d6d31c3c 100644 (file)
@@ -271,8 +271,6 @@ out:
 static int max8997_muic_handle_charger_type_detach(
                                struct max8997_muic_info *info)
 {
-       int ret = 0;
-
        switch (info->pre_charger_type) {
        case MAX8997_CHARGER_TYPE_USB:
                extcon_set_cable_state(info->edev, "USB", false);
@@ -290,11 +288,11 @@ static int max8997_muic_handle_charger_type_detach(
                extcon_set_cable_state(info->edev, "Fast-charger", false);
                break;
        default:
-               ret = -EINVAL;
+               return -EINVAL;
                break;
        }
 
-       return ret;
+       return 0;
 }
 
 static int max8997_muic_handle_charger_type(struct max8997_muic_info *info,
index 1162d6b3bf8561d6ed1cfe399643dff6deb4027b..bb1b392f5cdacd1194e9af1772469c834e4192dd 100644 (file)
@@ -1546,6 +1546,8 @@ static int sbp2_scsi_slave_configure(struct scsi_device *sdev)
        struct sbp2_logical_unit *lu = sdev->hostdata;
 
        sdev->use_10_for_rw = 1;
+       sdev->no_report_opcodes = 1;
+       sdev->no_write_same = 1;
 
        if (sbp2_param_exclusive_login)
                sdev->manage_start_stop = 1;
index d055cee36942d5e7aea8535b5f8d77b4ab34fe09..47150f5ded04ea4df13c14434fc3fa553141abaf 100644 (file)
@@ -47,7 +47,7 @@ if GPIOLIB
 
 config OF_GPIO
        def_bool y
-       depends on OF && !SPARC
+       depends on OF
 
 config DEBUG_GPIO
        bool "Debug GPIO calls"
@@ -466,7 +466,7 @@ config GPIO_ADP5588_IRQ
 
 config GPIO_ADNP
        tristate "Avionic Design N-bit GPIO expander"
-       depends on I2C && OF
+       depends on I2C && OF_GPIO
        help
          This option enables support for N GPIOs found on Avionic Design
          I2C GPIO expanders. The register space will be extended by powers
index ed3e55161bdc5bacbd0409a8a728f161872671c9..f05e54258ffb0a7c1b62eb54be11f2f8ed9486d8 100644 (file)
@@ -153,7 +153,7 @@ static int __devinit gen_74x164_probe(struct spi_device *spi)
        }
 
        chip->gpio_chip.ngpio = GEN_74X164_NUMBER_GPIOS * chip->registers;
-       chip->buffer = devm_kzalloc(&spi->dev, chip->gpio_chip.ngpio, GFP_KERNEL);
+       chip->buffer = devm_kzalloc(&spi->dev, chip->registers, GFP_KERNEL);
        if (!chip->buffer) {
                ret = -ENOMEM;
                goto exit_destroy;
index 0f425189de11b3b5b8003a9c9abb330d9debd116..ce1c847600764602f568994f08167b8fc044dd9a 100644 (file)
@@ -77,7 +77,7 @@ struct mcp23s08_driver_data {
 
 /*----------------------------------------------------------------------*/
 
-#ifdef CONFIG_I2C
+#if IS_ENABLED(CONFIG_I2C)
 
 static int mcp23008_read(struct mcp23s08 *mcp, unsigned reg)
 {
@@ -399,7 +399,7 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev,
                break;
 #endif /* CONFIG_SPI_MASTER */
 
-#ifdef CONFIG_I2C
+#if IS_ENABLED(CONFIG_I2C)
        case MCP_TYPE_008:
                mcp->ops = &mcp23008_ops;
                mcp->chip.ngpio = 8;
@@ -473,7 +473,7 @@ fail:
 
 /*----------------------------------------------------------------------*/
 
-#ifdef CONFIG_I2C
+#if IS_ENABLED(CONFIG_I2C)
 
 static int __devinit mcp230xx_probe(struct i2c_client *client,
                                    const struct i2c_device_id *id)
index 7a874129e5d8f3634b68ea45d5d73a2a316f8bae..be65c0451ad556e174b961f3542cc8d7b40e201c 100644 (file)
@@ -92,6 +92,11 @@ static inline void __iomem *mvebu_gpioreg_out(struct mvebu_gpio_chip *mvchip)
        return mvchip->membase + GPIO_OUT_OFF;
 }
 
+static inline void __iomem *mvebu_gpioreg_blink(struct mvebu_gpio_chip *mvchip)
+{
+       return mvchip->membase + GPIO_BLINK_EN_OFF;
+}
+
 static inline void __iomem *mvebu_gpioreg_io_conf(struct mvebu_gpio_chip *mvchip)
 {
        return mvchip->membase + GPIO_IO_CONF_OFF;
@@ -206,6 +211,23 @@ static int mvebu_gpio_get(struct gpio_chip *chip, unsigned pin)
        return (u >> pin) & 1;
 }
 
+static void mvebu_gpio_blink(struct gpio_chip *chip, unsigned pin, int value)
+{
+       struct mvebu_gpio_chip *mvchip =
+               container_of(chip, struct mvebu_gpio_chip, chip);
+       unsigned long flags;
+       u32 u;
+
+       spin_lock_irqsave(&mvchip->lock, flags);
+       u = readl_relaxed(mvebu_gpioreg_blink(mvchip));
+       if (value)
+               u |= 1 << pin;
+       else
+               u &= ~(1 << pin);
+       writel_relaxed(u, mvebu_gpioreg_blink(mvchip));
+       spin_unlock_irqrestore(&mvchip->lock, flags);
+}
+
 static int mvebu_gpio_direction_input(struct gpio_chip *chip, unsigned pin)
 {
        struct mvebu_gpio_chip *mvchip =
@@ -244,6 +266,9 @@ static int mvebu_gpio_direction_output(struct gpio_chip *chip, unsigned pin,
        if (ret)
                return ret;
 
+       mvebu_gpio_blink(chip, pin, 0);
+       mvebu_gpio_set(chip, pin, value);
+
        spin_lock_irqsave(&mvchip->lock, flags);
        u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip));
        u &= ~(1 << pin);
@@ -644,7 +669,7 @@ static int __devinit mvebu_gpio_probe(struct platform_device *pdev)
        ct->handler = handle_edge_irq;
        ct->chip.name = mvchip->chip.label;
 
-       irq_setup_generic_chip(gc, IRQ_MSK(ngpios), IRQ_GC_INIT_MASK_CACHE,
+       irq_setup_generic_chip(gc, IRQ_MSK(ngpios), 0,
                               IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE);
 
        /* Setup irq domain on top of the generic chip. */
index 94cbc842fbc3a1363de61b8b7d08f2e4b56daeaf..d335af1d4d858da39b2825fd9144c01e76f877e5 100644 (file)
@@ -251,6 +251,40 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio,
        }
 }
 
+/**
+ * _clear_gpio_debounce - clear debounce settings for a gpio
+ * @bank: the gpio bank we're acting upon
+ * @gpio: the gpio number on this @gpio
+ *
+ * If a gpio is using debounce, then clear the debounce enable bit and if
+ * this is the only gpio in this bank using debounce, then clear the debounce
+ * time too. The debounce clock will also be disabled when calling this function
+ * if this is the only gpio in the bank using debounce.
+ */
+static void _clear_gpio_debounce(struct gpio_bank *bank, unsigned gpio)
+{
+       u32 gpio_bit = GPIO_BIT(bank, gpio);
+
+       if (!bank->dbck_flag)
+               return;
+
+       if (!(bank->dbck_enable_mask & gpio_bit))
+               return;
+
+       bank->dbck_enable_mask &= ~gpio_bit;
+       bank->context.debounce_en &= ~gpio_bit;
+       __raw_writel(bank->context.debounce_en,
+                    bank->base + bank->regs->debounce_en);
+
+       if (!bank->dbck_enable_mask) {
+               bank->context.debounce = 0;
+               __raw_writel(bank->context.debounce, bank->base +
+                            bank->regs->debounce);
+               clk_disable(bank->dbck);
+               bank->dbck_enabled = false;
+       }
+}
+
 static inline void set_gpio_trigger(struct gpio_bank *bank, int gpio,
                                                unsigned trigger)
 {
@@ -539,6 +573,7 @@ static void _reset_gpio(struct gpio_bank *bank, int gpio)
        _set_gpio_irqenable(bank, gpio, 0);
        _clear_gpio_irqstatus(bank, gpio);
        _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), IRQ_TYPE_NONE);
+       _clear_gpio_debounce(bank, gpio);
 }
 
 /* Use disable_irq_wake() and enable_irq_wake() functions from drivers */
index 031c6adf5b651542420ee819ad0810d537707222..1a3e2b9b4772f7e710c16dee60a48049a3ff5c6d 100644 (file)
@@ -116,7 +116,7 @@ static void timbgpio_irq_disable(struct irq_data *d)
        unsigned long flags;
 
        spin_lock_irqsave(&tgpio->lock, flags);
-       tgpio->last_ier &= ~(1 << offset);
+       tgpio->last_ier &= ~(1UL << offset);
        iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER);
        spin_unlock_irqrestore(&tgpio->lock, flags);
 }
@@ -128,7 +128,7 @@ static void timbgpio_irq_enable(struct irq_data *d)
        unsigned long flags;
 
        spin_lock_irqsave(&tgpio->lock, flags);
-       tgpio->last_ier |= 1 << offset;
+       tgpio->last_ier |= 1UL << offset;
        iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER);
        spin_unlock_irqrestore(&tgpio->lock, flags);
 }
index 5d6c71edc73911c7765a7530e65352fda2478845..1c8d9e3380e17276e17e8f009659954e58d05bd1 100644 (file)
@@ -623,9 +623,11 @@ static ssize_t export_store(struct class *class,
         */
 
        status = gpio_request(gpio, "sysfs");
-       if (status < 0)
+       if (status < 0) {
+               if (status == -EPROBE_DEFER)
+                       status = -ENODEV;
                goto done;
-
+       }
        status = gpio_export(gpio, true);
        if (status < 0)
                gpio_free(gpio);
@@ -1191,8 +1193,10 @@ int gpio_request(unsigned gpio, const char *label)
 
        spin_lock_irqsave(&gpio_lock, flags);
 
-       if (!gpio_is_valid(gpio))
+       if (!gpio_is_valid(gpio)) {
+               status = -EINVAL;
                goto done;
+       }
        desc = &gpio_desc[gpio];
        chip = desc->chip;
        if (chip == NULL)
index 09e11a5d921a4487b273bcdc2c479e4a26f90301..fd9d0af4d5369bb7ebac13662a3d612188c87921 100644 (file)
@@ -206,7 +206,7 @@ static int drm_fbdev_cma_create(struct drm_fb_helper *helper,
        size_t size;
        int ret;
 
-       DRM_DEBUG_KMS("surface width(%d), height(%d) and bpp(%d\n",
+       DRM_DEBUG_KMS("surface width(%d), height(%d) and bpp(%d)\n",
                        sizes->surface_width, sizes->surface_height,
                        sizes->surface_bpp);
 
@@ -220,7 +220,7 @@ static int drm_fbdev_cma_create(struct drm_fb_helper *helper,
 
        size = mode_cmd.pitches[0] * mode_cmd.height;
        obj = drm_gem_cma_create(dev, size);
-       if (!obj)
+       if (IS_ERR(obj))
                return -ENOMEM;
 
        fbi = framebuffer_alloc(0, dev->dev);
index 7ef1b673e1be9ec2f82006ca3d8ea2519e13b231..133b4132983e35e366884301a443ff26f45a2a05 100644 (file)
@@ -121,6 +121,8 @@ int drm_open(struct inode *inode, struct file *filp)
        int minor_id = iminor(inode);
        struct drm_minor *minor;
        int retcode = 0;
+       int need_setup = 0;
+       struct address_space *old_mapping;
 
        minor = idr_find(&drm_minors_idr, minor_id);
        if (!minor)
@@ -132,23 +134,37 @@ int drm_open(struct inode *inode, struct file *filp)
        if (drm_device_is_unplugged(dev))
                return -ENODEV;
 
+       if (!dev->open_count++)
+               need_setup = 1;
+       mutex_lock(&dev->struct_mutex);
+       old_mapping = dev->dev_mapping;
+       if (old_mapping == NULL)
+               dev->dev_mapping = &inode->i_data;
+       /* ihold ensures nobody can remove inode with our i_data */
+       ihold(container_of(dev->dev_mapping, struct inode, i_data));
+       inode->i_mapping = dev->dev_mapping;
+       filp->f_mapping = dev->dev_mapping;
+       mutex_unlock(&dev->struct_mutex);
+
        retcode = drm_open_helper(inode, filp, dev);
-       if (!retcode) {
-               atomic_inc(&dev->counts[_DRM_STAT_OPENS]);
-               if (!dev->open_count++)
-                       retcode = drm_setup(dev);
-       }
-       if (!retcode) {
-               mutex_lock(&dev->struct_mutex);
-               if (dev->dev_mapping == NULL)
-                       dev->dev_mapping = &inode->i_data;
-               /* ihold ensures nobody can remove inode with our i_data */
-               ihold(container_of(dev->dev_mapping, struct inode, i_data));
-               inode->i_mapping = dev->dev_mapping;
-               filp->f_mapping = dev->dev_mapping;
-               mutex_unlock(&dev->struct_mutex);
+       if (retcode)
+               goto err_undo;
+       atomic_inc(&dev->counts[_DRM_STAT_OPENS]);
+       if (need_setup) {
+               retcode = drm_setup(dev);
+               if (retcode)
+                       goto err_undo;
        }
+       return 0;
 
+err_undo:
+       mutex_lock(&dev->struct_mutex);
+       filp->f_mapping = old_mapping;
+       inode->i_mapping = old_mapping;
+       iput(container_of(dev->dev_mapping, struct inode, i_data));
+       dev->dev_mapping = old_mapping;
+       mutex_unlock(&dev->struct_mutex);
+       dev->open_count--;
        return retcode;
 }
 EXPORT_SYMBOL(drm_open);
index 441ebc1bdbef5455c6a8cc7aa34103926dd963fa..d4b20ceda3fbd8d183dc7e628683732590200f51 100644 (file)
@@ -205,8 +205,6 @@ static int drm_gem_one_name_info(int id, void *ptr, void *data)
        struct drm_gem_object *obj = ptr;
        struct seq_file *m = data;
 
-       seq_printf(m, "name %d size %zd\n", obj->name, obj->size);
-
        seq_printf(m, "%6d %8zd %7d %8d\n",
                   obj->name, obj->size,
                   atomic_read(&obj->handle_count),
index aaeb6f8d69ce3502c569dda32d2d600117fb54c5..b8a282ea87515546695bc2965bce2b9f3e4f2f2d 100644 (file)
@@ -64,7 +64,6 @@ int drm_get_platform_dev(struct platform_device *platdev,
        }
 
        if (drm_core_check_feature(dev, DRIVER_MODESET)) {
-               dev_set_drvdata(&platdev->dev, dev);
                ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL);
                if (ret)
                        goto err_g1;
index 59a26e577b57f423077d5a2c86d75364f14b6838..fc345d4ebb03acea266bfb100b4661cebf970f69 100644 (file)
@@ -1,6 +1,6 @@
 config DRM_EXYNOS
        tristate "DRM Support for Samsung SoC EXYNOS Series"
-       depends on DRM && PLAT_SAMSUNG
+       depends on DRM && (PLAT_SAMSUNG || ARCH_MULTIPLATFORM)
        select DRM_KMS_HELPER
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
index 18c271862ca8468a8ce0d3d4b24d8a595d29ad44..0f68a28726739dd6b795ad066edb645799cfc6d2 100644 (file)
@@ -374,6 +374,7 @@ struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
        exynos_connector->encoder_id = encoder->base.id;
        exynos_connector->manager = manager;
        exynos_connector->dpms = DRM_MODE_DPMS_OFF;
+       connector->dpms = DRM_MODE_DPMS_OFF;
        connector->encoder = encoder;
 
        err = drm_mode_connector_attach_encoder(connector, encoder);
index e51503fbaf2bcbf19edbdf423638a725b5703a6e..241ad1eeec64d2097a4416bd76026723d384a215 100644 (file)
  * @manager: specific encoder has its own manager to control a hardware
  *     appropriately and we can access a hardware drawing on this manager.
  * @dpms: store the encoder dpms value.
+ * @updated: indicate whether overlay data updating is needed or not.
  */
 struct exynos_drm_encoder {
        struct drm_crtc                 *old_crtc;
        struct drm_encoder              drm_encoder;
        struct exynos_drm_manager       *manager;
-       int dpms;
+       int                             dpms;
+       bool                            updated;
 };
 
 static void exynos_drm_connector_power(struct drm_encoder *encoder, int mode)
@@ -85,7 +87,9 @@ static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
        switch (mode) {
        case DRM_MODE_DPMS_ON:
                if (manager_ops && manager_ops->apply)
-                       manager_ops->apply(manager->dev);
+                       if (!exynos_encoder->updated)
+                               manager_ops->apply(manager->dev);
+
                exynos_drm_connector_power(encoder, mode);
                exynos_encoder->dpms = mode;
                break;
@@ -94,6 +98,7 @@ static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
        case DRM_MODE_DPMS_OFF:
                exynos_drm_connector_power(encoder, mode);
                exynos_encoder->dpms = mode;
+               exynos_encoder->updated = false;
                break;
        default:
                DRM_ERROR("unspecified mode %d\n", mode);
@@ -205,13 +210,22 @@ static void exynos_drm_encoder_prepare(struct drm_encoder *encoder)
 
 static void exynos_drm_encoder_commit(struct drm_encoder *encoder)
 {
-       struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
+       struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
+       struct exynos_drm_manager *manager = exynos_encoder->manager;
        struct exynos_drm_manager_ops *manager_ops = manager->ops;
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
        if (manager_ops && manager_ops->commit)
                manager_ops->commit(manager->dev);
+
+       /*
+        * this will avoid one issue that overlay data is updated to
+        * real hardware two times.
+        * And this variable will be used to check if the data was
+        * already updated or not by exynos_drm_encoder_dpms function.
+        */
+       exynos_encoder->updated = true;
 }
 
 static void exynos_drm_encoder_disable(struct drm_encoder *encoder)
@@ -400,19 +414,6 @@ void exynos_drm_encoder_crtc_dpms(struct drm_encoder *encoder, void *data)
        if (manager_ops && manager_ops->dpms)
                manager_ops->dpms(manager->dev, mode);
 
-       /*
-        * set current mode to new one so that data aren't updated into
-        * registers by drm_helper_connector_dpms two times.
-        *
-        * in case that drm_crtc_helper_set_mode() is called,
-        * overlay_ops->commit() and manager_ops->commit() callbacks
-        * can be called two times, first at drm_crtc_helper_set_mode()
-        * and second at drm_helper_connector_dpms().
-        * so with this setting, when drm_helper_connector_dpms() is called
-        * encoder->funcs->dpms() will be ignored.
-        */
-       exynos_encoder->dpms = mode;
-
        /*
         * if this condition is ok then it means that the crtc is already
         * detached from encoder and last function for detaching is properly
index 614b2e9ac462c9c402226324d9b12d38b996af14..e7fbb823fd8e5fe2fe97845a1b42a3d84efd50be 100644 (file)
@@ -1142,7 +1142,7 @@ static int __devinit mixer_probe(struct platform_device *pdev)
                const struct of_device_id *match;
                match = of_match_node(of_match_ptr(mixer_match_types),
                                                          pdev->dev.of_node);
-               drv = match->data;
+               drv = (struct mixer_drv_data *)match->data;
        } else {
                drv = (struct mixer_drv_data *)
                        platform_get_device_id(pdev)->driver_data;
index c9bfd83dde64eb6d83cf181fb6c27b3cfcf0a038..61ae104dca8c0f5b9938f092b93f7eca70a06525 100644 (file)
@@ -1505,7 +1505,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
                goto put_gmch;
        }
 
-       i915_kick_out_firmware_fb(dev_priv);
+       if (drm_core_check_feature(dev, DRIVER_MODESET))
+               i915_kick_out_firmware_fb(dev_priv);
 
        pci_set_master(dev->pdev);
 
index aac4e5e1a5b9b3533f36f801be7c553c2e60c8a1..6770ee6084b478475c3dde3a9bec72fff1e11a53 100644 (file)
@@ -118,6 +118,13 @@ module_param_named(i915_enable_ppgtt, i915_enable_ppgtt, int, 0600);
 MODULE_PARM_DESC(i915_enable_ppgtt,
                "Enable PPGTT (default: true)");
 
+unsigned int i915_preliminary_hw_support __read_mostly = 0;
+module_param_named(preliminary_hw_support, i915_preliminary_hw_support, int, 0600);
+MODULE_PARM_DESC(preliminary_hw_support,
+               "Enable preliminary hardware support. "
+               "Enable Haswell and ValleyView Support. "
+               "(default: false)");
+
 static struct drm_driver driver;
 extern int intel_agp_enabled;
 
@@ -826,6 +833,12 @@ i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        struct intel_device_info *intel_info =
                (struct intel_device_info *) ent->driver_data;
 
+       if (intel_info->is_haswell || intel_info->is_valleyview)
+               if(!i915_preliminary_hw_support) {
+                       DRM_ERROR("Preliminary hardware support disabled\n");
+                       return -ENODEV;
+               }
+
        /* Only bind to function 0 of the device. Early generations
         * used function 1 as a placeholder for multi-head. This causes
         * us confusion instead, especially on the systems where both
index b84f7861e4388cb3ccd8baa86ec3d994e4e52ceb..f511fa2f41687718494f2f1d9e2afb0c24f1fb70 100644 (file)
@@ -1217,6 +1217,7 @@ extern int i915_enable_rc6 __read_mostly;
 extern int i915_enable_fbc __read_mostly;
 extern bool i915_enable_hangcheck __read_mostly;
 extern int i915_enable_ppgtt __read_mostly;
+extern unsigned int i915_preliminary_hw_support __read_mostly;
 
 extern int i915_suspend(struct drm_device *dev, pm_message_t state);
 extern int i915_resume(struct drm_device *dev);
index d33d02d13c9678a7dd64b1fb4c9e9c5f9682d223..107f09befe929540e9ad801ff2bbdfe97a6b651d 100644 (file)
@@ -1407,8 +1407,10 @@ out:
                return VM_FAULT_NOPAGE;
        case -ENOMEM:
                return VM_FAULT_OOM;
+       case -ENOSPC:
+               return VM_FAULT_SIGBUS;
        default:
-               WARN_ON_ONCE(ret);
+               WARN_ONCE(ret, "unhandled error in i915_gem_fault: %i\n", ret);
                return VM_FAULT_SIGBUS;
        }
 }
@@ -1822,10 +1824,11 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
                sg_set_page(sg, page, PAGE_SIZE, 0);
        }
 
+       obj->pages = st;
+
        if (i915_gem_object_needs_bit17_swizzle(obj))
                i915_gem_object_do_bit_17_swizzle(obj);
 
-       obj->pages = st;
        return 0;
 
 err_pages:
index 893f30164b7ec70a5cd2308db6db1e3e55222d6f..6345878ae1e73e260a9a3fdfcaaf760e6ec6e2c1 100644 (file)
@@ -143,7 +143,7 @@ static void intel_crt_dpms(struct drm_connector *connector, int mode)
        int old_dpms;
 
        /* PCH platforms and VLV only support on/off. */
-       if (INTEL_INFO(dev)->gen < 5 && mode != DRM_MODE_DPMS_ON)
+       if (INTEL_INFO(dev)->gen >= 5 && mode != DRM_MODE_DPMS_ON)
                mode = DRM_MODE_DPMS_OFF;
 
        if (mode == connector->dpms)
@@ -219,20 +219,7 @@ static void intel_crt_mode_set(struct drm_encoder *encoder,
                intel_encoder_to_crt(to_intel_encoder(encoder));
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct drm_i915_private *dev_priv = dev->dev_private;
-       int dpll_md_reg;
-       u32 adpa, dpll_md;
-
-       dpll_md_reg = DPLL_MD(intel_crtc->pipe);
-
-       /*
-        * Disable separate mode multiplier used when cloning SDVO to CRT
-        * XXX this needs to be adjusted when we really are cloning
-        */
-       if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) {
-               dpll_md = I915_READ(dpll_md_reg);
-               I915_WRITE(dpll_md_reg,
-                          dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK);
-       }
+       u32 adpa;
 
        adpa = ADPA_HOTPLUG_BITS;
        if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
@@ -742,7 +729,7 @@ void intel_crt_init(struct drm_device *dev)
 
        crt->base.type = INTEL_OUTPUT_ANALOG;
        crt->base.cloneable = true;
-       if (IS_HASWELL(dev))
+       if (IS_HASWELL(dev) || IS_I830(dev))
                crt->base.crtc_mask = (1 << 0);
        else
                crt->base.crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
index 682bd3729baf62369fc66d23434f058a643ffc78..4154bcd7a0708b957d4b176607662933ac49fc0d 100644 (file)
@@ -3841,6 +3841,17 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,
                        }
                }
 
+               if (intel_encoder->type == INTEL_OUTPUT_EDP) {
+                       /* Use VBT settings if we have an eDP panel */
+                       unsigned int edp_bpc = dev_priv->edp.bpp / 3;
+
+                       if (edp_bpc < display_bpc) {
+                               DRM_DEBUG_KMS("clamping display bpc (was %d) to eDP (%d)\n", display_bpc, edp_bpc);
+                               display_bpc = edp_bpc;
+                       }
+                       continue;
+               }
+
                /*
                 * HDMI is either 12 or 8, so if the display lets 10bpc sneak
                 * through, clamp it down.  (Note: >12bpc will be caught below.)
@@ -7892,6 +7903,34 @@ struct intel_quirk {
        void (*hook)(struct drm_device *dev);
 };
 
+/* For systems that don't have a meaningful PCI subdevice/subvendor ID */
+struct intel_dmi_quirk {
+       void (*hook)(struct drm_device *dev);
+       const struct dmi_system_id (*dmi_id_list)[];
+};
+
+static int intel_dmi_reverse_brightness(const struct dmi_system_id *id)
+{
+       DRM_INFO("Backlight polarity reversed on %s\n", id->ident);
+       return 1;
+}
+
+static const struct intel_dmi_quirk intel_dmi_quirks[] = {
+       {
+               .dmi_id_list = &(const struct dmi_system_id[]) {
+                       {
+                               .callback = intel_dmi_reverse_brightness,
+                               .ident = "NCR Corporation",
+                               .matches = {DMI_MATCH(DMI_SYS_VENDOR, "NCR Corporation"),
+                                           DMI_MATCH(DMI_PRODUCT_NAME, ""),
+                               },
+                       },
+                       { }  /* terminating entry */
+               },
+               .hook = quirk_invert_brightness,
+       },
+};
+
 static struct intel_quirk intel_quirks[] = {
        /* HP Mini needs pipe A force quirk (LP: #322104) */
        { 0x27ae, 0x103c, 0x361a, quirk_pipea_force },
@@ -7931,6 +7970,10 @@ static void intel_init_quirks(struct drm_device *dev)
                     q->subsystem_device == PCI_ANY_ID))
                        q->hook(dev);
        }
+       for (i = 0; i < ARRAY_SIZE(intel_dmi_quirks); i++) {
+               if (dmi_check_system(*intel_dmi_quirks[i].dmi_id_list) != 0)
+                       intel_dmi_quirks[i].hook(dev);
+       }
 }
 
 /* Disable the VGA plane that we never use */
index 1b727a5c9ee5680364343be93e15203df42e2369..368ed8ef1600233b6df90f32a591b46ea8fbdf88 100644 (file)
@@ -1797,7 +1797,8 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
                        if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0)
                                break;
                if (i == intel_dp->lane_count && voltage_tries == 5) {
-                       if (++loop_tries == 5) {
+                       ++loop_tries;
+                       if (loop_tries == 5) {
                                DRM_DEBUG_KMS("too many full retries, give up\n");
                                break;
                        }
@@ -1807,11 +1808,15 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
                }
 
                /* Check to see if we've tried the same voltage 5 times */
-               if ((intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) != voltage) {
-                       voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
-                       voltage_tries = 0;
-               } else
+               if ((intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) {
                        ++voltage_tries;
+                       if (voltage_tries == 5) {
+                               DRM_DEBUG_KMS("too many voltage retries, give up\n");
+                               break;
+                       }
+               } else
+                       voltage_tries = 0;
+               voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
 
                /* Compute new intel_dp->train_set as requested by target */
                intel_get_adjust_train(intel_dp, link_status);
index e3166df55daad03f4f5c144a5c0558aaa017fec6..edba93b3474b9540a5608f6acbd9eb75f7e53a33 100644 (file)
@@ -777,6 +777,14 @@ static const struct dmi_system_id intel_no_lvds[] = {
                        DMI_MATCH(DMI_BOARD_NAME, "D525TUD"),
                },
        },
+       {
+               .callback = intel_no_lvds_dmi_callback,
+               .ident = "Supermicro X7SPA-H",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Supermicro"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "X7SPA-H"),
+               },
+       },
 
        { }     /* terminating entry */
 };
index 495625914e4a084f01f476d93524bed83db7ac42..d7bc817f51a024b803986e76fa492146632da66d 100644 (file)
@@ -341,9 +341,17 @@ static int intel_overlay_off(struct intel_overlay *overlay)
        intel_ring_emit(ring, flip_addr);
        intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
        /* turn overlay off */
-       intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
-       intel_ring_emit(ring, flip_addr);
-       intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
+       if (IS_I830(dev)) {
+               /* Workaround: Don't disable the overlay fully, since otherwise
+                * it dies on the next OVERLAY_ON cmd. */
+               intel_ring_emit(ring, MI_NOOP);
+               intel_ring_emit(ring, MI_NOOP);
+               intel_ring_emit(ring, MI_NOOP);
+       } else {
+               intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
+               intel_ring_emit(ring, flip_addr);
+               intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
+       }
        intel_ring_advance(ring);
 
        return intel_overlay_do_wait_request(overlay, intel_overlay_off_tail);
index e019b236986128bae46c61bf49180f7ec2502a0d..e2aacd329545a1ff05a68dd4218f571c5208a2aa 100644 (file)
@@ -435,7 +435,7 @@ int intel_panel_setup_backlight(struct drm_device *dev)
        props.type = BACKLIGHT_RAW;
        props.max_brightness = _intel_panel_get_max_backlight(dev);
        if (props.max_brightness == 0) {
-               DRM_ERROR("Failed to get maximum backlight value\n");
+               DRM_DEBUG_DRIVER("Failed to get maximum backlight value\n");
                return -ENODEV;
        }
        dev_priv->backlight =
index 0007a4d9bf6e5248effc509fd25f442b6d4e3164..c600fb06e25e6a4798cd7f7f5841593025d3f484 100644 (file)
@@ -139,6 +139,11 @@ struct intel_sdvo {
 
        /* DDC bus used by this SDVO encoder */
        uint8_t ddc_bus;
+
+       /*
+        * the sdvo flag gets lost in round trip: dtd->adjusted_mode->dtd
+        */
+       uint8_t dtd_sdvo_flags;
 };
 
 struct intel_sdvo_connector {
@@ -889,6 +894,45 @@ static void intel_sdvo_dump_hdmi_buf(struct intel_sdvo *intel_sdvo)
 }
 #endif
 
+static bool intel_sdvo_write_infoframe(struct intel_sdvo *intel_sdvo,
+                                      unsigned if_index, uint8_t tx_rate,
+                                      uint8_t *data, unsigned length)
+{
+       uint8_t set_buf_index[2] = { if_index, 0 };
+       uint8_t hbuf_size, tmp[8];
+       int i;
+
+       if (!intel_sdvo_set_value(intel_sdvo,
+                                 SDVO_CMD_SET_HBUF_INDEX,
+                                 set_buf_index, 2))
+               return false;
+
+       if (!intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_HBUF_INFO,
+                                 &hbuf_size, 1))
+               return false;
+
+       /* Buffer size is 0 based, hooray! */
+       hbuf_size++;
+
+       DRM_DEBUG_KMS("writing sdvo hbuf: %i, hbuf_size %i, hbuf_size: %i\n",
+                     if_index, length, hbuf_size);
+
+       for (i = 0; i < hbuf_size; i += 8) {
+               memset(tmp, 0, 8);
+               if (i < length)
+                       memcpy(tmp, data + i, min_t(unsigned, 8, length - i));
+
+               if (!intel_sdvo_set_value(intel_sdvo,
+                                         SDVO_CMD_SET_HBUF_DATA,
+                                         tmp, 8))
+                       return false;
+       }
+
+       return intel_sdvo_set_value(intel_sdvo,
+                                   SDVO_CMD_SET_HBUF_TXRATE,
+                                   &tx_rate, 1);
+}
+
 static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo)
 {
        struct dip_infoframe avi_if = {
@@ -896,11 +940,7 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo)
                .ver = DIP_VERSION_AVI,
                .len = DIP_LEN_AVI,
        };
-       uint8_t tx_rate = SDVO_HBUF_TX_VSYNC;
-       uint8_t set_buf_index[2] = { 1, 0 };
        uint8_t sdvo_data[4 + sizeof(avi_if.body.avi)];
-       uint64_t *data = (uint64_t *)sdvo_data;
-       unsigned i;
 
        intel_dip_infoframe_csum(&avi_if);
 
@@ -910,22 +950,9 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo)
        sdvo_data[3] = avi_if.checksum;
        memcpy(&sdvo_data[4], &avi_if.body, sizeof(avi_if.body.avi));
 
-       if (!intel_sdvo_set_value(intel_sdvo,
-                                 SDVO_CMD_SET_HBUF_INDEX,
-                                 set_buf_index, 2))
-               return false;
-
-       for (i = 0; i < sizeof(sdvo_data); i += 8) {
-               if (!intel_sdvo_set_value(intel_sdvo,
-                                         SDVO_CMD_SET_HBUF_DATA,
-                                         data, 8))
-                       return false;
-               data++;
-       }
-
-       return intel_sdvo_set_value(intel_sdvo,
-                                   SDVO_CMD_SET_HBUF_TXRATE,
-                                   &tx_rate, 1);
+       return intel_sdvo_write_infoframe(intel_sdvo, SDVO_HBUF_INDEX_AVI_IF,
+                                         SDVO_HBUF_TX_VSYNC,
+                                         sdvo_data, sizeof(sdvo_data));
 }
 
 static bool intel_sdvo_set_tv_format(struct intel_sdvo *intel_sdvo)
@@ -984,6 +1011,7 @@ intel_sdvo_get_preferred_input_mode(struct intel_sdvo *intel_sdvo,
                return false;
 
        intel_sdvo_get_mode_from_dtd(adjusted_mode, &input_dtd);
+       intel_sdvo->dtd_sdvo_flags = input_dtd.part2.sdvo_flags;
 
        return true;
 }
@@ -1092,6 +1120,8 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
         * adjusted_mode.
         */
        intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode);
+       if (intel_sdvo->is_tv || intel_sdvo->is_lvds)
+               input_dtd.part2.sdvo_flags = intel_sdvo->dtd_sdvo_flags;
        if (!intel_sdvo_set_input_timing(intel_sdvo, &input_dtd))
                DRM_INFO("Setting input timings on %s failed\n",
                         SDVO_NAME(intel_sdvo));
@@ -2277,10 +2307,8 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device)
                intel_sdvo_connector->output_flag = SDVO_OUTPUT_LVDS1;
        }
 
-       /* SDVO LVDS is cloneable because the SDVO encoder does the upscaling,
-        * as opposed to native LVDS, where we upscale with the panel-fitter
-        * (and hence only the native LVDS resolution could be cloned). */
-       intel_sdvo->base.cloneable = true;
+       /* SDVO LVDS is not cloneable because the input mode gets adjusted by the encoder */
+       intel_sdvo->base.cloneable = false;
 
        intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo);
        if (!intel_sdvo_create_enhance_property(intel_sdvo, intel_sdvo_connector))
@@ -2354,6 +2382,18 @@ intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo, uint16_t flags)
        return true;
 }
 
+static void intel_sdvo_output_cleanup(struct intel_sdvo *intel_sdvo)
+{
+       struct drm_device *dev = intel_sdvo->base.base.dev;
+       struct drm_connector *connector, *tmp;
+
+       list_for_each_entry_safe(connector, tmp,
+                                &dev->mode_config.connector_list, head) {
+               if (intel_attached_encoder(connector) == &intel_sdvo->base)
+                       intel_sdvo_destroy(connector);
+       }
+}
+
 static bool intel_sdvo_tv_create_property(struct intel_sdvo *intel_sdvo,
                                          struct intel_sdvo_connector *intel_sdvo_connector,
                                          int type)
@@ -2677,7 +2717,8 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)
                                    intel_sdvo->caps.output_flags) != true) {
                DRM_DEBUG_KMS("SDVO output failed to setup on %s\n",
                              SDVO_NAME(intel_sdvo));
-               goto err;
+               /* Output_setup can leave behind connectors! */
+               goto err_output;
        }
 
        /* Only enable the hotplug irq if we need it, to work around noisy
@@ -2690,12 +2731,12 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)
 
        /* Set the input timing to the screen. Assume always input 0. */
        if (!intel_sdvo_set_target_input(intel_sdvo))
-               goto err;
+               goto err_output;
 
        if (!intel_sdvo_get_input_pixel_clock_range(intel_sdvo,
                                                    &intel_sdvo->pixel_clock_min,
                                                    &intel_sdvo->pixel_clock_max))
-               goto err;
+               goto err_output;
 
        DRM_DEBUG_KMS("%s device VID/DID: %02X:%02X.%02X, "
                        "clock range %dMHz - %dMHz, "
@@ -2715,6 +2756,9 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)
                        (SDVO_OUTPUT_TMDS1 | SDVO_OUTPUT_RGB1) ? 'Y' : 'N');
        return true;
 
+err_output:
+       intel_sdvo_output_cleanup(intel_sdvo);
+
 err:
        drm_encoder_cleanup(&intel_encoder->base);
        i2c_del_adapter(&intel_sdvo->ddc);
index 9d030142ee43476c89cf2769f0d8c75cf1697daa..770bdd6ecd9fb96b46365bbadd97ba3011c0ef96 100644 (file)
@@ -708,6 +708,8 @@ struct intel_sdvo_enhancements_arg {
 #define SDVO_CMD_SET_AUDIO_STAT                0x91
 #define SDVO_CMD_GET_AUDIO_STAT                0x92
 #define SDVO_CMD_SET_HBUF_INDEX                0x93
+  #define SDVO_HBUF_INDEX_ELD          0
+  #define SDVO_HBUF_INDEX_AVI_IF       1
 #define SDVO_CMD_GET_HBUF_INDEX                0x94
 #define SDVO_CMD_GET_HBUF_INFO         0x95
 #define SDVO_CMD_SET_HBUF_AV_SPLIT     0x96
index 1f34549aff18748758d4d72feed0eba5800734ab..70586fde69cf48018fd9786ccccacd4eef0900d4 100644 (file)
@@ -39,6 +39,11 @@ nouveau_gpuobj_destroy(struct nouveau_gpuobj *gpuobj)
                        nv_wo32(gpuobj, i, 0x00000000);
        }
 
+       if (gpuobj->node) {
+               nouveau_mm_free(&nv_gpuobj(gpuobj->parent)->heap,
+                               &gpuobj->node);
+       }
+
        if (gpuobj->heap.block_size)
                nouveau_mm_fini(&gpuobj->heap);
 
index bfddf87926dd8857a73df69cb26757836bd02f1f..a6d3cd6490f7fa97f171dff724f73430364af89f 100644 (file)
@@ -218,13 +218,16 @@ nouveau_mm_init(struct nouveau_mm *mm, u32 offset, u32 length, u32 block)
        node = kzalloc(sizeof(*node), GFP_KERNEL);
        if (!node)
                return -ENOMEM;
-       node->offset = roundup(offset, mm->block_size);
-       node->length = rounddown(offset + length, mm->block_size) - node->offset;
+
+       if (length) {
+               node->offset  = roundup(offset, mm->block_size);
+               node->length  = rounddown(offset + length, mm->block_size);
+               node->length -= node->offset;
+       }
 
        list_add_tail(&node->nl_entry, &mm->nodes);
        list_add_tail(&node->fl_entry, &mm->free);
        mm->heap_nodes++;
-       mm->heap_size += length;
        return 0;
 }
 
@@ -236,7 +239,7 @@ nouveau_mm_fini(struct nouveau_mm *mm)
        int nodes = 0;
 
        list_for_each_entry(node, &mm->nodes, nl_entry) {
-               if (nodes++ == mm->heap_nodes)
+               if (WARN_ON(nodes++ == mm->heap_nodes))
                        return -EBUSY;
        }
 
index 16a9afb1060b72372ce4cd879870ec362dc9c0e8..15b182c84ce8b74b55f0cb1073c452a410329f6e 100644 (file)
@@ -22,6 +22,8 @@
  * Authors: Ben Skeggs
  */
 
+#include <subdev/bar.h>
+
 #include <engine/software.h>
 #include <engine/disp.h>
 
@@ -37,6 +39,7 @@ nv50_disp_sclass[] = {
 static void
 nv50_disp_intr_vblank(struct nv50_disp_priv *priv, int crtc)
 {
+       struct nouveau_bar *bar = nouveau_bar(priv);
        struct nouveau_disp *disp = &priv->base;
        struct nouveau_software_chan *chan, *temp;
        unsigned long flags;
@@ -46,19 +49,25 @@ nv50_disp_intr_vblank(struct nv50_disp_priv *priv, int crtc)
                if (chan->vblank.crtc != crtc)
                        continue;
 
-               nv_wr32(priv, 0x001704, chan->vblank.channel);
-               nv_wr32(priv, 0x001710, 0x80000000 | chan->vblank.ctxdma);
-
-               if (nv_device(priv)->chipset == 0x50) {
-                       nv_wr32(priv, 0x001570, chan->vblank.offset);
-                       nv_wr32(priv, 0x001574, chan->vblank.value);
+               if (nv_device(priv)->chipset >= 0xc0) {
+                       nv_wr32(priv, 0x001718, 0x80000000 | chan->vblank.channel);
+                       bar->flush(bar);
+                       nv_wr32(priv, 0x06000c,
+                               upper_32_bits(chan->vblank.offset));
+                       nv_wr32(priv, 0x060010,
+                               lower_32_bits(chan->vblank.offset));
+                       nv_wr32(priv, 0x060014, chan->vblank.value);
                } else {
-                       if (nv_device(priv)->chipset >= 0xc0) {
-                               nv_wr32(priv, 0x06000c,
-                                       upper_32_bits(chan->vblank.offset));
+                       nv_wr32(priv, 0x001704, chan->vblank.channel);
+                       nv_wr32(priv, 0x001710, 0x80000000 | chan->vblank.ctxdma);
+                       bar->flush(bar);
+                       if (nv_device(priv)->chipset == 0x50) {
+                               nv_wr32(priv, 0x001570, chan->vblank.offset);
+                               nv_wr32(priv, 0x001574, chan->vblank.value);
+                       } else {
+                               nv_wr32(priv, 0x060010, chan->vblank.offset);
+                               nv_wr32(priv, 0x060014, chan->vblank.value);
                        }
-                       nv_wr32(priv, 0x060010, chan->vblank.offset);
-                       nv_wr32(priv, 0x060014, chan->vblank.value);
                }
 
                list_del(&chan->vblank.head);
index e45035efb8ca084c37785ffd4a0ca789523d4a2b..7bbb1e1b7a8d1ebbeeb275dd38e27caaa7a1400c 100644 (file)
@@ -669,21 +669,27 @@ nv40_grctx_fill(struct nouveau_device *device, struct nouveau_gpuobj *mem)
                           });
 }
 
-void
+int
 nv40_grctx_init(struct nouveau_device *device, u32 *size)
 {
-       u32 ctxprog[256], i;
+       u32 *ctxprog = kmalloc(256 * 4, GFP_KERNEL), i;
        struct nouveau_grctx ctx = {
                .device = device,
                .mode = NOUVEAU_GRCTX_PROG,
                .data = ctxprog,
-               .ctxprog_max = ARRAY_SIZE(ctxprog)
+               .ctxprog_max = 256,
        };
 
+       if (!ctxprog)
+               return -ENOMEM;
+
        nv40_grctx_generate(&ctx);
 
        nv_wr32(device, 0x400324, 0);
        for (i = 0; i < ctx.ctxprog_len; i++)
                nv_wr32(device, 0x400328, ctxprog[i]);
        *size = ctx.ctxvals_pos * 4;
+
+       kfree(ctxprog);
+       return 0;
 }
index 8d0021049ec09eeaf139b7797736965f52f8a7f2..cc6574eeb80e6459166224185a5bd81ce41e9aa4 100644 (file)
@@ -156,8 +156,8 @@ nv40_graph_context_ctor(struct nouveau_object *parent,
 static int
 nv40_graph_context_fini(struct nouveau_object *object, bool suspend)
 {
-       struct nv04_graph_priv *priv = (void *)object->engine;
-       struct nv04_graph_chan *chan = (void *)object;
+       struct nv40_graph_priv *priv = (void *)object->engine;
+       struct nv40_graph_chan *chan = (void *)object;
        u32 inst = 0x01000000 | nv_gpuobj(chan)->addr >> 4;
        int ret = 0;
 
@@ -346,7 +346,9 @@ nv40_graph_init(struct nouveau_object *object)
                return ret;
 
        /* generate and upload context program */
-       nv40_grctx_init(nv_device(priv), &priv->size);
+       ret = nv40_grctx_init(nv_device(priv), &priv->size);
+       if (ret)
+               return ret;
 
        /* No context present currently */
        nv_wr32(priv, NV40_PGRAPH_CTXCTL_CUR, 0x00000000);
index d2ac975afc2e8f46feff64c6be4c16e04faf73b3..7da35a4e7970d1684433f3fd036c60492a5ddb0d 100644 (file)
@@ -15,7 +15,7 @@ nv44_graph_class(void *priv)
        return !(0x0baf & (1 << (device->chipset & 0x0f)));
 }
 
-void nv40_grctx_init(struct nouveau_device *, u32 *size);
+int  nv40_grctx_init(struct nouveau_device *, u32 *size);
 void nv40_grctx_fill(struct nouveau_device *, struct nouveau_gpuobj *);
 
 #endif
index 12418574efeae389fa6fe3ee102379ae32b5fd19..f7c581ad1991b880b3abe6590f0250b68261a9d2 100644 (file)
@@ -38,7 +38,7 @@ struct nv40_mpeg_priv {
 };
 
 struct nv40_mpeg_chan {
-       struct nouveau_mpeg base;
+       struct nouveau_mpeg_chan base;
 };
 
 /*******************************************************************************
index 9ee9bf4028ca168800bc2c6fbcac96346aad9024..975137ba34a6faefb7d4121b8db2efd3464a28c6 100644 (file)
@@ -19,7 +19,6 @@ struct nouveau_mm {
 
        u32 block_size;
        int heap_nodes;
-       u32 heap_size;
 };
 
 int  nouveau_mm_init(struct nouveau_mm *, u32 offset, u32 length, u32 block);
index 818feabbf4a0969f090f897852fe4476a422b1b6..486f1a9217fd6cd51dc2c5530d455eaa155c86b4 100644 (file)
@@ -175,14 +175,18 @@ nv_mo32(void *obj, u32 addr, u32 mask, u32 data)
        return temp;
 }
 
-static inline bool
-nv_strncmp(void *obj, u32 addr, u32 len, const char *str)
+static inline int
+nv_memcmp(void *obj, u32 addr, const char *str, u32 len)
 {
+       unsigned char c1, c2;
+
        while (len--) {
-               if (nv_ro08(obj, addr++) != *(str++))
-                       return false;
+               c1 = nv_ro08(obj, addr++);
+               c2 = *(str++);
+               if (c1 != c2)
+                       return c1 - c2;
        }
-       return true;
+       return 0;
 }
 
 #endif
index 39e73b91d360a3753dbcc3c210ca1e77f00332ec..41b7a6a76f1981ae3427278bacaf8d2c99edbe09 100644 (file)
@@ -54,6 +54,7 @@ int nv04_clock_pll_calc(struct nouveau_clock *, struct nvbios_pll *,
                        int clk, struct nouveau_pll_vals *);
 int nv04_clock_pll_prog(struct nouveau_clock *, u32 reg1,
                        struct nouveau_pll_vals *);
-
+int nva3_clock_pll_calc(struct nouveau_clock *, struct nvbios_pll *,
+                       int clk, struct nouveau_pll_vals *);
 
 #endif
index dcb5c2befc928a716425ace89149cec8a808c2e3..70ca7d5a1aa1aaa4e4302ab599ed5398d4f666eb 100644 (file)
@@ -72,7 +72,7 @@ nouveau_bios_shadow_of(struct nouveau_bios *bios)
        }
 
        data = of_get_property(dn, "NVDA,BMP", &size);
-       if (data) {
+       if (data && size) {
                bios->size = size;
                bios->data = kmalloc(bios->size, GFP_KERNEL);
                if (bios->data)
@@ -104,6 +104,9 @@ nouveau_bios_shadow_pramin(struct nouveau_bios *bios)
                goto out;
 
        bios->size = nv_rd08(bios, 0x700002) * 512;
+       if (!bios->size)
+               goto out;
+
        bios->data = kmalloc(bios->size, GFP_KERNEL);
        if (bios->data) {
                for (i = 0; i < bios->size; i++)
@@ -155,6 +158,9 @@ nouveau_bios_shadow_prom(struct nouveau_bios *bios)
 
        /* read entire bios image to system memory */
        bios->size = nv_rd08(bios, 0x300002) * 512;
+       if (!bios->size)
+               goto out;
+
        bios->data = kmalloc(bios->size, GFP_KERNEL);
        if (bios->data) {
                for (i = 0; i < bios->size; i++)
@@ -186,14 +192,22 @@ nouveau_bios_shadow_acpi(struct nouveau_bios *bios)
 {
        struct pci_dev *pdev = nv_device(bios)->pdev;
        int ret, cnt, i;
-       u8  data[3];
 
-       if (!nouveau_acpi_rom_supported(pdev))
+       if (!nouveau_acpi_rom_supported(pdev)) {
+               bios->data = NULL;
                return;
+       }
 
        bios->size = 0;
-       if (nouveau_acpi_get_bios_chunk(data, 0, 3) == 3)
-               bios->size = data[2] * 512;
+       bios->data = kmalloc(4096, GFP_KERNEL);
+       if (bios->data) {
+               if (nouveau_acpi_get_bios_chunk(bios->data, 0, 4096) == 4096)
+                       bios->size = bios->data[2] * 512;
+               kfree(bios->data);
+       }
+
+       if (!bios->size)
+               return;
 
        bios->data = kmalloc(bios->size, GFP_KERNEL);
        for (i = 0; bios->data && i < bios->size; i += cnt) {
@@ -229,12 +243,14 @@ nouveau_bios_shadow_pci(struct nouveau_bios *bios)
 static int
 nouveau_bios_score(struct nouveau_bios *bios, const bool writeable)
 {
-       if (!bios->data || bios->data[0] != 0x55 || bios->data[1] != 0xAA) {
+       if (bios->size < 3 || !bios->data || bios->data[0] != 0x55 ||
+                       bios->data[1] != 0xAA) {
                nv_info(bios, "... signature not found\n");
                return 0;
        }
 
-       if (nvbios_checksum(bios->data, bios->data[2] * 512)) {
+       if (nvbios_checksum(bios->data,
+                       min_t(u32, bios->data[2] * 512, bios->size))) {
                nv_info(bios, "... checksum invalid\n");
                /* if a ro image is somewhat bad, it's probably all rubbish */
                return writeable ? 2 : 1;
index 7d750382a833c33b64fbbf40c98a1d8f936399e2..c511971577490499002426ed04087a517d8e0dab 100644 (file)
@@ -64,7 +64,7 @@ dcb_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
                }
        } else
        if (*ver >= 0x15) {
-               if (!nv_strncmp(bios, dcb - 7, 7, "DEV_REC")) {
+               if (!nv_memcmp(bios, dcb - 7, "DEV_REC", 7)) {
                        u16 i2c = nv_ro16(bios, dcb + 2);
                        *hdr = 4;
                        *cnt = (i2c - dcb) / 10;
index 5e5f4cddae3cc7248ed527c07b94e8d0c15e97e4..f835501203e552abb29b68425cb5b0a9b37e6bec 100644 (file)
@@ -157,11 +157,10 @@ pll_map_reg(struct nouveau_bios *bios, u32 reg, u32 *type, u8 *ver, u8 *len)
        while (map->reg) {
                if (map->reg == reg && *ver >= 0x20) {
                        u16 addr = (data += hdr);
+                       *type = map->type;
                        while (cnt--) {
-                               if (nv_ro32(bios, data) == map->reg) {
-                                       *type = map->type;
+                               if (nv_ro32(bios, data) == map->reg)
                                        return data;
-                               }
                                data += *len;
                        }
                        return addr;
@@ -200,11 +199,10 @@ pll_map_type(struct nouveau_bios *bios, u8 type, u32 *reg, u8 *ver, u8 *len)
        while (map->reg) {
                if (map->type == type && *ver >= 0x20) {
                        u16 addr = (data += hdr);
+                       *reg = map->reg;
                        while (cnt--) {
-                               if (nv_ro32(bios, data) == map->reg) {
-                                       *reg = map->reg;
+                               if (nv_ro32(bios, data) == map->reg)
                                        return data;
-                               }
                                data += *len;
                        }
                        return addr;
index cc8d7d162d7c348da6770d7404f195e9191d41e1..9068c98b96f64f2f8c0c5a18d478400d09855553 100644 (file)
@@ -66,6 +66,24 @@ nva3_clock_pll_set(struct nouveau_clock *clk, u32 type, u32 freq)
        return ret;
 }
 
+int
+nva3_clock_pll_calc(struct nouveau_clock *clock, struct nvbios_pll *info,
+                   int clk, struct nouveau_pll_vals *pv)
+{
+       int ret, N, M, P;
+
+       ret = nva3_pll_calc(clock, info, clk, &N, NULL, &M, &P);
+
+       if (ret > 0) {
+               pv->refclk = info->refclk;
+               pv->N1 = N;
+               pv->M1 = M;
+               pv->log2P = P;
+       }
+       return ret;
+}
+
+
 static int
 nva3_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
                struct nouveau_oclass *oclass, void *data, u32 size,
@@ -80,6 +98,7 @@ nva3_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
                return ret;
 
        priv->base.pll_set = nva3_clock_pll_set;
+       priv->base.pll_calc = nva3_clock_pll_calc;
        return 0;
 }
 
index 5ccce0b17bf3dd209bde225486b41bab55fcdf79..f6962c9b6c36b6f00db2715287dedf1c3adb9f4e 100644 (file)
@@ -79,6 +79,7 @@ nvc0_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
                return ret;
 
        priv->base.pll_set = nvc0_clock_pll_set;
+       priv->base.pll_calc = nva3_clock_pll_calc;
        return 0;
 }
 
index 42d7539e65250d239a9e7f8c65efd68855b76c90..5f570806143ad0fb35fcd67017acf07513b563e4 100644 (file)
@@ -219,13 +219,11 @@ nv50_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
                             ((priv->base.ram.size & 0x000000ff) << 32);
 
        tags = nv_rd32(priv, 0x100320);
-       if (tags) {
-               ret = nouveau_mm_init(&priv->base.tags, 0, tags, 1);
-               if (ret)
-                       return ret;
+       ret = nouveau_mm_init(&priv->base.tags, 0, tags, 1);
+       if (ret)
+               return ret;
 
-               nv_debug(priv, "%d compression tags\n", tags);
-       }
+       nv_debug(priv, "%d compression tags\n", tags);
 
        size = (priv->base.ram.size >> 12) - rsvd_head - rsvd_tail;
        switch (device->chipset) {
@@ -237,6 +235,7 @@ nv50_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
                        return ret;
 
                priv->base.ram.stolen = (u64)nv_rd32(priv, 0x100e10) << 12;
+               priv->base.ram.type = NV_MEM_TYPE_STOLEN;
                break;
        default:
                ret = nouveau_mm_init(&priv->base.vram, rsvd_head, size,
index 3d2c88310f982553380f19a7f89d5379a89a5d01..dbfc2abf0cfe1a98379a567fa8a7a90fcd409d5f 100644 (file)
@@ -292,7 +292,7 @@ nouveau_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
                case DCB_I2C_NVIO_BIT:
                        port->drive = info.drive & 0x0f;
                        if (device->card_type < NV_D0) {
-                               if (info.drive >= ARRAY_SIZE(nv50_i2c_port))
+                               if (port->drive >= ARRAY_SIZE(nv50_i2c_port))
                                        break;
                                port->drive = nv50_i2c_port[port->drive];
                                port->sense = port->drive;
index 0203e1e12caaad34f4639ec3824a33d770a5d447..9474cfca6e4ccde36379d3dfa3426317be005741 100644 (file)
@@ -67,7 +67,7 @@ nv41_vm_unmap(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt)
 static void
 nv41_vm_flush(struct nouveau_vm *vm)
 {
-       struct nv04_vm_priv *priv = (void *)vm->vmm;
+       struct nv04_vmmgr_priv *priv = (void *)vm->vmm;
 
        mutex_lock(&nv_subdev(priv)->mutex);
        nv_wr32(priv, 0x100810, 0x00000022);
@@ -92,7 +92,8 @@ nv41_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nv04_vmmgr_priv *priv;
        int ret;
 
-       if (!nouveau_boolopt(device->cfgopt, "NvPCIE", true)) {
+       if (pci_find_capability(device->pdev, PCI_CAP_ID_AGP) ||
+           !nouveau_boolopt(device->cfgopt, "NvPCIE", true)) {
                return nouveau_object_ctor(parent, engine, &nv04_vmmgr_oclass,
                                           data, size, pobject);
        }
index 0ac18d05a146389b6d87e8c7898188fda5b5c5e3..aa8131436e3dced3d3d9ef894fec6d5ff21cee2d 100644 (file)
@@ -163,7 +163,8 @@ nv44_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nv04_vmmgr_priv *priv;
        int ret;
 
-       if (!nouveau_boolopt(device->cfgopt, "NvPCIE", true)) {
+       if (pci_find_capability(device->pdev, PCI_CAP_ID_AGP) ||
+           !nouveau_boolopt(device->cfgopt, "NvPCIE", true)) {
                return nouveau_object_ctor(parent, engine, &nv04_vmmgr_oclass,
                                           data, size, pobject);
        }
index cc79c796afee316cd810125b93dd86fbef940d5e..cbf1fc60a38682be197dc1bb1f0f15c8853a06e6 100644 (file)
@@ -241,6 +241,10 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS)
 
        if (unlikely(!abi16))
                return -ENOMEM;
+
+       if (!drm->channel)
+               return nouveau_abi16_put(abi16, -ENODEV);
+
        client = nv_client(abi16->client);
 
        if (init->fb_ctxdma_handle == ~0 || init->tt_ctxdma_handle == ~0)
index 9a6e2cb282dc4e38612845f41f224c5e2aa9b083..d3595b23434ace439cc2087e871f636e86e59867 100644 (file)
@@ -355,7 +355,7 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force)
         * valid - it's not (rh#613284)
         */
        if (nv_encoder->dcb->lvdsconf.use_acpi_for_edid) {
-               if (!(nv_connector->edid = nouveau_acpi_edid(dev, connector))) {
+               if ((nv_connector->edid = nouveau_acpi_edid(dev, connector))) {
                        status = connector_status_connected;
                        goto out;
                }
index 8f98e5a8c488dba5c8e86d937aa26b5e65d78175..86124b131f4f31a2ca18e8c2416084ad6df1f585 100644 (file)
@@ -290,6 +290,7 @@ nouveau_display_create(struct drm_device *dev)
        struct nouveau_drm *drm = nouveau_drm(dev);
        struct nouveau_disp *pdisp = nouveau_disp(drm->device);
        struct nouveau_display *disp;
+       u32 pclass = dev->pdev->class >> 8;
        int ret, gen;
 
        disp = drm->display = kzalloc(sizeof(*disp), GFP_KERNEL);
@@ -360,23 +361,27 @@ nouveau_display_create(struct drm_device *dev)
        drm_kms_helper_poll_init(dev);
        drm_kms_helper_poll_disable(dev);
 
-       if (nv_device(drm->device)->card_type < NV_50)
-               ret = nv04_display_create(dev);
-       else
-       if (nv_device(drm->device)->card_type < NV_D0)
-               ret = nv50_display_create(dev);
-       else
-               ret = nvd0_display_create(dev);
-       if (ret)
-               goto disp_create_err;
-
-       if (dev->mode_config.num_crtc) {
-               ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
+       if (nouveau_modeset == 1 ||
+           (nouveau_modeset < 0 && pclass == PCI_CLASS_DISPLAY_VGA)) {
+               if (nv_device(drm->device)->card_type < NV_50)
+                       ret = nv04_display_create(dev);
+               else
+               if (nv_device(drm->device)->card_type < NV_D0)
+                       ret = nv50_display_create(dev);
+               else
+                       ret = nvd0_display_create(dev);
                if (ret)
-                       goto vblank_err;
+                       goto disp_create_err;
+
+               if (dev->mode_config.num_crtc) {
+                       ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
+                       if (ret)
+                               goto vblank_err;
+               }
+
+               nouveau_backlight_init(dev);
        }
 
-       nouveau_backlight_init(dev);
        return 0;
 
 vblank_err:
@@ -395,7 +400,8 @@ nouveau_display_destroy(struct drm_device *dev)
        nouveau_backlight_exit(dev);
        drm_vblank_cleanup(dev);
 
-       disp->dtor(dev);
+       if (disp->dtor)
+               disp->dtor(dev);
 
        drm_kms_helper_poll_fini(dev);
        drm_mode_config_cleanup(dev);
@@ -530,9 +536,11 @@ nouveau_page_flip_reserve(struct nouveau_bo *old_bo,
        if (ret)
                goto fail;
 
-       ret = ttm_bo_reserve(&old_bo->bo, false, false, false, 0);
-       if (ret)
-               goto fail_unreserve;
+       if (likely(old_bo != new_bo)) {
+               ret = ttm_bo_reserve(&old_bo->bo, false, false, false, 0);
+               if (ret)
+                       goto fail_unreserve;
+       }
 
        return 0;
 
@@ -551,8 +559,10 @@ nouveau_page_flip_unreserve(struct nouveau_bo *old_bo,
        nouveau_bo_fence(new_bo, fence);
        ttm_bo_unreserve(&new_bo->bo);
 
-       nouveau_bo_fence(old_bo, fence);
-       ttm_bo_unreserve(&old_bo->bo);
+       if (likely(old_bo != new_bo)) {
+               nouveau_bo_fence(old_bo, fence);
+               ttm_bo_unreserve(&old_bo->bo);
+       }
 
        nouveau_bo_unpin(old_bo);
 }
index ccae8c26ae2b34ecc25e8312ee6d57c0d14f06e3..8503b2ea570a0616234e409c524593f37a98648e 100644 (file)
@@ -63,8 +63,9 @@ MODULE_PARM_DESC(noaccel, "disable kernel/abi16 acceleration");
 static int nouveau_noaccel = 0;
 module_param_named(noaccel, nouveau_noaccel, int, 0400);
 
-MODULE_PARM_DESC(modeset, "enable driver");
-static int nouveau_modeset = -1;
+MODULE_PARM_DESC(modeset, "enable driver (default: auto, "
+                         "0 = disabled, 1 = enabled, 2 = headless)");
+int nouveau_modeset = -1;
 module_param_named(modeset, nouveau_modeset, int, 0400);
 
 static struct drm_driver driver;
@@ -128,7 +129,8 @@ nouveau_accel_init(struct nouveau_drm *drm)
 
        /* initialise synchronisation routines */
        if      (device->card_type < NV_10) ret = nv04_fence_create(drm);
-       else if (device->chipset   <  0x84) ret = nv10_fence_create(drm);
+       else if (device->card_type < NV_50) ret = nv10_fence_create(drm);
+       else if (device->chipset   <  0x84) ret = nv50_fence_create(drm);
        else if (device->card_type < NV_C0) ret = nv84_fence_create(drm);
        else                                ret = nvc0_fence_create(drm);
        if (ret) {
@@ -363,7 +365,8 @@ nouveau_drm_unload(struct drm_device *dev)
 
        nouveau_pm_fini(dev);
 
-       nouveau_display_fini(dev);
+       if (dev->mode_config.num_crtc)
+               nouveau_display_fini(dev);
        nouveau_display_destroy(dev);
 
        nouveau_irq_fini(dev);
@@ -403,13 +406,15 @@ nouveau_drm_suspend(struct pci_dev *pdev, pm_message_t pm_state)
            pm_state.event == PM_EVENT_PRETHAW)
                return 0;
 
-       NV_INFO(drm, "suspending fbcon...\n");
-       nouveau_fbcon_set_suspend(dev, 1);
+       if (dev->mode_config.num_crtc) {
+               NV_INFO(drm, "suspending fbcon...\n");
+               nouveau_fbcon_set_suspend(dev, 1);
 
-       NV_INFO(drm, "suspending display...\n");
-       ret = nouveau_display_suspend(dev);
-       if (ret)
-               return ret;
+               NV_INFO(drm, "suspending display...\n");
+               ret = nouveau_display_suspend(dev);
+               if (ret)
+                       return ret;
+       }
 
        NV_INFO(drm, "evicting buffers...\n");
        ttm_bo_evict_mm(&drm->ttm.bdev, TTM_PL_VRAM);
@@ -445,8 +450,10 @@ fail_client:
                nouveau_client_init(&cli->base);
        }
 
-       NV_INFO(drm, "resuming display...\n");
-       nouveau_display_resume(dev);
+       if (dev->mode_config.num_crtc) {
+               NV_INFO(drm, "resuming display...\n");
+               nouveau_display_resume(dev);
+       }
        return ret;
 }
 
@@ -486,8 +493,10 @@ nouveau_drm_resume(struct pci_dev *pdev)
        nouveau_irq_postinstall(dev);
        nouveau_pm_resume(dev);
 
-       NV_INFO(drm, "resuming display...\n");
-       nouveau_display_resume(dev);
+       if (dev->mode_config.num_crtc) {
+               NV_INFO(drm, "resuming display...\n");
+               nouveau_display_resume(dev);
+       }
        return 0;
 }
 
@@ -662,9 +671,7 @@ nouveau_drm_init(void)
 #ifdef CONFIG_VGA_CONSOLE
                if (vgacon_text_force())
                        nouveau_modeset = 0;
-               else
 #endif
-                       nouveau_modeset = 1;
        }
 
        if (!nouveau_modeset)
index 819471217546b23cb867e3e583ed856d5d810ea2..a10169927086dfea6c826dac0378ae1d2c82ffb3 100644 (file)
@@ -141,4 +141,6 @@ int nouveau_drm_resume(struct pci_dev *);
                nv_info((cli), fmt, ##args);                                   \
 } while (0)
 
+extern int nouveau_modeset;
+
 #endif
index 9ca8afdb5549777c7a2b25e64de9b63f700260bc..1d8cb506a28ae5159ebe4c9df362f3f0d92d7758 100644 (file)
@@ -61,13 +61,15 @@ nouveau_irq_handler(DRM_IRQ_ARGS)
 
        nv_subdev(pmc)->intr(nv_subdev(pmc));
 
-       if (device->card_type >= NV_D0) {
-               if (nv_rd32(device, 0x000100) & 0x04000000)
-                       nvd0_display_intr(dev);
-       } else
-       if (device->card_type >= NV_50) {
-               if (nv_rd32(device, 0x000100) & 0x04000000)
-                       nv50_display_intr(dev);
+       if (dev->mode_config.num_crtc) {
+               if (device->card_type >= NV_D0) {
+                       if (nv_rd32(device, 0x000100) & 0x04000000)
+                               nvd0_display_intr(dev);
+               } else
+               if (device->card_type >= NV_50) {
+                       if (nv_rd32(device, 0x000100) & 0x04000000)
+                               nv50_display_intr(dev);
+               }
        }
 
        return IRQ_HANDLED;
index 347a3bd78d0486f1fed24f11d8183f9382d822dd..64f7020fb605dcaff92163aa161d174ad0d77a23 100644 (file)
@@ -220,7 +220,7 @@ out:
        NVWriteVgaCrtc(dev, 0, NV_CIO_CR_MODE_INDEX, saved_cr_mode);
 
        if (blue == 0x18) {
-               NV_INFO(drm, "Load detected on head A\n");
+               NV_DEBUG(drm, "Load detected on head A\n");
                return connector_status_connected;
        }
 
@@ -338,8 +338,8 @@ nv17_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
 
        if (nv17_dac_sample_load(encoder) &
            NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI) {
-               NV_INFO(drm, "Load detected on output %c\n",
-                       '@' + ffs(dcb->or));
+               NV_DEBUG(drm, "Load detected on output %c\n",
+                        '@' + ffs(dcb->or));
                return connector_status_connected;
        } else {
                return connector_status_disconnected;
@@ -413,9 +413,9 @@ static void nv04_dac_commit(struct drm_encoder *encoder)
 
        helper->dpms(encoder, DRM_MODE_DPMS_ON);
 
-       NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n",
-               drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base),
-               nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
+       NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n",
+                drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base),
+                nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
 }
 
 void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable)
@@ -461,8 +461,8 @@ static void nv04_dac_dpms(struct drm_encoder *encoder, int mode)
                return;
        nv_encoder->last_dpms = mode;
 
-       NV_INFO(drm, "Setting dpms mode %d on vga encoder (output %d)\n",
-                    mode, nv_encoder->dcb->index);
+       NV_DEBUG(drm, "Setting dpms mode %d on vga encoder (output %d)\n",
+                mode, nv_encoder->dcb->index);
 
        nv04_dac_update_dacclk(encoder, mode == DRM_MODE_DPMS_ON);
 }
index da55d7642c8cdd325ccca35bd8a1d1b1c1bda8f5..184cdf806761c0bc0cefb52af00a8799ae8e6393 100644 (file)
@@ -476,9 +476,9 @@ static void nv04_dfp_commit(struct drm_encoder *encoder)
 
        helper->dpms(encoder, DRM_MODE_DPMS_ON);
 
-       NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n",
-               drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base),
-               nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
+       NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n",
+                drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base),
+                nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
 }
 
 static void nv04_dfp_update_backlight(struct drm_encoder *encoder, int mode)
@@ -520,8 +520,8 @@ static void nv04_lvds_dpms(struct drm_encoder *encoder, int mode)
                return;
        nv_encoder->last_dpms = mode;
 
-       NV_INFO(drm, "Setting dpms mode %d on lvds encoder (output %d)\n",
-                    mode, nv_encoder->dcb->index);
+       NV_DEBUG(drm, "Setting dpms mode %d on lvds encoder (output %d)\n",
+                mode, nv_encoder->dcb->index);
 
        if (was_powersaving && is_powersaving_dpms(mode))
                return;
@@ -565,8 +565,8 @@ static void nv04_tmds_dpms(struct drm_encoder *encoder, int mode)
                return;
        nv_encoder->last_dpms = mode;
 
-       NV_INFO(drm, "Setting dpms mode %d on tmds encoder (output %d)\n",
-                    mode, nv_encoder->dcb->index);
+       NV_DEBUG(drm, "Setting dpms mode %d on tmds encoder (output %d)\n",
+                mode, nv_encoder->dcb->index);
 
        nv04_dfp_update_backlight(encoder, mode);
        nv04_dfp_update_fp_control(encoder, mode);
index 099fbeda6e2e18f85b7dedbc961582516729b50a..62e826a139b3bd4b08d00a0ca46e0efc59c62d63 100644 (file)
@@ -75,8 +75,8 @@ static void nv04_tv_dpms(struct drm_encoder *encoder, int mode)
        struct nv04_mode_state *state = &nv04_display(dev)->mode_reg;
        uint8_t crtc1A;
 
-       NV_INFO(drm, "Setting dpms mode %d on TV encoder (output %d)\n",
-               mode, nv_encoder->dcb->index);
+       NV_DEBUG(drm, "Setting dpms mode %d on TV encoder (output %d)\n",
+                mode, nv_encoder->dcb->index);
 
        state->pllsel &= ~(PLLSEL_TV_CRTC1_MASK | PLLSEL_TV_CRTC2_MASK);
 
@@ -167,9 +167,8 @@ static void nv04_tv_commit(struct drm_encoder *encoder)
 
        helper->dpms(encoder, DRM_MODE_DPMS_ON);
 
-       NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n",
-                     drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), nv_crtc->index,
-                     '@' + ffs(nv_encoder->dcb->or));
+       NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n",
+                drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
 }
 
 static void nv04_tv_destroy(struct drm_encoder *encoder)
index 2e566e123e9e747e988f7482a3a5b827b7ca121f..3bce0299f64a664f9d1de78a6f452c907221694f 100644 (file)
@@ -1696,35 +1696,43 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc)
                        return ATOM_PPLL2;
                DRM_ERROR("unable to allocate a PPLL\n");
                return ATOM_PPLL_INVALID;
-       } else {
-               if (ASIC_IS_AVIVO(rdev)) {
-                       /* in DP mode, the DP ref clock can come from either PPLL
-                        * depending on the asic:
-                        * DCE3: PPLL1 or PPLL2
-                        */
-                       if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(radeon_crtc->encoder))) {
-                               /* use the same PPLL for all DP monitors */
-                               pll = radeon_get_shared_dp_ppll(crtc);
-                               if (pll != ATOM_PPLL_INVALID)
-                                       return pll;
-                       } else {
-                               /* use the same PPLL for all monitors with the same clock */
-                               pll = radeon_get_shared_nondp_ppll(crtc);
-                               if (pll != ATOM_PPLL_INVALID)
-                                       return pll;
-                       }
-                       /* all other cases */
-                       pll_in_use = radeon_get_pll_use_mask(crtc);
+       } else if (ASIC_IS_AVIVO(rdev)) {
+               /* in DP mode, the DP ref clock can come from either PPLL
+                * depending on the asic:
+                * DCE3: PPLL1 or PPLL2
+                */
+               if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(radeon_crtc->encoder))) {
+                       /* use the same PPLL for all DP monitors */
+                       pll = radeon_get_shared_dp_ppll(crtc);
+                       if (pll != ATOM_PPLL_INVALID)
+                               return pll;
+               } else {
+                       /* use the same PPLL for all monitors with the same clock */
+                       pll = radeon_get_shared_nondp_ppll(crtc);
+                       if (pll != ATOM_PPLL_INVALID)
+                               return pll;
+               }
+               /* all other cases */
+               pll_in_use = radeon_get_pll_use_mask(crtc);
+               /* the order shouldn't matter here, but we probably
+                * need this until we have atomic modeset
+                */
+               if (rdev->flags & RADEON_IS_IGP) {
                        if (!(pll_in_use & (1 << ATOM_PPLL1)))
                                return ATOM_PPLL1;
                        if (!(pll_in_use & (1 << ATOM_PPLL2)))
                                return ATOM_PPLL2;
-                       DRM_ERROR("unable to allocate a PPLL\n");
-                       return ATOM_PPLL_INVALID;
                } else {
-                       /* on pre-R5xx asics, the crtc to pll mapping is hardcoded */
-                       return radeon_crtc->crtc_id;
+                       if (!(pll_in_use & (1 << ATOM_PPLL2)))
+                               return ATOM_PPLL2;
+                       if (!(pll_in_use & (1 << ATOM_PPLL1)))
+                               return ATOM_PPLL1;
                }
+               DRM_ERROR("unable to allocate a PPLL\n");
+               return ATOM_PPLL_INVALID;
+       } else {
+               /* on pre-R5xx asics, the crtc to pll mapping is hardcoded */
+               return radeon_crtc->crtc_id;
        }
 }
 
index 49cbb3795a102e755337a3c2105f03caedc0f2ee..010bae19554ad204537a31a5e02584d130086ff3 100644 (file)
@@ -184,6 +184,7 @@ void radeon_atom_backlight_init(struct radeon_encoder *radeon_encoder,
        struct radeon_backlight_privdata *pdata;
        struct radeon_encoder_atom_dig *dig;
        u8 backlight_level;
+       char bl_name[16];
 
        if (!radeon_encoder->enc_priv)
                return;
@@ -203,7 +204,9 @@ void radeon_atom_backlight_init(struct radeon_encoder *radeon_encoder,
        memset(&props, 0, sizeof(props));
        props.max_brightness = RADEON_MAX_BL_LEVEL;
        props.type = BACKLIGHT_RAW;
-       bd = backlight_device_register("radeon_bl", &drm_connector->kdev,
+       snprintf(bl_name, sizeof(bl_name),
+                "radeon_bl%d", dev->primary->index);
+       bd = backlight_device_register(bl_name, &drm_connector->kdev,
                                       pdata, &radeon_atom_backlight_ops, &props);
        if (IS_ERR(bd)) {
                DRM_ERROR("Backlight registration failed\n");
@@ -1622,7 +1625,7 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
                        atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0);
                        atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
                        /* some early dce3.2 boards have a bug in their transmitter control table */
-                       if ((rdev->family != CHIP_RV710) || (rdev->family != CHIP_RV730))
+                       if ((rdev->family != CHIP_RV710) && (rdev->family != CHIP_RV730))
                                atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
                }
                if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
index 14313ad43b7680f28b322b913997cf653242bb07..219942c660d7d2129e7c21ac375761dcd5309c9f 100644 (file)
@@ -1330,6 +1330,8 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav
                                        break;
                                udelay(1);
                        }
+               } else {
+                       save->crtc_enabled[i] = false;
                }
        }
 
@@ -1372,7 +1374,7 @@ void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *s
        WREG32(BIF_FB_EN, FB_READ_EN | FB_WRITE_EN);
 
        for (i = 0; i < rdev->num_crtc; i++) {
-               if (save->crtc_enabled) {
+               if (save->crtc_enabled[i]) {
                        if (ASIC_IS_DCE6(rdev)) {
                                tmp = RREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i]);
                                tmp |= EVERGREEN_CRTC_BLANK_DATA_EN;
index 573ed1bc6cf7d36ffd1a3385cc05350fd7a3d3a0..c042e497e4507eaebfd91bb477acbc7520f0143d 100644 (file)
@@ -264,7 +264,7 @@ static int evergreen_surface_check_2d(struct radeon_cs_parser *p,
        /* macro tile width & height */
        palign = (8 * surf->bankw * track->npipes) * surf->mtilea;
        halign = (8 * surf->bankh * surf->nbanks) / surf->mtilea;
-       mtileb = (palign / 8) * (halign / 8) * tileb;;
+       mtileb = (palign / 8) * (halign / 8) * tileb;
        mtile_pr = surf->nbx / palign;
        mtile_ps = (mtile_pr * surf->nby) / halign;
        surf->layer_size = mtile_ps * mtileb * slice_pt;
@@ -2725,6 +2725,9 @@ static bool evergreen_vm_reg_valid(u32 reg)
        /* check config regs */
        switch (reg) {
        case GRBM_GFX_INDEX:
+       case CP_STRMOUT_CNTL:
+       case CP_COHER_CNTL:
+       case CP_COHER_SIZE:
        case VGT_VTX_VECT_EJECT_REG:
        case VGT_CACHE_INVALIDATION:
        case VGT_GS_VERTEX_REUSE:
@@ -2829,6 +2832,7 @@ static bool evergreen_vm_reg_valid(u32 reg)
        case CAYMAN_SQ_EX_ALLOC_TABLE_SLOTS:
                return true;
        default:
+               DRM_ERROR("Invalid register 0x%x in CS\n", reg);
                return false;
        }
 }
index df542f1a5dfbf38198d6bfbe329fd6964eacf352..2bc0f6a1b428ab8151b2a7fa57d5f7848ab0dda6 100644 (file)
 #define                FB_READ_EN                                      (1 << 0)
 #define                FB_WRITE_EN                                     (1 << 1)
 
+#define        CP_STRMOUT_CNTL                                 0x84FC
+
+#define        CP_COHER_CNTL                                   0x85F0
+#define        CP_COHER_SIZE                                   0x85F4
 #define        CP_COHER_BASE                                   0x85F8
 #define        CP_STALLED_STAT1                        0x8674
 #define        CP_STALLED_STAT2                        0x8678
index 8c74c729586db21185e54465d23289a15bc4d979..81e6a568c29debcf49bb915c5d3aa19bcc88324e 100644 (file)
@@ -1538,26 +1538,31 @@ void cayman_vm_set_page(struct radeon_device *rdev, uint64_t pe,
 {
        struct radeon_ring *ring = &rdev->ring[rdev->asic->vm.pt_ring_index];
        uint32_t r600_flags = cayman_vm_page_flags(rdev, flags);
-       int i;
 
-       radeon_ring_write(ring, PACKET3(PACKET3_ME_WRITE, 1 + count * 2));
-       radeon_ring_write(ring, pe);
-       radeon_ring_write(ring, upper_32_bits(pe) & 0xff);
-       for (i = 0; i < count; ++i) {
-               uint64_t value = 0;
-               if (flags & RADEON_VM_PAGE_SYSTEM) {
-                       value = radeon_vm_map_gart(rdev, addr);
-                       value &= 0xFFFFFFFFFFFFF000ULL;
-                       addr += incr;
-
-               } else if (flags & RADEON_VM_PAGE_VALID) {
-                       value = addr;
-                       addr += incr;
-               }
+       while (count) {
+               unsigned ndw = 1 + count * 2;
+               if (ndw > 0x3FFF)
+                       ndw = 0x3FFF;
+
+               radeon_ring_write(ring, PACKET3(PACKET3_ME_WRITE, ndw));
+               radeon_ring_write(ring, pe);
+               radeon_ring_write(ring, upper_32_bits(pe) & 0xff);
+               for (; ndw > 1; ndw -= 2, --count, pe += 8) {
+                       uint64_t value = 0;
+                       if (flags & RADEON_VM_PAGE_SYSTEM) {
+                               value = radeon_vm_map_gart(rdev, addr);
+                               value &= 0xFFFFFFFFFFFFF000ULL;
+                               addr += incr;
+
+                       } else if (flags & RADEON_VM_PAGE_VALID) {
+                               value = addr;
+                               addr += incr;
+                       }
 
-               value |= r600_flags;
-               radeon_ring_write(ring, value);
-               radeon_ring_write(ring, upper_32_bits(value));
+                       value |= r600_flags;
+                       radeon_ring_write(ring, value);
+                       radeon_ring_write(ring, upper_32_bits(value));
+               }
        }
 }
 
@@ -1586,4 +1591,8 @@ void cayman_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm)
        /* bits 0-7 are the VM contexts0-7 */
        radeon_ring_write(ring, PACKET0(VM_INVALIDATE_REQUEST, 0));
        radeon_ring_write(ring, 1 << vm->id);
+
+       /* sync PFP to ME, otherwise we might get invalid PFP reads */
+       radeon_ring_write(ring, PACKET3(PACKET3_PFP_SYNC_ME, 0));
+       radeon_ring_write(ring, 0x0);
 }
index 2423d1b5d385938f2445706abc97ab74198e1b0f..cbef6815907a13c83efff8b9e863568b1e625980 100644 (file)
 #define        PACKET3_MPEG_INDEX                              0x3A
 #define        PACKET3_WAIT_REG_MEM                            0x3C
 #define        PACKET3_MEM_WRITE                               0x3D
+#define        PACKET3_PFP_SYNC_ME                             0x42
 #define        PACKET3_SURFACE_SYNC                            0x43
 #              define PACKET3_CB0_DEST_BASE_ENA    (1 << 6)
 #              define PACKET3_CB1_DEST_BASE_ENA    (1 << 7)
index 10ea17a6b2a6edfae76955f7e8f2ccd08ea7b1fe..42433344cb1b24860998067fe7c96baf332c1ece 100644 (file)
@@ -69,9 +69,12 @@ static struct radeon_agpmode_quirk radeon_agpmode_quirk_list[] = {
        /* Intel 82830 830 Chipset Host Bridge / Mobility M6 LY Needs AGPMode 2 (fdo #17360)*/
        { PCI_VENDOR_ID_INTEL, 0x3575, PCI_VENDOR_ID_ATI, 0x4c59,
                PCI_VENDOR_ID_DELL, 0x00e3, 2},
-       /* Intel 82852/82855 host bridge / Mobility FireGL 9000 R250 Needs AGPMode 1 (lp #296617) */
+       /* Intel 82852/82855 host bridge / Mobility FireGL 9000 RV250 Needs AGPMode 1 (lp #296617) */
        { PCI_VENDOR_ID_INTEL, 0x3580, PCI_VENDOR_ID_ATI, 0x4c66,
                PCI_VENDOR_ID_DELL, 0x0149, 1},
+       /* Intel 82855PM host bridge / Mobility FireGL 9000 RV250 Needs AGPMode 1 for suspend/resume */
+       { PCI_VENDOR_ID_INTEL, 0x3340, PCI_VENDOR_ID_ATI, 0x4c66,
+               PCI_VENDOR_ID_IBM, 0x0531, 1},
        /* Intel 82852/82855 host bridge / Mobility 9600 M10 RV350 Needs AGPMode 1 (deb #467460) */
        { PCI_VENDOR_ID_INTEL, 0x3580, PCI_VENDOR_ID_ATI, 0x4e50,
                0x1025, 0x0061, 1},
index 1aa3f910b99328e9f3de367859742bb57722732b..15f5ded65e0c290e431a73d4d2c950c9fd9d2687 100644 (file)
@@ -87,7 +87,7 @@ static union acpi_object *radeon_atpx_call(acpi_handle handle, int function,
                atpx_arg_elements[1].integer.value = 0;
        }
 
-       status = acpi_evaluate_object(handle, "ATPX", &atpx_arg, &buffer);
+       status = acpi_evaluate_object(handle, NULL, &atpx_arg, &buffer);
 
        /* Fail only if calling the method fails and ATPX is supported */
        if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
@@ -352,9 +352,9 @@ static int radeon_atpx_switchto(enum vga_switcheroo_client_id id)
 }
 
 /**
- * radeon_atpx_switchto - switch to the requested GPU
+ * radeon_atpx_power_state - power down/up the requested GPU
  *
- * @id: GPU to switch to
+ * @id: GPU to power down/up
  * @state: requested power state (0 = off, 1 = on)
  *
  * Execute the necessary ATPX function to power down/up the discrete GPU
@@ -373,11 +373,11 @@ static int radeon_atpx_power_state(enum vga_switcheroo_client_id id,
 }
 
 /**
- * radeon_atpx_pci_probe_handle - look up the ATRM and ATPX handles
+ * radeon_atpx_pci_probe_handle - look up the ATPX handle
  *
  * @pdev: pci device
  *
- * Look up the ATPX and ATRM handles (all asics).
+ * Look up the ATPX handles (all asics).
  * Returns true if the handles are found, false if not.
  */
 static bool radeon_atpx_pci_probe_handle(struct pci_dev *pdev)
index 67cfc1795ecdd4560ac720cc85b0e5a17335a507..b884c362a8c2c0770c02ecb09100d1f9440b55ab 100644 (file)
@@ -941,7 +941,7 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
        struct drm_mode_object *obj;
        int i;
        enum drm_connector_status ret = connector_status_disconnected;
-       bool dret = false;
+       bool dret = false, broken_edid = false;
 
        if (!force && radeon_check_hpd_status_unchanged(connector))
                return connector->status;
@@ -965,6 +965,9 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
                                ret = connector_status_disconnected;
                                DRM_ERROR("%s: detected RS690 floating bus bug, stopping ddc detect\n", drm_get_connector_name(connector));
                                radeon_connector->ddc_bus = NULL;
+                       } else {
+                               ret = connector_status_connected;
+                               broken_edid = true; /* defer use_digital to later */
                        }
                } else {
                        radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL);
@@ -1047,13 +1050,24 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
 
                        encoder_funcs = encoder->helper_private;
                        if (encoder_funcs->detect) {
-                               if (ret != connector_status_connected) {
-                                       ret = encoder_funcs->detect(encoder, connector);
-                                       if (ret == connector_status_connected) {
-                                               radeon_connector->use_digital = false;
+                               if (!broken_edid) {
+                                       if (ret != connector_status_connected) {
+                                               /* deal with analog monitors without DDC */
+                                               ret = encoder_funcs->detect(encoder, connector);
+                                               if (ret == connector_status_connected) {
+                                                       radeon_connector->use_digital = false;
+                                               }
+                                               if (ret != connector_status_disconnected)
+                                                       radeon_connector->detected_by_load = true;
                                        }
-                                       if (ret != connector_status_disconnected)
-                                               radeon_connector->detected_by_load = true;
+                               } else {
+                                       enum drm_connector_status lret;
+                                       /* assume digital unless load detected otherwise */
+                                       radeon_connector->use_digital = true;
+                                       lret = encoder_funcs->detect(encoder, connector);
+                                       DRM_DEBUG_KMS("load_detect %x returned: %x\n",encoder->encoder_type,lret);
+                                       if (lret == connector_status_connected)
+                                               radeon_connector->use_digital = false;
                                }
                                break;
                        }
index bd13ca09eb626efcc2c312ef68569ffcf7655db9..e2f5f888c374cc29b2f8658a5e0ba9d91325827d 100644 (file)
@@ -355,6 +355,8 @@ int radeon_wb_init(struct radeon_device *rdev)
  */
 void radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *mc, u64 base)
 {
+       uint64_t limit = (uint64_t)radeon_vram_limit << 20;
+
        mc->vram_start = base;
        if (mc->mc_vram_size > (0xFFFFFFFF - base + 1)) {
                dev_warn(rdev->dev, "limiting VRAM to PCI aperture size\n");
@@ -368,8 +370,8 @@ void radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *mc, u64
                mc->mc_vram_size = mc->aper_size;
        }
        mc->vram_end = mc->vram_start + mc->mc_vram_size - 1;
-       if (radeon_vram_limit && radeon_vram_limit < mc->real_vram_size)
-               mc->real_vram_size = radeon_vram_limit;
+       if (limit && limit < mc->real_vram_size)
+               mc->real_vram_size = limit;
        dev_info(rdev->dev, "VRAM: %lluM 0x%016llX - 0x%016llX (%lluM used)\n",
                        mc->mc_vram_size >> 20, mc->vram_start,
                        mc->vram_end, mc->real_vram_size >> 20);
@@ -834,6 +836,19 @@ static unsigned int radeon_vga_set_decode(void *cookie, bool state)
                return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
 }
 
+/**
+ * radeon_check_pot_argument - check that argument is a power of two
+ *
+ * @arg: value to check
+ *
+ * Validates that a certain argument is a power of two (all asics).
+ * Returns true if argument is valid.
+ */
+static bool radeon_check_pot_argument(int arg)
+{
+       return (arg & (arg - 1)) == 0;
+}
+
 /**
  * radeon_check_arguments - validate module params
  *
@@ -845,52 +860,25 @@ static unsigned int radeon_vga_set_decode(void *cookie, bool state)
 static void radeon_check_arguments(struct radeon_device *rdev)
 {
        /* vramlimit must be a power of two */
-       switch (radeon_vram_limit) {
-       case 0:
-       case 4:
-       case 8:
-       case 16:
-       case 32:
-       case 64:
-       case 128:
-       case 256:
-       case 512:
-       case 1024:
-       case 2048:
-       case 4096:
-               break;
-       default:
+       if (!radeon_check_pot_argument(radeon_vram_limit)) {
                dev_warn(rdev->dev, "vram limit (%d) must be a power of 2\n",
                                radeon_vram_limit);
                radeon_vram_limit = 0;
-               break;
        }
-       radeon_vram_limit = radeon_vram_limit << 20;
+
        /* gtt size must be power of two and greater or equal to 32M */
-       switch (radeon_gart_size) {
-       case 4:
-       case 8:
-       case 16:
+       if (radeon_gart_size < 32) {
                dev_warn(rdev->dev, "gart size (%d) too small forcing to 512M\n",
                                radeon_gart_size);
                radeon_gart_size = 512;
-               break;
-       case 32:
-       case 64:
-       case 128:
-       case 256:
-       case 512:
-       case 1024:
-       case 2048:
-       case 4096:
-               break;
-       default:
+
+       } else if (!radeon_check_pot_argument(radeon_gart_size)) {
                dev_warn(rdev->dev, "gart size (%d) must be a power of 2\n",
                                radeon_gart_size);
                radeon_gart_size = 512;
-               break;
        }
-       rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
+       rdev->mc.gtt_size = (uint64_t)radeon_gart_size << 20;
+
        /* AGP mode can only be -1, 1, 2, 4, 8 */
        switch (radeon_agpmode) {
        case -1:
index a7677dd1ce98573121a395643b31a57480e60c76..4debd60e5aa63390f0f386ee236bfc42fe4f8cf3 100644 (file)
@@ -355,14 +355,13 @@ int radeon_gart_init(struct radeon_device *rdev)
        DRM_INFO("GART: num cpu pages %u, num gpu pages %u\n",
                 rdev->gart.num_cpu_pages, rdev->gart.num_gpu_pages);
        /* Allocate pages table */
-       rdev->gart.pages = kzalloc(sizeof(void *) * rdev->gart.num_cpu_pages,
-                                  GFP_KERNEL);
+       rdev->gart.pages = vzalloc(sizeof(void *) * rdev->gart.num_cpu_pages);
        if (rdev->gart.pages == NULL) {
                radeon_gart_fini(rdev);
                return -ENOMEM;
        }
-       rdev->gart.pages_addr = kzalloc(sizeof(dma_addr_t) *
-                                       rdev->gart.num_cpu_pages, GFP_KERNEL);
+       rdev->gart.pages_addr = vzalloc(sizeof(dma_addr_t) *
+                                       rdev->gart.num_cpu_pages);
        if (rdev->gart.pages_addr == NULL) {
                radeon_gart_fini(rdev);
                return -ENOMEM;
@@ -388,8 +387,8 @@ void radeon_gart_fini(struct radeon_device *rdev)
                radeon_gart_unbind(rdev, 0, rdev->gart.num_cpu_pages);
        }
        rdev->gart.ready = false;
-       kfree(rdev->gart.pages);
-       kfree(rdev->gart.pages_addr);
+       vfree(rdev->gart.pages);
+       vfree(rdev->gart.pages_addr);
        rdev->gart.pages = NULL;
        rdev->gart.pages_addr = NULL;
 
@@ -577,7 +576,7 @@ void radeon_vm_manager_fini(struct radeon_device *rdev)
  *
  * Global and local mutex must be locked!
  */
-int radeon_vm_evict(struct radeon_device *rdev, struct radeon_vm *vm)
+static int radeon_vm_evict(struct radeon_device *rdev, struct radeon_vm *vm)
 {
        struct radeon_vm *vm_evict;
 
@@ -1036,8 +1035,7 @@ static void radeon_vm_update_ptes(struct radeon_device *rdev,
                pte = radeon_sa_bo_gpu_addr(vm->page_tables[pt_idx]);
                pte += (addr & mask) * 8;
 
-               if (((last_pte + 8 * count) != pte) ||
-                   ((count + nptes) > 1 << 11)) {
+               if ((last_pte + 8 * count) != pte) {
 
                        if (count) {
                                radeon_asic_vm_set_page(rdev, last_pte,
@@ -1148,17 +1146,17 @@ int radeon_vm_bo_update_pte(struct radeon_device *rdev,
 
        if (RADEON_VM_BLOCK_SIZE > 11)
                /* reserve space for one header for every 2k dwords */
-               ndw += (nptes >> 11) * 3;
+               ndw += (nptes >> 11) * 4;
        else
                /* reserve space for one header for
                    every (1 << BLOCK_SIZE) entries */
-               ndw += (nptes >> RADEON_VM_BLOCK_SIZE) * 3;
+               ndw += (nptes >> RADEON_VM_BLOCK_SIZE) * 4;
 
        /* reserve space for pte addresses */
        ndw += nptes * 2;
 
        /* reserve space for one header for every 2k dwords */
-       ndw += (npdes >> 11) * 3;
+       ndw += (npdes >> 11) * 4;
 
        /* reserve space for pde addresses */
        ndw += npdes * 2;
index f38fbcc469358a2144791d40f910d4d900d99202..fe5c1f6b795795530075939d39c06486ce42d29d 100644 (file)
@@ -53,6 +53,7 @@ int radeon_gem_object_create(struct radeon_device *rdev, int size,
                                struct drm_gem_object **obj)
 {
        struct radeon_bo *robj;
+       unsigned long max_size;
        int r;
 
        *obj = NULL;
@@ -60,11 +61,26 @@ int radeon_gem_object_create(struct radeon_device *rdev, int size,
        if (alignment < PAGE_SIZE) {
                alignment = PAGE_SIZE;
        }
+
+       /* maximun bo size is the minimun btw visible vram and gtt size */
+       max_size = min(rdev->mc.visible_vram_size, rdev->mc.gtt_size);
+       if (size > max_size) {
+               printk(KERN_WARNING "%s:%d alloc size %dMb bigger than %ldMb limit\n",
+                      __func__, __LINE__, size >> 20, max_size >> 20);
+               return -ENOMEM;
+       }
+
+retry:
        r = radeon_bo_create(rdev, size, alignment, kernel, initial_domain, NULL, &robj);
        if (r) {
-               if (r != -ERESTARTSYS)
+               if (r != -ERESTARTSYS) {
+                       if (initial_domain == RADEON_GEM_DOMAIN_VRAM) {
+                               initial_domain |= RADEON_GEM_DOMAIN_GTT;
+                               goto retry;
+                       }
                        DRM_ERROR("Failed to allocate GEM object (%d, %d, %u, %d)\n",
                                  size, initial_domain, alignment, r);
+               }
                return r;
        }
        *obj = &robj->gem_base;
index 5677a424b58535e2bffb0422856e9385182b649c..6857cb4efb768c932f23d4645c3969fd9c792f18 100644 (file)
@@ -295,6 +295,7 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
        struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
        struct drm_device *dev = crtc->dev;
        struct radeon_device *rdev = dev->dev_private;
+       uint32_t crtc_ext_cntl = 0;
        uint32_t mask;
 
        if (radeon_crtc->crtc_id)
@@ -307,6 +308,16 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
                        RADEON_CRTC_VSYNC_DIS |
                        RADEON_CRTC_HSYNC_DIS);
 
+       /*
+        * On all dual CRTC GPUs this bit controls the CRTC of the primary DAC.
+        * Therefore it is set in the DAC DMPS function.
+        * This is different for GPU's with a single CRTC but a primary and a
+        * TV DAC: here it controls the single CRTC no matter where it is
+        * routed. Therefore we set it here.
+        */
+       if (rdev->flags & RADEON_SINGLE_CRTC)
+               crtc_ext_cntl = RADEON_CRTC_CRT_ON;
+       
        switch (mode) {
        case DRM_MODE_DPMS_ON:
                radeon_crtc->enabled = true;
@@ -317,7 +328,7 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
                else {
                        WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_EN, ~(RADEON_CRTC_EN |
                                                                         RADEON_CRTC_DISP_REQ_EN_B));
-                       WREG32_P(RADEON_CRTC_EXT_CNTL, 0, ~mask);
+                       WREG32_P(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl, ~(mask | crtc_ext_cntl));
                }
                drm_vblank_post_modeset(dev, radeon_crtc->crtc_id);
                radeon_crtc_load_lut(crtc);
@@ -331,7 +342,7 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
                else {
                        WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_DISP_REQ_EN_B, ~(RADEON_CRTC_EN |
                                                                                    RADEON_CRTC_DISP_REQ_EN_B));
-                       WREG32_P(RADEON_CRTC_EXT_CNTL, mask, ~mask);
+                       WREG32_P(RADEON_CRTC_EXT_CNTL, mask, ~(mask | crtc_ext_cntl));
                }
                radeon_crtc->enabled = false;
                /* adjust pm to dpms changes AFTER disabling crtcs */
index a13ad9d707cfcccdab04d085a62d4be0ab3690df..f5ba2241dacc6cfd2bb6b55fead51a7ae2c395e8 100644 (file)
@@ -370,6 +370,7 @@ void radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder,
        struct backlight_properties props;
        struct radeon_backlight_privdata *pdata;
        uint8_t backlight_level;
+       char bl_name[16];
 
        if (!radeon_encoder->enc_priv)
                return;
@@ -389,7 +390,9 @@ void radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder,
        memset(&props, 0, sizeof(props));
        props.max_brightness = RADEON_MAX_BL_LEVEL;
        props.type = BACKLIGHT_RAW;
-       bd = backlight_device_register("radeon_bl", &drm_connector->kdev,
+       snprintf(bl_name, sizeof(bl_name),
+                "radeon_bl%d", dev->primary->index);
+       bd = backlight_device_register(bl_name, &drm_connector->kdev,
                                       pdata, &radeon_backlight_ops, &props);
        if (IS_ERR(bd)) {
                DRM_ERROR("Backlight registration failed\n");
@@ -534,7 +537,9 @@ static void radeon_legacy_primary_dac_dpms(struct drm_encoder *encoder, int mode
                break;
        }
 
-       WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
+       /* handled in radeon_crtc_dpms() */
+       if (!(rdev->flags & RADEON_SINGLE_CRTC))
+               WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
        WREG32(RADEON_DAC_CNTL, dac_cntl);
        WREG32(RADEON_DAC_MACRO_CNTL, dac_macro_cntl);
 
@@ -659,6 +664,8 @@ static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_enc
 
        if (ASIC_IS_R300(rdev))
                tmp |= (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT);
+       else if (ASIC_IS_RV100(rdev))
+               tmp |= (0x1ac << RADEON_DAC_FORCE_DATA_SHIFT);
        else
                tmp |= (0x180 << RADEON_DAC_FORCE_DATA_SHIFT);
 
@@ -668,6 +675,7 @@ static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_enc
        tmp |= RADEON_DAC_RANGE_CNTL_PS2 | RADEON_DAC_CMP_EN;
        WREG32(RADEON_DAC_CNTL, tmp);
 
+       tmp = dac_macro_cntl;
        tmp &= ~(RADEON_DAC_PDWN_R |
                 RADEON_DAC_PDWN_G |
                 RADEON_DAC_PDWN_B);
@@ -1089,7 +1097,8 @@ static void radeon_legacy_tv_dac_dpms(struct drm_encoder *encoder, int mode)
        } else {
                if (is_tv)
                        WREG32(RADEON_TV_MASTER_CNTL, tv_master_cntl);
-               else
+               /* handled in radeon_crtc_dpms() */
+               else if (!(rdev->flags & RADEON_SINGLE_CRTC))
                        WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
                WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
        }
@@ -1413,13 +1422,104 @@ static bool radeon_legacy_tv_detect(struct drm_encoder *encoder,
        return found;
 }
 
+static bool radeon_legacy_ext_dac_detect(struct drm_encoder *encoder,
+                                        struct drm_connector *connector)
+{
+       struct drm_device *dev = encoder->dev;
+       struct radeon_device *rdev = dev->dev_private;
+       uint32_t gpio_monid, fp2_gen_cntl, disp_output_cntl, crtc2_gen_cntl;
+       uint32_t disp_lin_trans_grph_a, disp_lin_trans_grph_b, disp_lin_trans_grph_c;
+       uint32_t disp_lin_trans_grph_d, disp_lin_trans_grph_e, disp_lin_trans_grph_f;
+       uint32_t tmp, crtc2_h_total_disp, crtc2_v_total_disp;
+       uint32_t crtc2_h_sync_strt_wid, crtc2_v_sync_strt_wid;
+       bool found = false;
+       int i;
+
+       /* save the regs we need */
+       gpio_monid = RREG32(RADEON_GPIO_MONID);
+       fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
+       disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL);
+       crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
+       disp_lin_trans_grph_a = RREG32(RADEON_DISP_LIN_TRANS_GRPH_A);
+       disp_lin_trans_grph_b = RREG32(RADEON_DISP_LIN_TRANS_GRPH_B);
+       disp_lin_trans_grph_c = RREG32(RADEON_DISP_LIN_TRANS_GRPH_C);
+       disp_lin_trans_grph_d = RREG32(RADEON_DISP_LIN_TRANS_GRPH_D);
+       disp_lin_trans_grph_e = RREG32(RADEON_DISP_LIN_TRANS_GRPH_E);
+       disp_lin_trans_grph_f = RREG32(RADEON_DISP_LIN_TRANS_GRPH_F);
+       crtc2_h_total_disp = RREG32(RADEON_CRTC2_H_TOTAL_DISP);
+       crtc2_v_total_disp = RREG32(RADEON_CRTC2_V_TOTAL_DISP);
+       crtc2_h_sync_strt_wid = RREG32(RADEON_CRTC2_H_SYNC_STRT_WID);
+       crtc2_v_sync_strt_wid = RREG32(RADEON_CRTC2_V_SYNC_STRT_WID);
+
+       tmp = RREG32(RADEON_GPIO_MONID);
+       tmp &= ~RADEON_GPIO_A_0;
+       WREG32(RADEON_GPIO_MONID, tmp);
+
+       WREG32(RADEON_FP2_GEN_CNTL, (RADEON_FP2_ON |
+                                    RADEON_FP2_PANEL_FORMAT |
+                                    R200_FP2_SOURCE_SEL_TRANS_UNIT |
+                                    RADEON_FP2_DVO_EN |
+                                    R200_FP2_DVO_RATE_SEL_SDR));
+
+       WREG32(RADEON_DISP_OUTPUT_CNTL, (RADEON_DISP_DAC_SOURCE_RMX |
+                                        RADEON_DISP_TRANS_MATRIX_GRAPHICS));
+
+       WREG32(RADEON_CRTC2_GEN_CNTL, (RADEON_CRTC2_EN |
+                                      RADEON_CRTC2_DISP_REQ_EN_B));
+
+       WREG32(RADEON_DISP_LIN_TRANS_GRPH_A, 0x00000000);
+       WREG32(RADEON_DISP_LIN_TRANS_GRPH_B, 0x000003f0);
+       WREG32(RADEON_DISP_LIN_TRANS_GRPH_C, 0x00000000);
+       WREG32(RADEON_DISP_LIN_TRANS_GRPH_D, 0x000003f0);
+       WREG32(RADEON_DISP_LIN_TRANS_GRPH_E, 0x00000000);
+       WREG32(RADEON_DISP_LIN_TRANS_GRPH_F, 0x000003f0);
+
+       WREG32(RADEON_CRTC2_H_TOTAL_DISP, 0x01000008);
+       WREG32(RADEON_CRTC2_H_SYNC_STRT_WID, 0x00000800);
+       WREG32(RADEON_CRTC2_V_TOTAL_DISP, 0x00080001);
+       WREG32(RADEON_CRTC2_V_SYNC_STRT_WID, 0x00000080);
+
+       for (i = 0; i < 200; i++) {
+               tmp = RREG32(RADEON_GPIO_MONID);
+               if (tmp & RADEON_GPIO_Y_0)
+                       found = true;
+
+               if (found)
+                       break;
+
+               if (!drm_can_sleep())
+                       mdelay(1);
+               else
+                       msleep(1);
+       }
+
+       /* restore the regs we used */
+       WREG32(RADEON_DISP_LIN_TRANS_GRPH_A, disp_lin_trans_grph_a);
+       WREG32(RADEON_DISP_LIN_TRANS_GRPH_B, disp_lin_trans_grph_b);
+       WREG32(RADEON_DISP_LIN_TRANS_GRPH_C, disp_lin_trans_grph_c);
+       WREG32(RADEON_DISP_LIN_TRANS_GRPH_D, disp_lin_trans_grph_d);
+       WREG32(RADEON_DISP_LIN_TRANS_GRPH_E, disp_lin_trans_grph_e);
+       WREG32(RADEON_DISP_LIN_TRANS_GRPH_F, disp_lin_trans_grph_f);
+       WREG32(RADEON_CRTC2_H_TOTAL_DISP, crtc2_h_total_disp);
+       WREG32(RADEON_CRTC2_V_TOTAL_DISP, crtc2_v_total_disp);
+       WREG32(RADEON_CRTC2_H_SYNC_STRT_WID, crtc2_h_sync_strt_wid);
+       WREG32(RADEON_CRTC2_V_SYNC_STRT_WID, crtc2_v_sync_strt_wid);
+       WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
+       WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
+       WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
+       WREG32(RADEON_GPIO_MONID, gpio_monid);
+
+       return found;
+}
+
 static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder *encoder,
                                                             struct drm_connector *connector)
 {
        struct drm_device *dev = encoder->dev;
        struct radeon_device *rdev = dev->dev_private;
-       uint32_t crtc2_gen_cntl, tv_dac_cntl, dac_cntl2, dac_ext_cntl;
-       uint32_t disp_hw_debug, disp_output_cntl, gpiopad_a, pixclks_cntl, tmp;
+       uint32_t crtc2_gen_cntl = 0, tv_dac_cntl, dac_cntl2, dac_ext_cntl;
+       uint32_t gpiopad_a = 0, pixclks_cntl, tmp;
+       uint32_t disp_output_cntl = 0, disp_hw_debug = 0, crtc_ext_cntl = 0;
        enum drm_connector_status found = connector_status_disconnected;
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
        struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
@@ -1456,12 +1556,27 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder
                return connector_status_disconnected;
        }
 
+       /* R200 uses an external DAC for secondary DAC */
+       if (rdev->family == CHIP_R200) {
+               if (radeon_legacy_ext_dac_detect(encoder, connector))
+                       found = connector_status_connected;
+               return found;
+       }
+
        /* save the regs we need */
        pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL);
-       gpiopad_a = ASIC_IS_R300(rdev) ? RREG32(RADEON_GPIOPAD_A) : 0;
-       disp_output_cntl = ASIC_IS_R300(rdev) ? RREG32(RADEON_DISP_OUTPUT_CNTL) : 0;
-       disp_hw_debug = ASIC_IS_R300(rdev) ? 0 : RREG32(RADEON_DISP_HW_DEBUG);
-       crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
+
+       if (rdev->flags & RADEON_SINGLE_CRTC) {
+               crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL);
+       } else {
+               if (ASIC_IS_R300(rdev)) {
+                       gpiopad_a = RREG32(RADEON_GPIOPAD_A);
+                       disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL);
+               } else {
+                       disp_hw_debug = RREG32(RADEON_DISP_HW_DEBUG);
+               }
+               crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
+       }
        tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
        dac_ext_cntl = RREG32(RADEON_DAC_EXT_CNTL);
        dac_cntl2 = RREG32(RADEON_DAC_CNTL2);
@@ -1470,22 +1585,24 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder
                               | RADEON_PIX2CLK_DAC_ALWAYS_ONb);
        WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp);
 
-       if (ASIC_IS_R300(rdev))
-               WREG32_P(RADEON_GPIOPAD_A, 1, ~1);
-
-       tmp = crtc2_gen_cntl & ~RADEON_CRTC2_PIX_WIDTH_MASK;
-       tmp |= RADEON_CRTC2_CRT2_ON |
-               (2 << RADEON_CRTC2_PIX_WIDTH_SHIFT);
-
-       WREG32(RADEON_CRTC2_GEN_CNTL, tmp);
-
-       if (ASIC_IS_R300(rdev)) {
-               tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK;
-               tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2;
-               WREG32(RADEON_DISP_OUTPUT_CNTL, tmp);
+       if (rdev->flags & RADEON_SINGLE_CRTC) {
+               tmp = crtc_ext_cntl | RADEON_CRTC_CRT_ON;
+               WREG32(RADEON_CRTC_EXT_CNTL, tmp);
        } else {
-               tmp = disp_hw_debug & ~RADEON_CRT2_DISP1_SEL;
-               WREG32(RADEON_DISP_HW_DEBUG, tmp);
+               tmp = crtc2_gen_cntl & ~RADEON_CRTC2_PIX_WIDTH_MASK;
+               tmp |= RADEON_CRTC2_CRT2_ON |
+                       (2 << RADEON_CRTC2_PIX_WIDTH_SHIFT);
+               WREG32(RADEON_CRTC2_GEN_CNTL, tmp);
+
+               if (ASIC_IS_R300(rdev)) {
+                       WREG32_P(RADEON_GPIOPAD_A, 1, ~1);
+                       tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK;
+                       tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2;
+                       WREG32(RADEON_DISP_OUTPUT_CNTL, tmp);
+               } else {
+                       tmp = disp_hw_debug & ~RADEON_CRT2_DISP1_SEL;
+                       WREG32(RADEON_DISP_HW_DEBUG, tmp);
+               }
        }
 
        tmp = RADEON_TV_DAC_NBLANK |
@@ -1527,14 +1644,19 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder
        WREG32(RADEON_DAC_CNTL2, dac_cntl2);
        WREG32(RADEON_DAC_EXT_CNTL, dac_ext_cntl);
        WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
-       WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
 
-       if (ASIC_IS_R300(rdev)) {
-               WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
-               WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1);
+       if (rdev->flags & RADEON_SINGLE_CRTC) {
+               WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
        } else {
-               WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug);
+               WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
+               if (ASIC_IS_R300(rdev)) {
+                       WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
+                       WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1);
+               } else {
+                       WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug);
+               }
        }
+
        WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl);
 
        return found;
index 8b27dd6e3144566bf9cfcb218f4697cd92dbbb95..b91118ccef867f5b59effd78d0ee93d65a932f8b 100644 (file)
@@ -105,7 +105,6 @@ int radeon_bo_create(struct radeon_device *rdev,
        struct radeon_bo *bo;
        enum ttm_bo_type type;
        unsigned long page_align = roundup(byte_align, PAGE_SIZE) >> PAGE_SHIFT;
-       unsigned long max_size = 0;
        size_t acc_size;
        int r;
 
@@ -121,18 +120,9 @@ int radeon_bo_create(struct radeon_device *rdev,
        }
        *bo_ptr = NULL;
 
-       /* maximun bo size is the minimun btw visible vram and gtt size */
-       max_size = min(rdev->mc.visible_vram_size, rdev->mc.gtt_size);
-       if ((page_align << PAGE_SHIFT) >= max_size) {
-               printk(KERN_WARNING "%s:%d alloc size %ldM bigger than %ldMb limit\n",
-                       __func__, __LINE__, page_align  >> (20 - PAGE_SHIFT), max_size >> 20);
-               return -ENOMEM;
-       }
-
        acc_size = ttm_bo_dma_acc_size(&rdev->mman.bdev, size,
                                       sizeof(struct radeon_bo));
 
-retry:
        bo = kzalloc(sizeof(struct radeon_bo), GFP_KERNEL);
        if (bo == NULL)
                return -ENOMEM;
@@ -154,15 +144,6 @@ retry:
                        acc_size, sg, &radeon_ttm_bo_destroy);
        up_read(&rdev->pm.mclk_lock);
        if (unlikely(r != 0)) {
-               if (r != -ERESTARTSYS) {
-                       if (domain == RADEON_GEM_DOMAIN_VRAM) {
-                               domain |= RADEON_GEM_DOMAIN_GTT;
-                               goto retry;
-                       }
-                       dev_err(rdev->dev,
-                               "object_init failed for (%lu, 0x%08X)\n",
-                               size, domain);
-               }
                return r;
        }
        *bo_ptr = bo;
index df8dd77016436373dcfcfce4e3fb3e8410a3d873..4422d630b33bc4052ddfdc311ea37944f9d87051 100644 (file)
@@ -2474,6 +2474,7 @@ static bool si_vm_reg_valid(u32 reg)
        /* check config regs */
        switch (reg) {
        case GRBM_GFX_INDEX:
+       case CP_STRMOUT_CNTL:
        case VGT_VTX_VECT_EJECT_REG:
        case VGT_CACHE_INVALIDATION:
        case VGT_ESGS_RING_SIZE:
@@ -2808,26 +2809,31 @@ void si_vm_set_page(struct radeon_device *rdev, uint64_t pe,
 {
        struct radeon_ring *ring = &rdev->ring[rdev->asic->vm.pt_ring_index];
        uint32_t r600_flags = cayman_vm_page_flags(rdev, flags);
-       int i;
-       uint64_t value;
 
-       radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 2 + count * 2));
-       radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
-                                WRITE_DATA_DST_SEL(1)));
-       radeon_ring_write(ring, pe);
-       radeon_ring_write(ring, upper_32_bits(pe));
-       for (i = 0; i < count; ++i) {
-               if (flags & RADEON_VM_PAGE_SYSTEM) {
-                       value = radeon_vm_map_gart(rdev, addr);
-                       value &= 0xFFFFFFFFFFFFF000ULL;
-               } else if (flags & RADEON_VM_PAGE_VALID)
-                       value = addr;
-               else
-                       value = 0;
-               addr += incr;
-               value |= r600_flags;
-               radeon_ring_write(ring, value);
-               radeon_ring_write(ring, upper_32_bits(value));
+       while (count) {
+               unsigned ndw = 2 + count * 2;
+               if (ndw > 0x3FFE)
+                       ndw = 0x3FFE;
+
+               radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, ndw));
+               radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
+                                        WRITE_DATA_DST_SEL(1)));
+               radeon_ring_write(ring, pe);
+               radeon_ring_write(ring, upper_32_bits(pe));
+               for (; ndw > 2; ndw -= 2, --count, pe += 8) {
+                       uint64_t value;
+                       if (flags & RADEON_VM_PAGE_SYSTEM) {
+                               value = radeon_vm_map_gart(rdev, addr);
+                               value &= 0xFFFFFFFFFFFFF000ULL;
+                       } else if (flags & RADEON_VM_PAGE_VALID)
+                               value = addr;
+                       else
+                               value = 0;
+                       addr += incr;
+                       value |= r600_flags;
+                       radeon_ring_write(ring, value);
+                       radeon_ring_write(ring, upper_32_bits(value));
+               }
        }
 }
 
@@ -2868,6 +2874,10 @@ void si_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm)
        radeon_ring_write(ring, VM_INVALIDATE_REQUEST >> 2);
        radeon_ring_write(ring, 0);
        radeon_ring_write(ring, 1 << vm->id);
+
+       /* sync PFP to ME, otherwise we might get invalid PFP reads */
+       radeon_ring_write(ring, PACKET3(PACKET3_PFP_SYNC_ME, 0));
+       radeon_ring_write(ring, 0x0);
 }
 
 /*
index 7d2a20e565771366a09124386a3ac513b66f8613..a8871afc5b4e6af2f13599bbed34a2cfd05eec36 100644 (file)
 #       define RDERR_INT_ENABLE                         (1 << 0)
 #       define GUI_IDLE_INT_ENABLE                      (1 << 19)
 
+#define        CP_STRMOUT_CNTL                                 0x84FC
 #define        SCRATCH_REG0                                    0x8500
 #define        SCRATCH_REG1                                    0x8504
 #define        SCRATCH_REG2                                    0x8508
index c71d493fd0c54fc184023428bdcbfb286d2d1109..1c350fc4e449715edd5ef997e6eb791722d0f604 100644 (file)
@@ -201,6 +201,8 @@ static int shmob_drm_load(struct drm_device *dev, unsigned long flags)
                goto done;
        }
 
+       platform_set_drvdata(pdev, sdev);
+
 done:
        if (ret)
                shmob_drm_unload(dev);
@@ -299,11 +301,9 @@ static struct drm_driver shmob_drm_driver = {
 #if CONFIG_PM_SLEEP
 static int shmob_drm_pm_suspend(struct device *dev)
 {
-       struct platform_device *pdev = to_platform_device(dev);
-       struct drm_device *ddev = platform_get_drvdata(pdev);
-       struct shmob_drm_device *sdev = ddev->dev_private;
+       struct shmob_drm_device *sdev = dev_get_drvdata(dev);
 
-       drm_kms_helper_poll_disable(ddev);
+       drm_kms_helper_poll_disable(sdev->ddev);
        shmob_drm_crtc_suspend(&sdev->crtc);
 
        return 0;
@@ -311,9 +311,7 @@ static int shmob_drm_pm_suspend(struct device *dev)
 
 static int shmob_drm_pm_resume(struct device *dev)
 {
-       struct platform_device *pdev = to_platform_device(dev);
-       struct drm_device *ddev = platform_get_drvdata(pdev);
-       struct shmob_drm_device *sdev = ddev->dev_private;
+       struct shmob_drm_device *sdev = dev_get_drvdata(dev);
 
        mutex_lock(&sdev->ddev->mode_config.mutex);
        shmob_drm_crtc_resume(&sdev->crtc);
index 402ab69f9f991c64d149841cc154d6ea86ae9a96..bf6e4b5a73b509a73d06873c213335158b5fff89 100644 (file)
@@ -580,6 +580,7 @@ retry:
        if (unlikely(ret != 0))
                return ret;
 
+retry_reserve:
        spin_lock(&glob->lru_lock);
 
        if (unlikely(list_empty(&bo->ddestroy))) {
@@ -587,14 +588,20 @@ retry:
                return 0;
        }
 
-       ret = ttm_bo_reserve_locked(bo, interruptible,
-                                   no_wait_reserve, false, 0);
+       ret = ttm_bo_reserve_locked(bo, false, true, false, 0);
 
-       if (unlikely(ret != 0)) {
+       if (unlikely(ret == -EBUSY)) {
                spin_unlock(&glob->lru_lock);
-               return ret;
+               if (likely(!no_wait_reserve))
+                       ret = ttm_bo_wait_unreserved(bo, interruptible);
+               if (unlikely(ret != 0))
+                       return ret;
+
+               goto retry_reserve;
        }
 
+       BUG_ON(ret != 0);
+
        /**
         * We can re-check for sync object without taking
         * the bo::lock since setting the sync object requires
@@ -811,17 +818,14 @@ retry:
                                          no_wait_reserve, no_wait_gpu);
                kref_put(&bo->list_kref, ttm_bo_release_list);
 
-               if (likely(ret == 0 || ret == -ERESTARTSYS))
-                       return ret;
-
-               goto retry;
+               return ret;
        }
 
-       ret = ttm_bo_reserve_locked(bo, false, no_wait_reserve, false, 0);
+       ret = ttm_bo_reserve_locked(bo, false, true, false, 0);
 
        if (unlikely(ret == -EBUSY)) {
                spin_unlock(&glob->lru_lock);
-               if (likely(!no_wait_gpu))
+               if (likely(!no_wait_reserve))
                        ret = ttm_bo_wait_unreserved(bo, interruptible);
 
                kref_put(&bo->list_kref, ttm_bo_release_list);
index 860dc4813e9991fe67754333ad487686605a7b26..bd2a3b40cd129b30d4445a8cdca8adec2eb492f9 100644 (file)
@@ -749,7 +749,10 @@ static int ttm_get_pages(struct page **pages, unsigned npages, int flags,
        /* clear the pages coming from the pool if requested */
        if (flags & TTM_PAGE_FLAG_ZERO_ALLOC) {
                list_for_each_entry(p, &plist, lru) {
-                       clear_page(page_address(p));
+                       if (PageHighMem(p))
+                               clear_highpage(p);
+                       else
+                               clear_page(page_address(p));
                }
        }
 
index bf8260133ea9dc2cd6058118864cd481fbe8dcff..7d759a4302943bb6c5904356dd9e81dec6d4588f 100644 (file)
@@ -308,9 +308,7 @@ int ttm_tt_swapin(struct ttm_tt *ttm)
                if (unlikely(to_page == NULL))
                        goto out_err;
 
-               preempt_disable();
                copy_highpage(to_page, from_page);
-               preempt_enable();
                page_cache_release(from_page);
        }
 
@@ -358,9 +356,7 @@ int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistent_swap_storage)
                        ret = PTR_ERR(to_page);
                        goto out_err;
                }
-               preempt_disable();
                copy_highpage(to_page, from_page);
-               preempt_enable();
                set_page_dirty(to_page);
                mark_page_accessed(to_page);
                page_cache_release(to_page);
index fccd361f7b50b4e4d4bd072afac3f32869da3da7..87aa5f5d3c88657b8c55055608a65baa271c4c94 100644 (file)
@@ -104,7 +104,7 @@ udl_fb_user_fb_create(struct drm_device *dev,
 
 int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr,
                     const char *front, char **urb_buf_ptr,
-                    u32 byte_offset, u32 byte_width,
+                    u32 byte_offset, u32 device_byte_offset, u32 byte_width,
                     int *ident_ptr, int *sent_ptr);
 
 int udl_dumb_create(struct drm_file *file_priv,
index 69a2b16f42a60284d2d8eecb8ae1fe01fe8e2ced..d4ab3beaada027825d6182a1330b79bd75d220d4 100644 (file)
@@ -114,9 +114,10 @@ static void udlfb_dpy_deferred_io(struct fb_info *info,
        list_for_each_entry(cur, &fbdefio->pagelist, lru) {
 
                if (udl_render_hline(dev, (ufbdev->ufb.base.bits_per_pixel / 8),
-                                 &urb, (char *) info->fix.smem_start,
-                                 &cmd, cur->index << PAGE_SHIFT,
-                                 PAGE_SIZE, &bytes_identical, &bytes_sent))
+                                    &urb, (char *) info->fix.smem_start,
+                                    &cmd, cur->index << PAGE_SHIFT,
+                                    cur->index << PAGE_SHIFT,
+                                    PAGE_SIZE, &bytes_identical, &bytes_sent))
                        goto error;
                bytes_rendered += PAGE_SIZE;
        }
@@ -187,10 +188,11 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y,
        for (i = y; i < y + height ; i++) {
                const int line_offset = fb->base.pitches[0] * i;
                const int byte_offset = line_offset + (x * bpp);
-
+               const int dev_byte_offset = (fb->base.width * bpp * i) + (x * bpp);
                if (udl_render_hline(dev, bpp, &urb,
                                     (char *) fb->obj->vmapping,
-                                    &cmd, byte_offset, width * bpp,
+                                    &cmd, byte_offset, dev_byte_offset,
+                                    width * bpp,
                                     &bytes_identical, &bytes_sent))
                        goto error;
        }
index dc095526ffb750124573b9c2a9e472a4bbe82101..142fee5f983f9aa36c8fff99b3ddaf4d4eba78cd 100644 (file)
@@ -213,11 +213,12 @@ static void udl_compress_hline16(
  */
 int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr,
                     const char *front, char **urb_buf_ptr,
-                    u32 byte_offset, u32 byte_width,
+                    u32 byte_offset, u32 device_byte_offset,
+                    u32 byte_width,
                     int *ident_ptr, int *sent_ptr)
 {
        const u8 *line_start, *line_end, *next_pixel;
-       u32 base16 = 0 + (byte_offset / bpp) * 2;
+       u32 base16 = 0 + (device_byte_offset / bpp) * 2;
        struct urb *urb = *urb_ptr;
        u8 *cmd = *urb_buf_ptr;
        u8 *cmd_end = (u8 *) urb->transfer_buffer + urb->transfer_buffer_length;
index 3ce68a2e312dbba2e588a3e52595b0d7f060ef44..d1498bfd78732ef519f50d6fea726d502cffd824 100644 (file)
@@ -306,7 +306,7 @@ void vmw_bo_pin(struct ttm_buffer_object *bo, bool pin)
 
        BUG_ON(!atomic_read(&bo->reserved));
        BUG_ON(old_mem_type != TTM_PL_VRAM &&
-              old_mem_type != VMW_PL_FLAG_GMR);
+              old_mem_type != VMW_PL_GMR);
 
        pl_flags = TTM_PL_FLAG_VRAM | VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED;
        if (pin)
index ed3c1e7ddde94cde6db31c1e09b3174364eb9d22..2dd185e42f2129c8492021050e8ba149890cfbfd 100644 (file)
@@ -1098,6 +1098,11 @@ static void vmw_pm_complete(struct device *kdev)
        struct drm_device *dev = pci_get_drvdata(pdev);
        struct vmw_private *dev_priv = vmw_priv(dev);
 
+       mutex_lock(&dev_priv->hw_mutex);
+       vmw_write(dev_priv, SVGA_REG_ID, SVGA_ID_2);
+       (void) vmw_read(dev_priv, SVGA_REG_ID);
+       mutex_unlock(&dev_priv->hw_mutex);
+
        /**
         * Reclaim 3d reference held by fbdev and potentially
         * start fifo.
index b07ca2e4d04b5852c6b59438aaae27bbe478acd2..7290811f89bef5956019f90acc59f543206e49e7 100644 (file)
@@ -110,6 +110,8 @@ int vmw_get_cap_3d_ioctl(struct drm_device *dev, void *data,
        memcpy_fromio(bounce, &fifo_mem[SVGA_FIFO_3D_CAPS], size);
 
        ret = copy_to_user(buffer, bounce, size);
+       if (ret)
+               ret = -EFAULT;
        vfree(bounce);
 
        if (unlikely(ret != 0))
index 06ebdbb6ea0207f8d92d691d15c00434f4fab21a..fd7722aecf77929eea158263af6cc1b601287408 100644 (file)
@@ -522,6 +522,12 @@ static const struct hid_device_id apple_devices[] = {
                .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS),
                .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI),
+               .driver_data = APPLE_HAS_FN },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO),
+               .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS),
+               .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI),
                .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO),
index bd3971bf31bf7bc4369911a648b02c8729a3004d..f4109fd657ff7a337761f9029969dde8ee71e3cc 100644 (file)
@@ -1532,6 +1532,9 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ISO) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) },
@@ -2139,6 +2142,9 @@ static const struct hid_device_id hid_mouse_ignore_list[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ISO) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
        { }
index 269b50912a4ae9207d1d04f2e014b3c950f20324..9d7a42857ea190a9b9fbc12582582b8ae97ebd2a 100644 (file)
 #define USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI  0x0252
 #define USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO   0x0253
 #define USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS   0x0254
+#define USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI  0x0259
+#define USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO   0x025a
+#define USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS   0x025b
 #define USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI  0x0249
 #define USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO   0x024a
 #define USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS   0x024b
index 3acdcfcc17df24f696ed7b440f6a29540456e33e..6fcd466d082512f675d027aafd7600eb34edebaf 100644 (file)
 #define MS_RDESC               0x08
 #define MS_NOGET               0x10
 #define MS_DUPLICATE_USAGES    0x20
+#define MS_RDESC_3K            0x40
 
-/*
- * Microsoft Wireless Desktop Receiver (Model 1028) has
- * 'Usage Min/Max' where it ought to have 'Physical Min/Max'
- */
 static __u8 *ms_report_fixup(struct hid_device *hdev, __u8 *rdesc,
                unsigned int *rsize)
 {
        unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
 
+       /*
+        * Microsoft Wireless Desktop Receiver (Model 1028) has
+        * 'Usage Min/Max' where it ought to have 'Physical Min/Max'
+        */
        if ((quirks & MS_RDESC) && *rsize == 571 && rdesc[557] == 0x19 &&
                        rdesc[559] == 0x29) {
                hid_info(hdev, "fixing up Microsoft Wireless Receiver Model 1028 report descriptor\n");
                rdesc[557] = 0x35;
                rdesc[559] = 0x45;
        }
+       /* the same as above (s/usage/physical/) */
+       if ((quirks & MS_RDESC_3K) && *rsize == 106 && rdesc[94] == 0x19 &&
+                       rdesc[95] == 0x00 && rdesc[96] == 0x29 &&
+                       rdesc[97] == 0xff) {
+               rdesc[94] = 0x35;
+               rdesc[96] = 0x45;
+       }
        return rdesc;
 }
 
@@ -192,7 +200,7 @@ static const struct hid_device_id ms_devices[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB),
                .driver_data = MS_PRESENTER },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K),
-               .driver_data = MS_ERGONOMY },
+               .driver_data = MS_ERGONOMY | MS_RDESC_3K },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0),
                .driver_data = MS_NOGET },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500),
index 3eb02b94fc87c8a3bc903474db7c3b55efd5ead5..7867d69f0efe1cd734c57e7e4627eb9aaf7a367e 100644 (file)
@@ -210,8 +210,7 @@ static struct mt_class mt_classes[] = {
        },
        { .name = MT_CLS_GENERALTOUCH_PWT_TENFINGERS,
                .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP |
-                       MT_QUIRK_SLOT_IS_CONTACTNUMBER,
-               .maxcontacts = 10
+                       MT_QUIRK_SLOT_IS_CONTACTNUMBER
        },
 
        { .name = MT_CLS_FLATFROG,
@@ -421,11 +420,11 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
                         * contact max are global to the report */
                        td->last_field_index = field->index;
                        return -1;
-               }
                case HID_DG_TOUCH:
                        /* Legacy devices use TIPSWITCH and not TOUCH.
                         * Let's just ignore this field. */
                        return -1;
+               }
                /* let hid-input decide for the others */
                return 0;
 
index 17d15bb610d15ac4b544e11af3007cd5b6357fd8..7c47fc3f7b2b0b28f27021c75bb3b8d8f3771c4d 100644 (file)
@@ -42,7 +42,6 @@ static struct cdev hidraw_cdev;
 static struct class *hidraw_class;
 static struct hidraw *hidraw_table[HIDRAW_MAX_DEVICES];
 static DEFINE_MUTEX(minors_lock);
-static void drop_ref(struct hidraw *hid, int exists_bit);
 
 static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
 {
@@ -114,7 +113,7 @@ static ssize_t hidraw_send_report(struct file *file, const char __user *buffer,
        __u8 *buf;
        int ret = 0;
 
-       if (!hidraw_table[minor] || !hidraw_table[minor]->exist) {
+       if (!hidraw_table[minor]) {
                ret = -ENODEV;
                goto out;
        }
@@ -262,7 +261,7 @@ static int hidraw_open(struct inode *inode, struct file *file)
        }
 
        mutex_lock(&minors_lock);
-       if (!hidraw_table[minor] || !hidraw_table[minor]->exist) {
+       if (!hidraw_table[minor]) {
                err = -ENODEV;
                goto out_unlock;
        }
@@ -299,12 +298,36 @@ out:
 static int hidraw_release(struct inode * inode, struct file * file)
 {
        unsigned int minor = iminor(inode);
+       struct hidraw *dev;
        struct hidraw_list *list = file->private_data;
+       int ret;
+       int i;
+
+       mutex_lock(&minors_lock);
+       if (!hidraw_table[minor]) {
+               ret = -ENODEV;
+               goto unlock;
+       }
 
-       drop_ref(hidraw_table[minor], 0);
        list_del(&list->node);
+       dev = hidraw_table[minor];
+       if (!--dev->open) {
+               if (list->hidraw->exist) {
+                       hid_hw_power(dev->hid, PM_HINT_NORMAL);
+                       hid_hw_close(dev->hid);
+               } else {
+                       kfree(list->hidraw);
+               }
+       }
+
+       for (i = 0; i < HIDRAW_BUFFER_SIZE; ++i)
+               kfree(list->buffer[i].value);
        kfree(list);
-       return 0;
+       ret = 0;
+unlock:
+       mutex_unlock(&minors_lock);
+
+       return ret;
 }
 
 static long hidraw_ioctl(struct file *file, unsigned int cmd,
@@ -506,7 +529,21 @@ EXPORT_SYMBOL_GPL(hidraw_connect);
 void hidraw_disconnect(struct hid_device *hid)
 {
        struct hidraw *hidraw = hid->hidraw;
-       drop_ref(hidraw, 1);
+
+       mutex_lock(&minors_lock);
+       hidraw->exist = 0;
+
+       device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor));
+
+       hidraw_table[hidraw->minor] = NULL;
+
+       if (hidraw->open) {
+               hid_hw_close(hid);
+               wake_up_interruptible(&hidraw->wait);
+       } else {
+               kfree(hidraw);
+       }
+       mutex_unlock(&minors_lock);
 }
 EXPORT_SYMBOL_GPL(hidraw_disconnect);
 
@@ -555,23 +592,3 @@ void hidraw_exit(void)
        unregister_chrdev_region(dev_id, HIDRAW_MAX_DEVICES);
 
 }
-
-static void drop_ref(struct hidraw *hidraw, int exists_bit)
-{
-       mutex_lock(&minors_lock);
-       if (exists_bit) {
-               hid_hw_close(hidraw->hid);
-               hidraw->exist = 0;
-               if (hidraw->open)
-                       wake_up_interruptible(&hidraw->wait);
-       } else {
-               --hidraw->open;
-       }
-
-       if (!hidraw->open && !hidraw->exist) {
-               device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor));
-               hidraw_table[hidraw->minor] = NULL;
-               kfree(hidraw);
-       }
-       mutex_unlock(&minors_lock);
-}
index 406537420fffdc0b90c008dad53205bd19f2acfe..f4c3d28cd1fcc96ed76720433104aa21bd0b08a6 100644 (file)
@@ -146,14 +146,14 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
 
        if (ret != 0) {
                err = ret;
-               goto errorout;
+               goto error0;
        }
 
        ret = hv_ringbuffer_init(
                &newchannel->inbound, in, recv_ringbuffer_size);
        if (ret != 0) {
                err = ret;
-               goto errorout;
+               goto error0;
        }
 
 
@@ -168,7 +168,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
 
        if (ret != 0) {
                err = ret;
-               goto errorout;
+               goto error0;
        }
 
        /* Create and init the channel open message */
@@ -177,7 +177,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
                           GFP_KERNEL);
        if (!open_info) {
                err = -ENOMEM;
-               goto errorout;
+               goto error0;
        }
 
        init_completion(&open_info->waitevent);
@@ -193,7 +193,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
 
        if (userdatalen > MAX_USER_DEFINED_BYTES) {
                err = -EINVAL;
-               goto errorout;
+               goto error0;
        }
 
        if (userdatalen)
@@ -208,19 +208,18 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
                               sizeof(struct vmbus_channel_open_channel));
 
        if (ret != 0)
-               goto cleanup;
+               goto error1;
 
        t = wait_for_completion_timeout(&open_info->waitevent, 5*HZ);
        if (t == 0) {
                err = -ETIMEDOUT;
-               goto errorout;
+               goto error1;
        }
 
 
        if (open_info->response.open_result.status)
                err = open_info->response.open_result.status;
 
-cleanup:
        spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
        list_del(&open_info->msglistentry);
        spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
@@ -228,9 +227,12 @@ cleanup:
        kfree(open_info);
        return err;
 
-errorout:
-       hv_ringbuffer_cleanup(&newchannel->outbound);
-       hv_ringbuffer_cleanup(&newchannel->inbound);
+error1:
+       spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
+       list_del(&open_info->msglistentry);
+       spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
+
+error0:
        free_pages((unsigned long)out,
                get_order(send_ringbuffer_size + recv_ringbuffer_size));
        kfree(open_info);
index a227be47149f473bfd6fc2d41a8de99f842056fd..520e5bf4f76d9f8cd1b16edf5610554fde103181 100644 (file)
@@ -32,7 +32,7 @@
  * ASB100-A supports pwm1, while plain ASB100 does not.  There is no known
  * way for the driver to tell which one is there.
  *
- * Chip        #vin    #fanin  #pwm    #temp   wchipid vendid  i2c     ISA
+ * Chip                #vin    #fanin  #pwm    #temp   wchipid vendid  i2c     ISA
  * asb100      7       3       1       4       0x31    0x0694  yes     no
  */
 
index 68ad7d2555124a45f2d9008374d973d4b6de3b04..4f4110407387fce21c4e58cdc76dfec6093b6183 100644 (file)
@@ -2,7 +2,7 @@
  * fam15h_power.c - AMD Family 15h processor power monitoring
  *
  * Copyright (c) 2011 Advanced Micro Devices, Inc.
- * Author: Andreas Herrmann <andreas.herrmann3@amd.com>
+ * Author: Andreas Herrmann <herrmann.der.user@googlemail.com>
  *
  *
  * This driver is free software; you can redistribute it and/or
@@ -28,7 +28,7 @@
 #include <asm/processor.h>
 
 MODULE_DESCRIPTION("AMD Family 15h CPU processor power monitor");
-MODULE_AUTHOR("Andreas Herrmann <andreas.herrmann3@amd.com>");
+MODULE_AUTHOR("Andreas Herrmann <herrmann.der.user@googlemail.com>");
 MODULE_LICENSE("GPL");
 
 /* D18F3 */
index 36509ae32083d2b3e48ec894768c504e1179577c..1381a2e3bbd4dc09dca9e74c87dd4ad2ce5ebc50 100644 (file)
@@ -630,7 +630,9 @@ static struct platform_driver gpio_fan_driver = {
        .driver = {
                .name   = "gpio-fan",
                .pm     = GPIO_FAN_PM,
+#ifdef CONFIG_OF_GPIO
                .of_match_table = of_match_ptr(of_gpio_fan_match),
+#endif
        },
 };
 
index 1821b7423d5b77ae5a9e6cdd2794a7e1b9a2c173..de3c7e04c3b5b21ae095f6f91308d1fb97eb6e64 100644 (file)
@@ -2083,6 +2083,7 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
        mutex_init(&data->lock);
        mutex_init(&data->update_lock);
        data->name = w83627ehf_device_names[sio_data->kind];
+       data->bank = 0xff;              /* Force initial bank selection */
        platform_set_drvdata(pdev, data);
 
        /* 627EHG and 627EHF have 10 voltage inputs; 627DHG and 667HG have 9 */
index 5b1a6a666441f242ac63f21d9b9359464ced3f97..af15899087095044c623b4ddf0aeadbb15ed8801 100644 (file)
@@ -25,7 +25,7 @@
 /*
  * Supports following chips:
  *
- * Chip        #vin    #fanin  #pwm    #temp   wchipid vendid  i2c     ISA
+ * Chip                #vin    #fanin  #pwm    #temp   wchipid vendid  i2c     ISA
  * w83627hf    9       3       2       3       0x20    0x5ca3  no      yes(LPC)
  * w83627thf   7       3       3       3       0x90    0x5ca3  no      yes(LPC)
  * w83637hf    7       3       3       3       0x80    0x5ca3  no      yes(LPC)
index 5a5046d94c3eee8288cf5871655fffa973d97977..20f11d31da407f5545af8b7082187c518721522a 100644 (file)
@@ -24,7 +24,7 @@
 /*
  * Supports following chips:
  *
- * Chip        #vin    #fanin  #pwm    #temp   wchipid vendid  i2c     ISA
+ * Chip                #vin    #fanin  #pwm    #temp   wchipid vendid  i2c     ISA
  * as99127f    7       3       0       3       0x31    0x12c3  yes     no
  * as99127f rev.2 (type_name = as99127f)       0x31    0x5ca3  yes     no
  * w83781d     7       3       0       3       0x10-1  0x5ca3  yes     yes
index 39ab7bcc616e7a9e8733ce9bbbcc7e3cf6b0b970..ed397c6451983473b9ca7d1dbac399194a746fb3 100644 (file)
@@ -22,7 +22,7 @@
 /*
  * Supports following chips:
  *
- * Chip        #vin    #fanin  #pwm    #temp   wchipid vendid  i2c     ISA
+ * Chip                #vin    #fanin  #pwm    #temp   wchipid vendid  i2c     ISA
  * w83791d     10      5       5       3       0x71    0x5ca3  yes     no
  *
  * The w83791d chip appears to be part way between the 83781d and the
index 053645279f381b453396053dfb71294346604717..301942d084534ef748f1917b1fa3dccde1b8beed 100644 (file)
@@ -31,7 +31,7 @@
 /*
  * Supports following chips:
  *
- * Chip        #vin    #fanin  #pwm    #temp   wchipid vendid  i2c     ISA
+ * Chip                #vin    #fanin  #pwm    #temp   wchipid vendid  i2c     ISA
  * w83792d     9       7       7       3       0x7a    0x5ca3  yes     no
  */
 
index f0e8286c3c70ed7c1c2a57a73b19cc06fec8a193..79710bcac2f724233746b9c416fd53384dd52e52 100644 (file)
@@ -20,7 +20,7 @@
 /*
  * Supports following chips:
  *
- * Chip        #vin    #fanin  #pwm    #temp   wchipid vendid  i2c     ISA
+ * Chip                #vin    #fanin  #pwm    #temp   wchipid vendid  i2c     ISA
  * w83l786ng   3       2       2       2       0x7b    0x5ca3  yes     no
  */
 
index beee6b2d361db458a1336a48bd13b5166d6d013c..1722f50f247385e0247c98e5dee91c97f18203ee 100644 (file)
@@ -8,6 +8,7 @@ obj-$(CONFIG_I2C_SMBUS)         += i2c-smbus.o
 obj-$(CONFIG_I2C_CHARDEV)      += i2c-dev.o
 obj-$(CONFIG_I2C_MUX)          += i2c-mux.o
 obj-y                          += algos/ busses/ muxes/
+obj-$(CONFIG_I2C_STUB)         += i2c-stub.o
 
 ccflags-$(CONFIG_I2C_DEBUG_CORE) := -DDEBUG
 CFLAGS_i2c-core.o := -Wno-deprecated-declarations
index 65dd599a02620211b8db7a1ef6bfd1d8f9cdda30..e9df4612b7ebc9710db24290b159b4bd77d5d625 100644 (file)
@@ -81,7 +81,6 @@ config I2C_I801
        tristate "Intel 82801 (ICH/PCH)"
        depends on PCI
        select CHECK_SIGNATURE if X86 && DMI
-       select GPIOLIB if I2C_MUX
        help
          If you say yes to this option, support will be included for the Intel
          801 family of mainboard I2C interfaces.  Specifically, the following
index 2d33d62952c112adfb62bde5f08a342a37466c78..395b516ffa08cddbf5fdc2cbc5e2c34a558e356c 100644 (file)
@@ -85,7 +85,6 @@ obj-$(CONFIG_I2C_ACORN)               += i2c-acorn.o
 obj-$(CONFIG_I2C_ELEKTOR)      += i2c-elektor.o
 obj-$(CONFIG_I2C_PCA_ISA)      += i2c-pca-isa.o
 obj-$(CONFIG_I2C_SIBYTE)       += i2c-sibyte.o
-obj-$(CONFIG_I2C_STUB)         += i2c-stub.o
 obj-$(CONFIG_SCx200_ACB)       += scx200_acb.o
 obj-$(CONFIG_SCx200_I2C)       += scx200_i2c.o
 
index aa59a254be2c3e3755a377d0c0c1f02dfa6c797d..c02bf208084f0a52cbb08548a36cece9c0ca3fb9 100644 (file)
@@ -39,6 +39,7 @@
 #define        AT91_TWI_STOP           0x0002  /* Send a Stop Condition */
 #define        AT91_TWI_MSEN           0x0004  /* Master Transfer Enable */
 #define        AT91_TWI_SVDIS          0x0020  /* Slave Transfer Disable */
+#define        AT91_TWI_QUICK          0x0040  /* SMBus quick command */
 #define        AT91_TWI_SWRST          0x0080  /* Software Reset */
 
 #define        AT91_TWI_MMR            0x0004  /* Master Mode Register */
@@ -212,7 +213,11 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev)
 
        INIT_COMPLETION(dev->cmd_complete);
        dev->transfer_status = 0;
-       if (dev->msg->flags & I2C_M_RD) {
+
+       if (!dev->buf_len) {
+               at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_QUICK);
+               at91_twi_write(dev, AT91_TWI_IER, AT91_TWI_TXCOMP);
+       } else if (dev->msg->flags & I2C_M_RD) {
                unsigned start_flags = AT91_TWI_START;
 
                if (at91_twi_read(dev, AT91_TWI_SR) & AT91_TWI_RXRDY) {
index 37793156bd936202a10362e7910d88708c4a9248..6abc00d59881c921e14ab460f8bb477995c4ea44 100644 (file)
@@ -82,7 +82,8 @@
 #include <linux/wait.h>
 #include <linux/err.h>
 
-#if defined CONFIG_I2C_MUX || defined CONFIG_I2C_MUX_MODULE
+#if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \
+               defined CONFIG_DMI
 #include <linux/gpio.h>
 #include <linux/i2c-mux-gpio.h>
 #include <linux/platform_device.h>
@@ -192,7 +193,8 @@ struct i801_priv {
        int len;
        u8 *data;
 
-#if defined CONFIG_I2C_MUX || defined CONFIG_I2C_MUX_MODULE
+#if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \
+               defined CONFIG_DMI
        const struct i801_mux_config *mux_drvdata;
        struct platform_device *mux_pdev;
 #endif
@@ -921,7 +923,8 @@ static void __init input_apanel_init(void) {}
 static void __devinit i801_probe_optional_slaves(struct i801_priv *priv) {}
 #endif /* CONFIG_X86 && CONFIG_DMI */
 
-#if defined CONFIG_I2C_MUX || defined CONFIG_I2C_MUX_MODULE
+#if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \
+               defined CONFIG_DMI
 static struct i801_mux_config i801_mux_config_asus_z8_d12 = {
        .gpio_chip = "gpio_ich",
        .values = { 0x02, 0x03 },
@@ -1059,7 +1062,7 @@ static unsigned int __devinit i801_get_adapter_class(struct i801_priv *priv)
 
        id = dmi_first_match(mux_dmi_table);
        if (id) {
-               /* Remove from branch classes from trunk */
+               /* Remove branch classes from trunk */
                mux_config = id->driver_data;
                for (i = 0; i < mux_config->n_values; i++)
                        class &= ~mux_config->classes[i];
index 1f58197062cfe120b8987236044afbeec5e397df..0670da79ee5e53cd0682dbdc1e7b311a196f73e1 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Freescale MXS I2C bus driver
  *
- * Copyright (C) 2011 Wolfram Sang, Pengutronix e.K.
+ * Copyright (C) 2011-2012 Wolfram Sang, Pengutronix e.K.
  *
  * based on a (non-working) driver which was:
  *
 
 #define DRIVER_NAME "mxs-i2c"
 
-static bool use_pioqueue;
-module_param(use_pioqueue, bool, 0);
-MODULE_PARM_DESC(use_pioqueue, "Use PIOQUEUE mode for transfer instead of DMA");
-
 #define MXS_I2C_CTRL0          (0x00)
 #define MXS_I2C_CTRL0_SET      (0x04)
 
@@ -75,23 +71,6 @@ MODULE_PARM_DESC(use_pioqueue, "Use PIOQUEUE mode for transfer instead of DMA");
                                 MXS_I2C_CTRL1_SLAVE_STOP_IRQ | \
                                 MXS_I2C_CTRL1_SLAVE_IRQ)
 
-#define MXS_I2C_QUEUECTRL      (0x60)
-#define MXS_I2C_QUEUECTRL_SET  (0x64)
-#define MXS_I2C_QUEUECTRL_CLR  (0x68)
-
-#define MXS_I2C_QUEUECTRL_QUEUE_RUN            0x20
-#define MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE       0x04
-
-#define MXS_I2C_QUEUESTAT      (0x70)
-#define MXS_I2C_QUEUESTAT_RD_QUEUE_EMPTY        0x00002000
-#define MXS_I2C_QUEUESTAT_WRITE_QUEUE_CNT_MASK 0x0000001F
-
-#define MXS_I2C_QUEUECMD       (0x80)
-
-#define MXS_I2C_QUEUEDATA      (0x90)
-
-#define MXS_I2C_DATA           (0xa0)
-
 
 #define MXS_CMD_I2C_SELECT     (MXS_I2C_CTRL0_RETAIN_CLOCK |   \
                                 MXS_I2C_CTRL0_PRE_SEND_START | \
@@ -153,7 +132,6 @@ struct mxs_i2c_dev {
        const struct mxs_i2c_speed_config *speed;
 
        /* DMA support components */
-       bool                            dma_mode;
        int                             dma_channel;
        struct dma_chan                 *dmach;
        struct mxs_dma_data             dma_data;
@@ -172,99 +150,6 @@ static void mxs_i2c_reset(struct mxs_i2c_dev *i2c)
        writel(i2c->speed->timing2, i2c->regs + MXS_I2C_TIMING2);
 
        writel(MXS_I2C_IRQ_MASK << 8, i2c->regs + MXS_I2C_CTRL1_SET);
-       if (i2c->dma_mode)
-               writel(MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE,
-                       i2c->regs + MXS_I2C_QUEUECTRL_CLR);
-       else
-               writel(MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE,
-                       i2c->regs + MXS_I2C_QUEUECTRL_SET);
-}
-
-static void mxs_i2c_pioq_setup_read(struct mxs_i2c_dev *i2c, u8 addr, int len,
-                                       int flags)
-{
-       u32 data;
-
-       writel(MXS_CMD_I2C_SELECT, i2c->regs + MXS_I2C_QUEUECMD);
-
-       data = (addr << 1) | I2C_SMBUS_READ;
-       writel(data, i2c->regs + MXS_I2C_DATA);
-
-       data = MXS_CMD_I2C_READ | MXS_I2C_CTRL0_XFER_COUNT(len) | flags;
-       writel(data, i2c->regs + MXS_I2C_QUEUECMD);
-}
-
-static void mxs_i2c_pioq_setup_write(struct mxs_i2c_dev *i2c,
-                                   u8 addr, u8 *buf, int len, int flags)
-{
-       u32 data;
-       int i, shifts_left;
-
-       data = MXS_CMD_I2C_WRITE | MXS_I2C_CTRL0_XFER_COUNT(len + 1) | flags;
-       writel(data, i2c->regs + MXS_I2C_QUEUECMD);
-
-       /*
-        * We have to copy the slave address (u8) and buffer (arbitrary number
-        * of u8) into the data register (u32). To achieve that, the u8 are put
-        * into the MSBs of 'data' which is then shifted for the next u8. When
-        * appropriate, 'data' is written to MXS_I2C_DATA. So, the first u32
-        * looks like this:
-        *
-        *  3          2          1          0
-        * 10987654|32109876|54321098|76543210
-        * --------+--------+--------+--------
-        * buffer+2|buffer+1|buffer+0|slave_addr
-        */
-
-       data = ((addr << 1) | I2C_SMBUS_WRITE) << 24;
-
-       for (i = 0; i < len; i++) {
-               data >>= 8;
-               data |= buf[i] << 24;
-               if ((i & 3) == 2)
-                       writel(data, i2c->regs + MXS_I2C_DATA);
-       }
-
-       /* Write out the remaining bytes if any */
-       shifts_left = 24 - (i & 3) * 8;
-       if (shifts_left)
-               writel(data >> shifts_left, i2c->regs + MXS_I2C_DATA);
-}
-
-/*
- * TODO: should be replaceable with a waitqueue and RD_QUEUE_IRQ (setting the
- * rd_threshold to 1). Couldn't get this to work, though.
- */
-static int mxs_i2c_wait_for_data(struct mxs_i2c_dev *i2c)
-{
-       unsigned long timeout = jiffies + msecs_to_jiffies(1000);
-
-       while (readl(i2c->regs + MXS_I2C_QUEUESTAT)
-                       & MXS_I2C_QUEUESTAT_RD_QUEUE_EMPTY) {
-                       if (time_after(jiffies, timeout))
-                               return -ETIMEDOUT;
-                       cond_resched();
-       }
-
-       return 0;
-}
-
-static int mxs_i2c_finish_read(struct mxs_i2c_dev *i2c, u8 *buf, int len)
-{
-       u32 uninitialized_var(data);
-       int i;
-
-       for (i = 0; i < len; i++) {
-               if ((i & 3) == 0) {
-                       if (mxs_i2c_wait_for_data(i2c))
-                               return -ETIMEDOUT;
-                       data = readl(i2c->regs + MXS_I2C_QUEUEDATA);
-               }
-               buf[i] = data & 0xff;
-               data >>= 8;
-       }
-
-       return 0;
 }
 
 static void mxs_i2c_dma_finish(struct mxs_i2c_dev *i2c)
@@ -402,12 +287,14 @@ read_init_dma_fail:
 select_init_dma_fail:
        dma_unmap_sg(i2c->dev, &i2c->sg_io[0], 1, DMA_TO_DEVICE);
 select_init_pio_fail:
+       dmaengine_terminate_all(i2c->dmach);
        return -EINVAL;
 
 /* Write failpath. */
 write_init_dma_fail:
        dma_unmap_sg(i2c->dev, i2c->sg_io, 2, DMA_TO_DEVICE);
 write_init_pio_fail:
+       dmaengine_terminate_all(i2c->dmach);
        return -EINVAL;
 }
 
@@ -432,39 +319,17 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,
        init_completion(&i2c->cmd_complete);
        i2c->cmd_err = 0;
 
-       if (i2c->dma_mode) {
-               ret = mxs_i2c_dma_setup_xfer(adap, msg, flags);
-               if (ret)
-                       return ret;
-       } else {
-               if (msg->flags & I2C_M_RD) {
-                       mxs_i2c_pioq_setup_read(i2c, msg->addr,
-                                               msg->len, flags);
-               } else {
-                       mxs_i2c_pioq_setup_write(i2c, msg->addr, msg->buf,
-                                               msg->len, flags);
-               }
-
-               writel(MXS_I2C_QUEUECTRL_QUEUE_RUN,
-                       i2c->regs + MXS_I2C_QUEUECTRL_SET);
-       }
+       ret = mxs_i2c_dma_setup_xfer(adap, msg, flags);
+       if (ret)
+               return ret;
 
        ret = wait_for_completion_timeout(&i2c->cmd_complete,
                                                msecs_to_jiffies(1000));
        if (ret == 0)
                goto timeout;
 
-       if (!i2c->dma_mode && !i2c->cmd_err && (msg->flags & I2C_M_RD)) {
-               ret = mxs_i2c_finish_read(i2c, msg->buf, msg->len);
-               if (ret)
-                       goto timeout;
-       }
-
        if (i2c->cmd_err == -ENXIO)
                mxs_i2c_reset(i2c);
-       else
-               writel(MXS_I2C_QUEUECTRL_QUEUE_RUN,
-                               i2c->regs + MXS_I2C_QUEUECTRL_CLR);
 
        dev_dbg(i2c->dev, "Done with err=%d\n", i2c->cmd_err);
 
@@ -472,8 +337,7 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,
 
 timeout:
        dev_dbg(i2c->dev, "Timeout!\n");
-       if (i2c->dma_mode)
-               mxs_i2c_dma_finish(i2c);
+       mxs_i2c_dma_finish(i2c);
        mxs_i2c_reset(i2c);
        return -ETIMEDOUT;
 }
@@ -502,7 +366,6 @@ static irqreturn_t mxs_i2c_isr(int this_irq, void *dev_id)
 {
        struct mxs_i2c_dev *i2c = dev_id;
        u32 stat = readl(i2c->regs + MXS_I2C_CTRL1) & MXS_I2C_IRQ_MASK;
-       bool is_last_cmd;
 
        if (!stat)
                return IRQ_NONE;
@@ -515,14 +378,6 @@ static irqreturn_t mxs_i2c_isr(int this_irq, void *dev_id)
                /* MXS_I2C_CTRL1_OVERSIZE_XFER_TERM_IRQ is only for slaves */
                i2c->cmd_err = -EIO;
 
-       if (!i2c->dma_mode) {
-               is_last_cmd = (readl(i2c->regs + MXS_I2C_QUEUESTAT) &
-                       MXS_I2C_QUEUESTAT_WRITE_QUEUE_CNT_MASK) == 0;
-
-               if (is_last_cmd || i2c->cmd_err)
-                       complete(&i2c->cmd_complete);
-       }
-
        writel(stat, i2c->regs + MXS_I2C_CTRL1_CLR);
 
        return IRQ_HANDLED;
@@ -555,15 +410,6 @@ static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c)
        struct device_node *node = dev->of_node;
        int ret;
 
-       /*
-        * The MXS I2C DMA mode is prefered and enabled by default.
-        * The PIO mode is still supported, but should be used only
-        * for debuging purposes etc.
-        */
-       i2c->dma_mode = !use_pioqueue;
-       if (!i2c->dma_mode)
-               dev_info(dev, "Using PIOQUEUE mode for I2C transfers!\n");
-
        /*
         * TODO: This is a temporary solution and should be changed
         * to use generic DMA binding later when the helpers get in.
@@ -571,8 +417,8 @@ static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c)
        ret = of_property_read_u32(node, "fsl,i2c-dma-channel",
                                   &i2c->dma_channel);
        if (ret) {
-               dev_warn(dev, "Failed to get DMA channel, using PIOQUEUE!\n");
-               i2c->dma_mode = 0;
+               dev_err(dev, "Failed to get DMA channel!\n");
+               return -ENODEV;
        }
 
        ret = of_property_read_u32(node, "clock-frequency", &speed);
@@ -634,15 +480,13 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev)
        }
 
        /* Setup the DMA */
-       if (i2c->dma_mode) {
-               dma_cap_zero(mask);
-               dma_cap_set(DMA_SLAVE, mask);
-               i2c->dma_data.chan_irq = dmairq;
-               i2c->dmach = dma_request_channel(mask, mxs_i2c_dma_filter, i2c);
-               if (!i2c->dmach) {
-                       dev_err(dev, "Failed to request dma\n");
-                       return -ENODEV;
-               }
+       dma_cap_zero(mask);
+       dma_cap_set(DMA_SLAVE, mask);
+       i2c->dma_data.chan_irq = dmairq;
+       i2c->dmach = dma_request_channel(mask, mxs_i2c_dma_filter, i2c);
+       if (!i2c->dmach) {
+               dev_err(dev, "Failed to request dma\n");
+               return -ENODEV;
        }
 
        platform_set_drvdata(pdev, i2c);
index 698d7acb0f083c10ea2028ad895e58043105f44e..02c3115a2dfa11c0aecf5a5c7e6bc24566539c8b 100644 (file)
@@ -644,7 +644,11 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap,
 
        pm_runtime_get_sync(&dev->adev->dev);
 
-       clk_enable(dev->clk);
+       status = clk_prepare_enable(dev->clk);
+       if (status) {
+               dev_err(&dev->adev->dev, "can't prepare_enable clock\n");
+               goto out_clk;
+       }
 
        status = init_hw(dev);
        if (status)
@@ -671,7 +675,8 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap,
        }
 
 out:
-       clk_disable(dev->clk);
+       clk_disable_unprepare(dev->clk);
+out_clk:
        pm_runtime_put_sync(&dev->adev->dev);
 
        dev->busy = false;
index db31eaed6ea59b32083df49f757c1fc949c60303..3525c9e62cb0f9bf23f47705fd86d3bba9707b45 100644 (file)
@@ -43,7 +43,6 @@
 #include <linux/slab.h>
 #include <linux/i2c-omap.h>
 #include <linux/pm_runtime.h>
-#include <linux/pm_qos.h>
 
 /* I2C controller revisions */
 #define OMAP_I2C_OMAP1_REV_2           0x20
@@ -187,8 +186,9 @@ struct omap_i2c_dev {
        int                     reg_shift;      /* bit shift for I2C register addresses */
        struct completion       cmd_complete;
        struct resource         *ioarea;
-       u32                     latency;        /* maximum MPU wkup latency */
-       struct pm_qos_request   pm_qos_request;
+       u32                     latency;        /* maximum mpu wkup latency */
+       void                    (*set_mpu_wkup_lat)(struct device *dev,
+                                                   long latency);
        u32                     speed;          /* Speed of bus in kHz */
        u32                     dtrev;          /* extra revision from DT */
        u32                     flags;
@@ -494,7 +494,9 @@ static void omap_i2c_resize_fifo(struct omap_i2c_dev *dev, u8 size, bool is_rx)
                dev->b_hw = 1; /* Enable hardware fixes */
 
        /* calculate wakeup latency constraint for MPU */
-       dev->latency = (1000000 * dev->threshold) / (1000 * dev->speed / 8);
+       if (dev->set_mpu_wkup_lat != NULL)
+               dev->latency = (1000000 * dev->threshold) /
+                       (1000 * dev->speed / 8);
 }
 
 /*
@@ -522,6 +524,9 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
        dev->buf = msg->buf;
        dev->buf_len = msg->len;
 
+       /* make sure writes to dev->buf_len are ordered */
+       barrier();
+
        omap_i2c_write_reg(dev, OMAP_I2C_CNT_REG, dev->buf_len);
 
        /* Clear the FIFO Buffers */
@@ -579,7 +584,6 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
         */
        timeout = wait_for_completion_timeout(&dev->cmd_complete,
                                                OMAP_I2C_TIMEOUT);
-       dev->buf_len = 0;
        if (timeout == 0) {
                dev_err(dev->dev, "controller timed out\n");
                omap_i2c_init(dev);
@@ -629,16 +633,8 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
        if (r < 0)
                goto out;
 
-       /*
-        * When waiting for completion of a i2c transfer, we need to
-        * set a wake up latency constraint for the MPU. This is to
-        * ensure quick enough wakeup from idle, when transfer
-        * completes.
-        */
-       if (dev->latency)
-               pm_qos_add_request(&dev->pm_qos_request,
-                                  PM_QOS_CPU_DMA_LATENCY,
-                                  dev->latency);
+       if (dev->set_mpu_wkup_lat != NULL)
+               dev->set_mpu_wkup_lat(dev->dev, dev->latency);
 
        for (i = 0; i < num; i++) {
                r = omap_i2c_xfer_msg(adap, &msgs[i], (i == (num - 1)));
@@ -646,8 +642,8 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
                        break;
        }
 
-       if (dev->latency)
-               pm_qos_remove_request(&dev->pm_qos_request);
+       if (dev->set_mpu_wkup_lat != NULL)
+               dev->set_mpu_wkup_lat(dev->dev, -1);
 
        if (r == 0)
                r = num;
@@ -1104,6 +1100,7 @@ omap_i2c_probe(struct platform_device *pdev)
        } else if (pdata != NULL) {
                dev->speed = pdata->clkrate;
                dev->flags = pdata->flags;
+               dev->set_mpu_wkup_lat = pdata->set_mpu_wkup_lat;
                dev->dtrev = pdata->rev;
        }
 
@@ -1159,8 +1156,9 @@ omap_i2c_probe(struct platform_device *pdev)
                        dev->b_hw = 1; /* Enable hardware fixes */
 
                /* calculate wakeup latency constraint for MPU */
-               dev->latency = (1000000 * dev->fifo_size) /
-                              (1000 * dev->speed / 8);
+               if (dev->set_mpu_wkup_lat != NULL)
+                       dev->latency = (1000000 * dev->fifo_size) /
+                                      (1000 * dev->speed / 8);
        }
 
        /* reset ASAP, clearing any IRQs */
index 3e0335f1fc60df8b78ce50c7a4e5284e82ad432f..9d902725bac94f28c91aa26ec57615988cd96e77 100644 (file)
@@ -806,6 +806,7 @@ static int s3c24xx_i2c_parse_dt_gpio(struct s3c24xx_i2c *i2c)
                        dev_err(i2c->dev, "invalid gpio[%d]: %d\n", idx, gpio);
                        goto free_gpio;
                }
+               i2c->gpios[idx] = gpio;
 
                ret = gpio_request(gpio, "i2c-bus");
                if (ret) {
diff --git a/drivers/i2c/busses/i2c-stub.c b/drivers/i2c/busses/i2c-stub.c
deleted file mode 100644 (file)
index b1b3447..0000000
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
-    i2c-stub.c - I2C/SMBus chip emulator
-
-    Copyright (c) 2004 Mark M. Hoffman <mhoffman@lightlink.com>
-    Copyright (C) 2007 Jean Delvare <khali@linux-fr.org>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#define DEBUG 1
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/i2c.h>
-
-#define MAX_CHIPS 10
-#define STUB_FUNC (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | \
-                  I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | \
-                  I2C_FUNC_SMBUS_I2C_BLOCK)
-
-static unsigned short chip_addr[MAX_CHIPS];
-module_param_array(chip_addr, ushort, NULL, S_IRUGO);
-MODULE_PARM_DESC(chip_addr,
-                "Chip addresses (up to 10, between 0x03 and 0x77)");
-
-static unsigned long functionality = STUB_FUNC;
-module_param(functionality, ulong, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(functionality, "Override functionality bitfield");
-
-struct stub_chip {
-       u8 pointer;
-       u16 words[256];         /* Byte operations use the LSB as per SMBus
-                                  specification */
-};
-
-static struct stub_chip *stub_chips;
-
-/* Return negative errno on error. */
-static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,
-       char read_write, u8 command, int size, union i2c_smbus_data * data)
-{
-       s32 ret;
-       int i, len;
-       struct stub_chip *chip = NULL;
-
-       /* Search for the right chip */
-       for (i = 0; i < MAX_CHIPS && chip_addr[i]; i++) {
-               if (addr == chip_addr[i]) {
-                       chip = stub_chips + i;
-                       break;
-               }
-       }
-       if (!chip)
-               return -ENODEV;
-
-       switch (size) {
-
-       case I2C_SMBUS_QUICK:
-               dev_dbg(&adap->dev, "smbus quick - addr 0x%02x\n", addr);
-               ret = 0;
-               break;
-
-       case I2C_SMBUS_BYTE:
-               if (read_write == I2C_SMBUS_WRITE) {
-                       chip->pointer = command;
-                       dev_dbg(&adap->dev, "smbus byte - addr 0x%02x, "
-                                       "wrote 0x%02x.\n",
-                                       addr, command);
-               } else {
-                       data->byte = chip->words[chip->pointer++] & 0xff;
-                       dev_dbg(&adap->dev, "smbus byte - addr 0x%02x, "
-                                       "read  0x%02x.\n",
-                                       addr, data->byte);
-               }
-
-               ret = 0;
-               break;
-
-       case I2C_SMBUS_BYTE_DATA:
-               if (read_write == I2C_SMBUS_WRITE) {
-                       chip->words[command] &= 0xff00;
-                       chip->words[command] |= data->byte;
-                       dev_dbg(&adap->dev, "smbus byte data - addr 0x%02x, "
-                                       "wrote 0x%02x at 0x%02x.\n",
-                                       addr, data->byte, command);
-               } else {
-                       data->byte = chip->words[command] & 0xff;
-                       dev_dbg(&adap->dev, "smbus byte data - addr 0x%02x, "
-                                       "read  0x%02x at 0x%02x.\n",
-                                       addr, data->byte, command);
-               }
-               chip->pointer = command + 1;
-
-               ret = 0;
-               break;
-
-       case I2C_SMBUS_WORD_DATA:
-               if (read_write == I2C_SMBUS_WRITE) {
-                       chip->words[command] = data->word;
-                       dev_dbg(&adap->dev, "smbus word data - addr 0x%02x, "
-                                       "wrote 0x%04x at 0x%02x.\n",
-                                       addr, data->word, command);
-               } else {
-                       data->word = chip->words[command];
-                       dev_dbg(&adap->dev, "smbus word data - addr 0x%02x, "
-                                       "read  0x%04x at 0x%02x.\n",
-                                       addr, data->word, command);
-               }
-
-               ret = 0;
-               break;
-
-       case I2C_SMBUS_I2C_BLOCK_DATA:
-               len = data->block[0];
-               if (read_write == I2C_SMBUS_WRITE) {
-                       for (i = 0; i < len; i++) {
-                               chip->words[command + i] &= 0xff00;
-                               chip->words[command + i] |= data->block[1 + i];
-                       }
-                       dev_dbg(&adap->dev, "i2c block data - addr 0x%02x, "
-                                       "wrote %d bytes at 0x%02x.\n",
-                                       addr, len, command);
-               } else {
-                       for (i = 0; i < len; i++) {
-                               data->block[1 + i] =
-                                       chip->words[command + i] & 0xff;
-                       }
-                       dev_dbg(&adap->dev, "i2c block data - addr 0x%02x, "
-                                       "read  %d bytes at 0x%02x.\n",
-                                       addr, len, command);
-               }
-
-               ret = 0;
-               break;
-
-       default:
-               dev_dbg(&adap->dev, "Unsupported I2C/SMBus command\n");
-               ret = -EOPNOTSUPP;
-               break;
-       } /* switch (size) */
-
-       return ret;
-}
-
-static u32 stub_func(struct i2c_adapter *adapter)
-{
-       return STUB_FUNC & functionality;
-}
-
-static const struct i2c_algorithm smbus_algorithm = {
-       .functionality  = stub_func,
-       .smbus_xfer     = stub_xfer,
-};
-
-static struct i2c_adapter stub_adapter = {
-       .owner          = THIS_MODULE,
-       .class          = I2C_CLASS_HWMON | I2C_CLASS_SPD,
-       .algo           = &smbus_algorithm,
-       .name           = "SMBus stub driver",
-};
-
-static int __init i2c_stub_init(void)
-{
-       int i, ret;
-
-       if (!chip_addr[0]) {
-               printk(KERN_ERR "i2c-stub: Please specify a chip address\n");
-               return -ENODEV;
-       }
-
-       for (i = 0; i < MAX_CHIPS && chip_addr[i]; i++) {
-               if (chip_addr[i] < 0x03 || chip_addr[i] > 0x77) {
-                       printk(KERN_ERR "i2c-stub: Invalid chip address "
-                              "0x%02x\n", chip_addr[i]);
-                       return -EINVAL;
-               }
-
-               printk(KERN_INFO "i2c-stub: Virtual chip at 0x%02x\n",
-                      chip_addr[i]);
-       }
-
-       /* Allocate memory for all chips at once */
-       stub_chips = kzalloc(i * sizeof(struct stub_chip), GFP_KERNEL);
-       if (!stub_chips) {
-               printk(KERN_ERR "i2c-stub: Out of memory\n");
-               return -ENOMEM;
-       }
-
-       ret = i2c_add_adapter(&stub_adapter);
-       if (ret)
-               kfree(stub_chips);
-       return ret;
-}
-
-static void __exit i2c_stub_exit(void)
-{
-       i2c_del_adapter(&stub_adapter);
-       kfree(stub_chips);
-}
-
-MODULE_AUTHOR("Mark M. Hoffman <mhoffman@lightlink.com>");
-MODULE_DESCRIPTION("I2C stub driver");
-MODULE_LICENSE("GPL");
-
-module_init(i2c_stub_init);
-module_exit(i2c_stub_exit);
-
index f981ac4e6783104ee8586e2631fc58f788d49be6..dcea77bf6f50ff2cc1c198e7850bbbe138128238 100644 (file)
@@ -742,7 +742,7 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev)
        }
 
        ret = devm_request_irq(&pdev->dev, i2c_dev->irq,
-                       tegra_i2c_isr, 0, pdev->name, i2c_dev);
+                       tegra_i2c_isr, 0, dev_name(&pdev->dev), i2c_dev);
        if (ret) {
                dev_err(&pdev->dev, "Failed to request irq %i\n", i2c_dev->irq);
                return ret;
diff --git a/drivers/i2c/i2c-stub.c b/drivers/i2c/i2c-stub.c
new file mode 100644 (file)
index 0000000..d0a9c59
--- /dev/null
@@ -0,0 +1,220 @@
+/*
+    i2c-stub.c - I2C/SMBus chip emulator
+
+    Copyright (c) 2004 Mark M. Hoffman <mhoffman@lightlink.com>
+    Copyright (C) 2007, 2012 Jean Delvare <khali@linux-fr.org>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#define DEBUG 1
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/i2c.h>
+
+#define MAX_CHIPS 10
+#define STUB_FUNC (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | \
+                  I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | \
+                  I2C_FUNC_SMBUS_I2C_BLOCK)
+
+static unsigned short chip_addr[MAX_CHIPS];
+module_param_array(chip_addr, ushort, NULL, S_IRUGO);
+MODULE_PARM_DESC(chip_addr,
+                "Chip addresses (up to 10, between 0x03 and 0x77)");
+
+static unsigned long functionality = STUB_FUNC;
+module_param(functionality, ulong, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(functionality, "Override functionality bitfield");
+
+struct stub_chip {
+       u8 pointer;
+       u16 words[256];         /* Byte operations use the LSB as per SMBus
+                                  specification */
+};
+
+static struct stub_chip *stub_chips;
+
+/* Return negative errno on error. */
+static s32 stub_xfer(struct i2c_adapter *adap, u16 addr, unsigned short flags,
+       char read_write, u8 command, int size, union i2c_smbus_data *data)
+{
+       s32 ret;
+       int i, len;
+       struct stub_chip *chip = NULL;
+
+       /* Search for the right chip */
+       for (i = 0; i < MAX_CHIPS && chip_addr[i]; i++) {
+               if (addr == chip_addr[i]) {
+                       chip = stub_chips + i;
+                       break;
+               }
+       }
+       if (!chip)
+               return -ENODEV;
+
+       switch (size) {
+
+       case I2C_SMBUS_QUICK:
+               dev_dbg(&adap->dev, "smbus quick - addr 0x%02x\n", addr);
+               ret = 0;
+               break;
+
+       case I2C_SMBUS_BYTE:
+               if (read_write == I2C_SMBUS_WRITE) {
+                       chip->pointer = command;
+                       dev_dbg(&adap->dev,
+                               "smbus byte - addr 0x%02x, wrote 0x%02x.\n",
+                               addr, command);
+               } else {
+                       data->byte = chip->words[chip->pointer++] & 0xff;
+                       dev_dbg(&adap->dev,
+                               "smbus byte - addr 0x%02x, read  0x%02x.\n",
+                               addr, data->byte);
+               }
+
+               ret = 0;
+               break;
+
+       case I2C_SMBUS_BYTE_DATA:
+               if (read_write == I2C_SMBUS_WRITE) {
+                       chip->words[command] &= 0xff00;
+                       chip->words[command] |= data->byte;
+                       dev_dbg(&adap->dev,
+                               "smbus byte data - addr 0x%02x, wrote 0x%02x at 0x%02x.\n",
+                               addr, data->byte, command);
+               } else {
+                       data->byte = chip->words[command] & 0xff;
+                       dev_dbg(&adap->dev,
+                               "smbus byte data - addr 0x%02x, read  0x%02x at 0x%02x.\n",
+                               addr, data->byte, command);
+               }
+               chip->pointer = command + 1;
+
+               ret = 0;
+               break;
+
+       case I2C_SMBUS_WORD_DATA:
+               if (read_write == I2C_SMBUS_WRITE) {
+                       chip->words[command] = data->word;
+                       dev_dbg(&adap->dev,
+                               "smbus word data - addr 0x%02x, wrote 0x%04x at 0x%02x.\n",
+                               addr, data->word, command);
+               } else {
+                       data->word = chip->words[command];
+                       dev_dbg(&adap->dev,
+                               "smbus word data - addr 0x%02x, read  0x%04x at 0x%02x.\n",
+                               addr, data->word, command);
+               }
+
+               ret = 0;
+               break;
+
+       case I2C_SMBUS_I2C_BLOCK_DATA:
+               len = data->block[0];
+               if (read_write == I2C_SMBUS_WRITE) {
+                       for (i = 0; i < len; i++) {
+                               chip->words[command + i] &= 0xff00;
+                               chip->words[command + i] |= data->block[1 + i];
+                       }
+                       dev_dbg(&adap->dev,
+                               "i2c block data - addr 0x%02x, wrote %d bytes at 0x%02x.\n",
+                               addr, len, command);
+               } else {
+                       for (i = 0; i < len; i++) {
+                               data->block[1 + i] =
+                                       chip->words[command + i] & 0xff;
+                       }
+                       dev_dbg(&adap->dev,
+                               "i2c block data - addr 0x%02x, read  %d bytes at 0x%02x.\n",
+                               addr, len, command);
+               }
+
+               ret = 0;
+               break;
+
+       default:
+               dev_dbg(&adap->dev, "Unsupported I2C/SMBus command\n");
+               ret = -EOPNOTSUPP;
+               break;
+       } /* switch (size) */
+
+       return ret;
+}
+
+static u32 stub_func(struct i2c_adapter *adapter)
+{
+       return STUB_FUNC & functionality;
+}
+
+static const struct i2c_algorithm smbus_algorithm = {
+       .functionality  = stub_func,
+       .smbus_xfer     = stub_xfer,
+};
+
+static struct i2c_adapter stub_adapter = {
+       .owner          = THIS_MODULE,
+       .class          = I2C_CLASS_HWMON | I2C_CLASS_SPD,
+       .algo           = &smbus_algorithm,
+       .name           = "SMBus stub driver",
+};
+
+static int __init i2c_stub_init(void)
+{
+       int i, ret;
+
+       if (!chip_addr[0]) {
+               pr_err("i2c-stub: Please specify a chip address\n");
+               return -ENODEV;
+       }
+
+       for (i = 0; i < MAX_CHIPS && chip_addr[i]; i++) {
+               if (chip_addr[i] < 0x03 || chip_addr[i] > 0x77) {
+                       pr_err("i2c-stub: Invalid chip address 0x%02x\n",
+                              chip_addr[i]);
+                       return -EINVAL;
+               }
+
+               pr_info("i2c-stub: Virtual chip at 0x%02x\n", chip_addr[i]);
+       }
+
+       /* Allocate memory for all chips at once */
+       stub_chips = kzalloc(i * sizeof(struct stub_chip), GFP_KERNEL);
+       if (!stub_chips) {
+               pr_err("i2c-stub: Out of memory\n");
+               return -ENOMEM;
+       }
+
+       ret = i2c_add_adapter(&stub_adapter);
+       if (ret)
+               kfree(stub_chips);
+       return ret;
+}
+
+static void __exit i2c_stub_exit(void)
+{
+       i2c_del_adapter(&stub_adapter);
+       kfree(stub_chips);
+}
+
+MODULE_AUTHOR("Mark M. Hoffman <mhoffman@lightlink.com>");
+MODULE_DESCRIPTION("I2C stub driver");
+MODULE_LICENSE("GPL");
+
+module_init(i2c_stub_init);
+module_exit(i2c_stub_exit);
index 5f097f309b9f9e92c59a5525db04283ab699fc74..7fa5b24b16db9a4a1c4c1a360f16dd01b018a215 100644 (file)
@@ -169,7 +169,7 @@ static int __devinit i2c_mux_pinctrl_probe(struct platform_device *pdev)
        mux->busses = devm_kzalloc(&pdev->dev,
                                   sizeof(mux->busses) * mux->pdata->bus_count,
                                   GFP_KERNEL);
-       if (!mux->states) {
+       if (!mux->busses) {
                dev_err(&pdev->dev, "Cannot allocate busses\n");
                ret = -ENOMEM;
                goto err;
index 6e3f143fc71d146c786a550162216be2200d0f4f..fc937aca71fbb2f7bb8a53fac55e2ae9b0cec048 100644 (file)
@@ -62,7 +62,6 @@ source "drivers/iio/frequency/Kconfig"
 source "drivers/iio/dac/Kconfig"
 source "drivers/iio/common/Kconfig"
 source "drivers/iio/gyro/Kconfig"
-source "drivers/iio/light/Kconfig"
 source "drivers/iio/magnetometer/Kconfig"
 
 endif # IIO
index f7fa3c0867b4c29026b2821cf793c352972741ce..761f2b65ac52865f4d16a99db3a1f6e7e1b61fbb 100644 (file)
@@ -18,5 +18,4 @@ obj-y += frequency/
 obj-y += dac/
 obj-y += common/
 obj-y += gyro/
-obj-y += light/
 obj-y += magnetometer/
index 57e07c61ace2e8147badfcd87e7f19fa211e4746..afd81790ab3c3e818c73b26fb6856e4f327c133a 100644 (file)
@@ -468,7 +468,7 @@ struct ib_mr *c4iw_register_phys_mem(struct ib_pd *pd,
        ret = alloc_pbl(mhp, npages);
        if (ret) {
                kfree(page_list);
-               goto err_pbl;
+               goto err;
        }
 
        ret = write_pbl(&mhp->rhp->rdev, page_list, mhp->attr.pbl_addr,
index d2fb38d43571d9f5ebba2dbc33e94ff5fc4cf737..2f215b93db6ba5a68b6d7e6fc38d21c91ff0cfa9 100644 (file)
@@ -107,7 +107,7 @@ static __be64 get_cached_alias_guid(struct mlx4_ib_dev *dev, int port, int index
 {
        if (index >= NUM_ALIAS_GUID_PER_PORT) {
                pr_err("%s: ERROR: asked for index:%d\n", __func__, index);
-               return  (__force __be64) ((u64) 0xFFFFFFFFFFFFFFFFUL);
+               return (__force __be64) -1;
        }
        return *(__be64 *)&dev->sriov.demux[port - 1].guid_cache[index];
 }
index 21a794152d15acea2a2e450258f4aaa915bce03a..0a903c129f0a19bfd0175de7aaea382dddec6d88 100644 (file)
@@ -409,38 +409,45 @@ int mlx4_ib_find_real_gid(struct ib_device *ibdev, u8 port, __be64 guid)
 }
 
 
-static int get_pkey_phys_indices(struct mlx4_ib_dev *ibdev, u8 port, u8 ph_pkey_ix,
-                                u8 *full_pk_ix, u8 *partial_pk_ix,
-                                int *is_full_member)
+static int find_slave_port_pkey_ix(struct mlx4_ib_dev *dev, int slave,
+                                  u8 port, u16 pkey, u16 *ix)
 {
-       u16 search_pkey;
-       int fm;
-       int err = 0;
-       u16 pk;
+       int i, ret;
+       u8 unassigned_pkey_ix, pkey_ix, partial_ix = 0xFF;
+       u16 slot_pkey;
 
-       err = ib_get_cached_pkey(&ibdev->ib_dev, port, ph_pkey_ix, &search_pkey);
-       if (err)
-               return err;
+       if (slave == mlx4_master_func_num(dev->dev))
+               return ib_find_cached_pkey(&dev->ib_dev, port, pkey, ix);
 
-       fm = (search_pkey & 0x8000) ? 1 : 0;
-       if (fm) {
-               *full_pk_ix = ph_pkey_ix;
-               search_pkey &= 0x7FFF;
-       } else {
-               *partial_pk_ix = ph_pkey_ix;
-               search_pkey |= 0x8000;
-       }
+       unassigned_pkey_ix = dev->dev->phys_caps.pkey_phys_table_len[port] - 1;
 
-       if (ib_find_exact_cached_pkey(&ibdev->ib_dev, port, search_pkey, &pk))
-               pk = 0xFFFF;
+       for (i = 0; i < dev->dev->caps.pkey_table_len[port]; i++) {
+               if (dev->pkeys.virt2phys_pkey[slave][port - 1][i] == unassigned_pkey_ix)
+                       continue;
 
-       if (fm)
-               *partial_pk_ix = (pk & 0xFF);
-       else
-               *full_pk_ix = (pk & 0xFF);
+               pkey_ix = dev->pkeys.virt2phys_pkey[slave][port - 1][i];
 
-       *is_full_member = fm;
-       return err;
+               ret = ib_get_cached_pkey(&dev->ib_dev, port, pkey_ix, &slot_pkey);
+               if (ret)
+                       continue;
+               if ((slot_pkey & 0x7FFF) == (pkey & 0x7FFF)) {
+                       if (slot_pkey & 0x8000) {
+                               *ix = (u16) pkey_ix;
+                               return 0;
+                       } else {
+                               /* take first partial pkey index found */
+                               if (partial_ix == 0xFF)
+                                       partial_ix = pkey_ix;
+                       }
+               }
+       }
+
+       if (partial_ix < 0xFF) {
+               *ix = (u16) partial_ix;
+               return 0;
+       }
+
+       return -EINVAL;
 }
 
 int mlx4_ib_send_to_slave(struct mlx4_ib_dev *dev, int slave, u8 port,
@@ -458,10 +465,8 @@ int mlx4_ib_send_to_slave(struct mlx4_ib_dev *dev, int slave, u8 port,
        unsigned tun_tx_ix = 0;
        int dqpn;
        int ret = 0;
-       int i;
-       int is_full_member = 0;
        u16 tun_pkey_ix;
-       u8 ph_pkey_ix, full_pk_ix = 0, partial_pk_ix = 0;
+       u16 cached_pkey;
 
        if (dest_qpt > IB_QPT_GSI)
                return -EINVAL;
@@ -481,27 +486,17 @@ int mlx4_ib_send_to_slave(struct mlx4_ib_dev *dev, int slave, u8 port,
        else
                tun_qp = &tun_ctx->qp[1];
 
-       /* compute pkey index for slave */
-       /* get physical pkey -- virtualized Dom0 pkey to phys*/
+       /* compute P_Key index to put in tunnel header for slave */
        if (dest_qpt) {
-               ph_pkey_ix =
-                       dev->pkeys.virt2phys_pkey[mlx4_master_func_num(dev->dev)][port - 1][wc->pkey_index];
-
-               /* now, translate this to the slave pkey index */
-               ret = get_pkey_phys_indices(dev, port, ph_pkey_ix, &full_pk_ix,
-                                           &partial_pk_ix, &is_full_member);
+               u16 pkey_ix;
+               ret = ib_get_cached_pkey(&dev->ib_dev, port, wc->pkey_index, &cached_pkey);
                if (ret)
                        return -EINVAL;
 
-               for (i = 0; i < dev->dev->caps.pkey_table_len[port]; i++) {
-                       if ((dev->pkeys.virt2phys_pkey[slave][port - 1][i] == full_pk_ix) ||
-                           (is_full_member &&
-                            (dev->pkeys.virt2phys_pkey[slave][port - 1][i] == partial_pk_ix)))
-                               break;
-               }
-               if (i == dev->dev->caps.pkey_table_len[port])
+               ret = find_slave_port_pkey_ix(dev, slave, port, cached_pkey, &pkey_ix);
+               if (ret)
                        return -EINVAL;
-               tun_pkey_ix = i;
+               tun_pkey_ix = pkey_ix;
        } else
                tun_pkey_ix = dev->pkeys.virt2phys_pkey[slave][port - 1][0];
 
index 3c3b54c3fdd93206e60b85c421bc313d952c9655..25b2cdff00f8e4bcd76044e8916b2aa257a7276e 100644 (file)
@@ -233,7 +233,8 @@ static int send_mad_to_slave(int slave, struct mlx4_ib_demux_ctx *ctx,
 
        ib_query_ah(dev->sm_ah[ctx->port - 1], &ah_attr);
 
-       wc.pkey_index = 0;
+       if (ib_find_cached_pkey(&dev->ib_dev, ctx->port, IB_DEFAULT_PKEY_FULL, &wc.pkey_index))
+               return -EINVAL;
        wc.sl = 0;
        wc.dlid_path_bits = 0;
        wc.port_num = ctx->port;
@@ -1074,10 +1075,6 @@ static void _mlx4_ib_mcg_port_cleanup(struct mlx4_ib_demux_ctx *ctx, int destroy
        unsigned long end;
        int count;
 
-       if (ctx->flushing)
-               return;
-
-       ctx->flushing = 1;
        for (i = 0; i < MAX_VFS; ++i)
                clean_vf_mcast(ctx, i);
 
@@ -1107,9 +1104,6 @@ static void _mlx4_ib_mcg_port_cleanup(struct mlx4_ib_demux_ctx *ctx, int destroy
                force_clean_group(group);
        }
        mutex_unlock(&ctx->mcg_table_lock);
-
-       if (!destroy_wq)
-               ctx->flushing = 0;
 }
 
 struct clean_work {
@@ -1123,6 +1117,7 @@ static void mcg_clean_task(struct work_struct *work)
        struct clean_work *cw = container_of(work, struct clean_work, work);
 
        _mlx4_ib_mcg_port_cleanup(cw->ctx, cw->destroy_wq);
+       cw->ctx->flushing = 0;
        kfree(cw);
 }
 
@@ -1130,13 +1125,20 @@ void mlx4_ib_mcg_port_cleanup(struct mlx4_ib_demux_ctx *ctx, int destroy_wq)
 {
        struct clean_work *work;
 
+       if (ctx->flushing)
+               return;
+
+       ctx->flushing = 1;
+
        if (destroy_wq) {
                _mlx4_ib_mcg_port_cleanup(ctx, destroy_wq);
+               ctx->flushing = 0;
                return;
        }
 
        work = kmalloc(sizeof *work, GFP_KERNEL);
        if (!work) {
+               ctx->flushing = 0;
                mcg_warn("failed allocating work for cleanup\n");
                return;
        }
index 6ae2ac47c9c806ecf5224e2eb02c49a704b40432..f0f8928b3c8a2902295ccfdf4803b43e00f3a0c9 100644 (file)
@@ -292,7 +292,6 @@ static int evdev_release(struct inode *inode, struct file *file)
        kfree(client);
 
        evdev_close_device(evdev);
-       put_device(&evdev->dev);
 
        return 0;
 }
@@ -331,7 +330,6 @@ static int evdev_open(struct inode *inode, struct file *file)
        file->private_data = client;
        nonseekable_open(inode, file);
 
-       get_device(&evdev->dev);
        return 0;
 
  err_free_client:
@@ -1001,6 +999,7 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
                goto err_free_evdev;
 
        cdev_init(&evdev->cdev, &evdev_fops);
+       evdev->cdev.kobj.parent = &evdev->dev.kobj;
        error = cdev_add(&evdev->cdev, evdev->dev.devt, 1);
        if (error)
                goto err_unregister_handle;
index c0ec7d42c3be05ffd574daec1870d44d560ed15a..1abbc170d8b77f302154323a0ea944474bfd5d37 100644 (file)
@@ -26,10 +26,14 @@ static void copy_abs(struct input_dev *dev, unsigned int dst, unsigned int src)
  * input_mt_init_slots() - initialize MT input slots
  * @dev: input device supporting MT events and finger tracking
  * @num_slots: number of slots used by the device
+ * @flags: mt tasks to handle in core
  *
  * This function allocates all necessary memory for MT slot handling
  * in the input device, prepares the ABS_MT_SLOT and
  * ABS_MT_TRACKING_ID events for use and sets up appropriate buffers.
+ * Depending on the flags set, it also performs pointer emulation and
+ * frame synchronization.
+ *
  * May be called repeatedly. Returns -EINVAL if attempting to
  * reinitialize with a different number of slots.
  */
index b62b5891f3999573893c732297ecd0467a094147..f362883c94e37ce828d18938b7d25790135cf2d1 100644 (file)
@@ -243,7 +243,6 @@ static int joydev_release(struct inode *inode, struct file *file)
        kfree(client);
 
        joydev_close_device(joydev);
-       put_device(&joydev->dev);
 
        return 0;
 }
@@ -270,7 +269,6 @@ static int joydev_open(struct inode *inode, struct file *file)
        file->private_data = client;
        nonseekable_open(inode, file);
 
-       get_device(&joydev->dev);
        return 0;
 
  err_free_client:
@@ -858,6 +856,7 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
                goto err_free_joydev;
 
        cdev_init(&joydev->cdev, &joydev_fops);
+       joydev->cdev.kobj.parent = &joydev->dev.kobj;
        error = cdev_add(&joydev->cdev, joydev->dev.devt, 1);
        if (error)
                goto err_unregister_handle;
index b4b65af8612a3f03a79ea19422873cd777f39b76..de0874054e9faebde97690fdb23986d268cbf95d 100644 (file)
@@ -335,6 +335,7 @@ config KEYBOARD_LOCOMO
 config KEYBOARD_LPC32XX
        tristate "LPC32XX matrix key scanner support"
        depends on ARCH_LPC32XX && OF
+       select INPUT_MATRIXKMAP
        help
          Say Y here if you want to use NXP LPC32XX SoC key scanner interface,
          connected to a key matrix.
index 803ff6fe021ec001393a5a9844dd825cbcb6235d..cad9d5dd597330b2eaa523b046f33edddb3641bb 100644 (file)
@@ -368,6 +368,9 @@ static void pxa27x_keypad_config(struct pxa27x_keypad *keypad)
        unsigned int mask = 0, direct_key_num = 0;
        unsigned long kpc = 0;
 
+       /* clear pending interrupt bit */
+       keypad_readl(KPC);
+
        /* enable matrix keys with automatic scan */
        if (pdata->matrix_key_rows && pdata->matrix_key_cols) {
                kpc |= KPC_ASACT | KPC_MIE | KPC_ME | KPC_MS_ALL;
index 7c0f1ecfdd7a3ff88fed02671e1cf0fba5847b24..104a7c3153c0c4ce5fd695403bfb8a263da992d7 100644 (file)
@@ -72,6 +72,16 @@ config INPUT_AD714X_SPI
          To compile this driver as a module, choose M here: the
          module will be called ad714x-spi.
 
+config INPUT_ARIZONA_HAPTICS
+       tristate "Arizona haptics support"
+       depends on MFD_ARIZONA && SND_SOC
+       select INPUT_FF_MEMLESS
+       help
+         Say Y to enable support for the haptics module in Arizona CODECs.
+
+         To compile this driver as a module, choose M here: the
+         module will be called arizona-haptics.
+
 config INPUT_BMA150
        tristate "BMA150/SMB380 acceleration sensor support"
        depends on I2C
index 83fe6f5b77d120e9b3194325f0fc83879a474a0a..5ea769eda999ff1fa35954bdc6bf467c22ebbf99 100644 (file)
@@ -14,6 +14,7 @@ obj-$(CONFIG_INPUT_ADXL34X)           += adxl34x.o
 obj-$(CONFIG_INPUT_ADXL34X_I2C)                += adxl34x-i2c.o
 obj-$(CONFIG_INPUT_ADXL34X_SPI)                += adxl34x-spi.o
 obj-$(CONFIG_INPUT_APANEL)             += apanel.o
+obj-$(CONFIG_INPUT_ARIZONA_HAPTICS)    += arizona-haptics.o
 obj-$(CONFIG_INPUT_ATI_REMOTE2)                += ati_remote2.o
 obj-$(CONFIG_INPUT_ATLAS_BTNS)         += atlas_btns.o
 obj-$(CONFIG_INPUT_BFIN_ROTARY)                += bfin_rotary.o
diff --git a/drivers/input/misc/arizona-haptics.c b/drivers/input/misc/arizona-haptics.c
new file mode 100644 (file)
index 0000000..7a04f54
--- /dev/null
@@ -0,0 +1,255 @@
+/*
+ * Arizona haptics driver
+ *
+ * Copyright 2012 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include <linux/mfd/arizona/core.h>
+#include <linux/mfd/arizona/pdata.h>
+#include <linux/mfd/arizona/registers.h>
+
+struct arizona_haptics {
+       struct arizona *arizona;
+       struct input_dev *input_dev;
+       struct work_struct work;
+
+       struct mutex mutex;
+       u8 intensity;
+};
+
+static void arizona_haptics_work(struct work_struct *work)
+{
+       struct arizona_haptics *haptics = container_of(work,
+                                                      struct arizona_haptics,
+                                                      work);
+       struct arizona *arizona = haptics->arizona;
+       struct mutex *dapm_mutex = &arizona->dapm->card->dapm_mutex;
+       int ret;
+
+       if (!haptics->arizona->dapm) {
+               dev_err(arizona->dev, "No DAPM context\n");
+               return;
+       }
+
+       if (haptics->intensity) {
+               ret = regmap_update_bits(arizona->regmap,
+                                        ARIZONA_HAPTICS_PHASE_2_INTENSITY,
+                                        ARIZONA_PHASE2_INTENSITY_MASK,
+                                        haptics->intensity);
+               if (ret != 0) {
+                       dev_err(arizona->dev, "Failed to set intensity: %d\n",
+                               ret);
+                       return;
+               }
+
+               /* This enable sequence will be a noop if already enabled */
+               ret = regmap_update_bits(arizona->regmap,
+                                        ARIZONA_HAPTICS_CONTROL_1,
+                                        ARIZONA_HAP_CTRL_MASK,
+                                        1 << ARIZONA_HAP_CTRL_SHIFT);
+               if (ret != 0) {
+                       dev_err(arizona->dev, "Failed to start haptics: %d\n",
+                               ret);
+                       return;
+               }
+
+               mutex_lock_nested(dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
+
+               ret = snd_soc_dapm_enable_pin(arizona->dapm, "HAPTICS");
+               if (ret != 0) {
+                       dev_err(arizona->dev, "Failed to start HAPTICS: %d\n",
+                               ret);
+                       mutex_unlock(dapm_mutex);
+                       return;
+               }
+
+               ret = snd_soc_dapm_sync(arizona->dapm);
+               if (ret != 0) {
+                       dev_err(arizona->dev, "Failed to sync DAPM: %d\n",
+                               ret);
+                       mutex_unlock(dapm_mutex);
+                       return;
+               }
+
+               mutex_unlock(dapm_mutex);
+
+       } else {
+               /* This disable sequence will be a noop if already enabled */
+               mutex_lock_nested(dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
+
+               ret = snd_soc_dapm_disable_pin(arizona->dapm, "HAPTICS");
+               if (ret != 0) {
+                       dev_err(arizona->dev, "Failed to disable HAPTICS: %d\n",
+                               ret);
+                       mutex_unlock(dapm_mutex);
+                       return;
+               }
+
+               ret = snd_soc_dapm_sync(arizona->dapm);
+               if (ret != 0) {
+                       dev_err(arizona->dev, "Failed to sync DAPM: %d\n",
+                               ret);
+                       mutex_unlock(dapm_mutex);
+                       return;
+               }
+
+               mutex_unlock(dapm_mutex);
+
+               ret = regmap_update_bits(arizona->regmap,
+                                        ARIZONA_HAPTICS_CONTROL_1,
+                                        ARIZONA_HAP_CTRL_MASK,
+                                        1 << ARIZONA_HAP_CTRL_SHIFT);
+               if (ret != 0) {
+                       dev_err(arizona->dev, "Failed to stop haptics: %d\n",
+                               ret);
+                       return;
+               }
+       }
+}
+
+static int arizona_haptics_play(struct input_dev *input, void *data,
+                               struct ff_effect *effect)
+{
+       struct arizona_haptics *haptics = input_get_drvdata(input);
+       struct arizona *arizona = haptics->arizona;
+
+       if (!arizona->dapm) {
+               dev_err(arizona->dev, "No DAPM context\n");
+               return -EBUSY;
+       }
+
+       if (effect->u.rumble.strong_magnitude) {
+               /* Scale the magnitude into the range the device supports */
+               if (arizona->pdata.hap_act) {
+                       haptics->intensity =
+                               effect->u.rumble.strong_magnitude >> 9;
+                       if (effect->direction < 0x8000)
+                               haptics->intensity += 0x7f;
+               } else {
+                       haptics->intensity =
+                               effect->u.rumble.strong_magnitude >> 8;
+               }
+       } else {
+               haptics->intensity = 0;
+       }
+
+       schedule_work(&haptics->work);
+
+       return 0;
+}
+
+static void arizona_haptics_close(struct input_dev *input)
+{
+       struct arizona_haptics *haptics = input_get_drvdata(input);
+       struct mutex *dapm_mutex = &haptics->arizona->dapm->card->dapm_mutex;
+
+       cancel_work_sync(&haptics->work);
+
+       mutex_lock_nested(dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
+
+       if (haptics->arizona->dapm)
+               snd_soc_dapm_disable_pin(haptics->arizona->dapm, "HAPTICS");
+
+       mutex_unlock(dapm_mutex);
+}
+
+static int arizona_haptics_probe(struct platform_device *pdev)
+{
+       struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
+       struct arizona_haptics *haptics;
+       int ret;
+
+       haptics = devm_kzalloc(&pdev->dev, sizeof(*haptics), GFP_KERNEL);
+       if (!haptics)
+               return -ENOMEM;
+
+       haptics->arizona = arizona;
+
+       ret = regmap_update_bits(arizona->regmap, ARIZONA_HAPTICS_CONTROL_1,
+                                ARIZONA_HAP_ACT, arizona->pdata.hap_act);
+       if (ret != 0) {
+               dev_err(arizona->dev, "Failed to set haptics actuator: %d\n",
+                       ret);
+               return ret;
+       }
+
+       INIT_WORK(&haptics->work, arizona_haptics_work);
+
+       haptics->input_dev = input_allocate_device();
+       if (haptics->input_dev == NULL) {
+               dev_err(arizona->dev, "Failed to allocate input device\n");
+               return -ENOMEM;
+       }
+
+       input_set_drvdata(haptics->input_dev, haptics);
+
+       haptics->input_dev->name = "arizona:haptics";
+       haptics->input_dev->dev.parent = pdev->dev.parent;
+       haptics->input_dev->close = arizona_haptics_close;
+       __set_bit(FF_RUMBLE, haptics->input_dev->ffbit);
+
+       ret = input_ff_create_memless(haptics->input_dev, NULL,
+                                     arizona_haptics_play);
+       if (ret < 0) {
+               dev_err(arizona->dev, "input_ff_create_memless() failed: %d\n",
+                       ret);
+               goto err_ialloc;
+       }
+
+       ret = input_register_device(haptics->input_dev);
+       if (ret < 0) {
+               dev_err(arizona->dev, "couldn't register input device: %d\n",
+                       ret);
+               goto err_iff;
+       }
+
+       platform_set_drvdata(pdev, haptics);
+
+       return 0;
+
+err_iff:
+       if (haptics->input_dev)
+               input_ff_destroy(haptics->input_dev);
+err_ialloc:
+       input_free_device(haptics->input_dev);
+
+       return ret;
+}
+
+static int arizona_haptics_remove(struct platform_device *pdev)
+{
+       struct arizona_haptics *haptics = platform_get_drvdata(pdev);
+
+       input_unregister_device(haptics->input_dev);
+
+       return 0;
+}
+
+static struct platform_driver arizona_haptics_driver = {
+       .probe          = arizona_haptics_probe,
+       .remove         = arizona_haptics_remove,
+       .driver         = {
+               .name   = "arizona-haptics",
+               .owner  = THIS_MODULE,
+       },
+};
+module_platform_driver(arizona_haptics_driver);
+
+MODULE_ALIAS("platform:arizona-haptics");
+MODULE_DESCRIPTION("Arizona haptics driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
index 02ca8680ea5b8f68393cecc3925792fc74236614..6f7d99013031b66f16d2c4e25f06dd3c352a622c 100644 (file)
@@ -311,7 +311,6 @@ static void xenkbd_backend_changed(struct xenbus_device *dev,
        case XenbusStateReconfiguring:
        case XenbusStateReconfigured:
        case XenbusStateUnknown:
-       case XenbusStateClosed:
                break;
 
        case XenbusStateInitWait:
@@ -350,6 +349,10 @@ InitWait:
 
                break;
 
+       case XenbusStateClosed:
+               if (dev->state == XenbusStateClosed)
+                       break;
+               /* Missed the backend's CLOSING state -- fallthrough */
        case XenbusStateClosing:
                xenbus_frontend_closed(dev);
                break;
index 3a78f235fa3e70b8057b929a2c4e2e763141cd9f..2baff1b79a5596eb33eaaaa31577c193d80f099e 100644 (file)
 #define USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI   0x0262
 #define USB_DEVICE_ID_APPLE_WELLSPRING7_ISO    0x0263
 #define USB_DEVICE_ID_APPLE_WELLSPRING7_JIS    0x0264
+/* MacbookPro10,2 (unibody, October 2012) */
+#define USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI  0x0259
+#define USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO   0x025a
+#define USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS   0x025b
 
 #define BCM5974_DEVICE(prod) {                                 \
        .match_flags = (USB_DEVICE_ID_MATCH_DEVICE |            \
@@ -137,6 +141,10 @@ static const struct usb_device_id bcm5974_table[] = {
        BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI),
        BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7_ISO),
        BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7_JIS),
+       /* MacbookPro10,2 */
+       BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI),
+       BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO),
+       BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS),
        /* Terminating entry */
        {}
 };
@@ -379,6 +387,19 @@ static const struct bcm5974_config bcm5974_config_table[] = {
                { SN_COORD, -150, 6730 },
                { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
        },
+       {
+               USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI,
+               USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO,
+               USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS,
+               HAS_INTEGRATED_BUTTON,
+               0x84, sizeof(struct bt_data),
+               0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
+               { SN_PRESSURE, 0, 300 },
+               { SN_WIDTH, 0, 2048 },
+               { SN_COORD, -4750, 5280 },
+               { SN_COORD, -150, 6730 },
+               { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
+       },
        {}
 };
 
index a1b4c37956b2ef3af055e5c66ccd7753225cabeb..4c842c320c2ede9f2bf42d507ee5c91f00eef7e3 100644 (file)
@@ -12,8 +12,8 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #define MOUSEDEV_MINOR_BASE    32
-#define MOUSEDEV_MINORS                32
-#define MOUSEDEV_MIX           31
+#define MOUSEDEV_MINORS                31
+#define MOUSEDEV_MIX           63
 
 #include <linux/sched.h>
 #include <linux/slab.h>
@@ -523,7 +523,6 @@ static int mousedev_release(struct inode *inode, struct file *file)
        kfree(client);
 
        mousedev_close_device(mousedev);
-       put_device(&mousedev->dev);
 
        return 0;
 }
@@ -558,7 +557,6 @@ static int mousedev_open(struct inode *inode, struct file *file)
        file->private_data = client;
        nonseekable_open(inode, file);
 
-       get_device(&mousedev->dev);
        return 0;
 
  err_free_client:
@@ -892,6 +890,7 @@ static struct mousedev *mousedev_create(struct input_dev *dev,
        }
 
        cdev_init(&mousedev->cdev, &mousedev_fops);
+       mousedev->cdev.kobj.parent = &mousedev->dev.kobj;
        error = cdev_add(&mousedev->cdev, mousedev->dev.devt, 1);
        if (error)
                goto err_unregister_handle;
index 9edf9806cff9db6350e4e25677fb74177364251a..858ad446de91b338553d6577bb6d1ac886c1fbb5 100644 (file)
@@ -391,7 +391,7 @@ static int wacom_parse_hid(struct usb_interface *intf,
                                                        features->pktlen = WACOM_PKGLEN_TPC2FG;
                                                }
 
-                                               if (features->type == MTSCREEN)
+                                               if (features->type == MTSCREEN || features->type == WACOM_24HDT)
                                                        features->pktlen = WACOM_PKGLEN_MTOUCH;
 
                                                if (features->type == BAMBOO_PT) {
@@ -402,6 +402,14 @@ static int wacom_parse_hid(struct usb_interface *intf,
                                                        features->x_max =
                                                                get_unaligned_le16(&report[i + 8]);
                                                        i += 15;
+                                               } else if (features->type == WACOM_24HDT) {
+                                                       features->x_max =
+                                                               get_unaligned_le16(&report[i + 3]);
+                                                       features->x_phy =
+                                                               get_unaligned_le16(&report[i + 8]);
+                                                       features->unit = report[i - 1];
+                                                       features->unitExpo = report[i - 3];
+                                                       i += 12;
                                                } else {
                                                        features->x_max =
                                                                get_unaligned_le16(&report[i + 3]);
@@ -434,6 +442,12 @@ static int wacom_parse_hid(struct usb_interface *intf,
                                                        features->y_phy =
                                                                get_unaligned_le16(&report[i + 6]);
                                                        i += 7;
+                                               } else if (type == WACOM_24HDT) {
+                                                       features->y_max =
+                                                               get_unaligned_le16(&report[i + 3]);
+                                                       features->y_phy =
+                                                               get_unaligned_le16(&report[i - 2]);
+                                                       i += 7;
                                                } else if (type == BAMBOO_PT) {
                                                        features->y_phy =
                                                                get_unaligned_le16(&report[i + 3]);
@@ -541,6 +555,9 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat
                        /* MT Tablet PC touch */
                        return wacom_set_device_mode(intf, 3, 4, 4);
                }
+               else if (features->type == WACOM_24HDT) {
+                       return wacom_set_device_mode(intf, 18, 3, 2);
+               }
        } else if (features->device_type == BTN_TOOL_PEN) {
                if (features->type <= BAMBOO_PT && features->type != WIRELESS) {
                        return wacom_set_device_mode(intf, 2, 2, 2);
@@ -613,6 +630,30 @@ struct wacom_usbdev_data {
 static LIST_HEAD(wacom_udev_list);
 static DEFINE_MUTEX(wacom_udev_list_lock);
 
+static struct usb_device *wacom_get_sibling(struct usb_device *dev, int vendor, int product)
+{
+       int port1;
+       struct usb_device *sibling;
+
+       if (vendor == 0 && product == 0)
+               return dev;
+
+       if (dev->parent == NULL)
+               return NULL;
+
+       usb_hub_for_each_child(dev->parent, port1, sibling) {
+               struct usb_device_descriptor *d;
+               if (sibling == NULL)
+                       continue;
+
+               d = &sibling->descriptor;
+               if (d->idVendor == vendor && d->idProduct == product)
+                       return sibling;
+       }
+
+       return NULL;
+}
+
 static struct wacom_usbdev_data *wacom_get_usbdev_data(struct usb_device *dev)
 {
        struct wacom_usbdev_data *data;
@@ -1257,13 +1298,19 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
        strlcpy(wacom_wac->name, features->name, sizeof(wacom_wac->name));
 
        if (features->quirks & WACOM_QUIRK_MULTI_INPUT) {
+               struct usb_device *other_dev;
+
                /* Append the device type to the name */
                strlcat(wacom_wac->name,
                        features->device_type == BTN_TOOL_PEN ?
                                " Pen" : " Finger",
                        sizeof(wacom_wac->name));
 
-               error = wacom_add_shared_data(wacom_wac, dev);
+
+               other_dev = wacom_get_sibling(dev, features->oVid, features->oPid);
+               if (other_dev == NULL || wacom_get_usbdev_data(other_dev) == NULL)
+                       other_dev = dev;
+               error = wacom_add_shared_data(wacom_wac, other_dev);
                if (error)
                        goto fail3;
        }
index c3468c8dbd891865b0fd2b4a8159f499ea8df1f1..0a67031ffc131a2559d6573d5c3cf65173edd9c6 100644 (file)
@@ -806,6 +806,70 @@ static int find_slot_from_contactid(struct wacom_wac *wacom, int contactid)
        return -1;
 }
 
+static int int_dist(int x1, int y1, int x2, int y2)
+{
+       int x = x2 - x1;
+       int y = y2 - y1;
+
+       return int_sqrt(x*x + y*y);
+}
+
+static int wacom_24hdt_irq(struct wacom_wac *wacom)
+{
+       struct input_dev *input = wacom->input;
+       char *data = wacom->data;
+       int i;
+       int current_num_contacts = data[61];
+       int contacts_to_send = 0;
+
+       /*
+        * First packet resets the counter since only the first
+        * packet in series will have non-zero current_num_contacts.
+        */
+       if (current_num_contacts)
+               wacom->num_contacts_left = current_num_contacts;
+
+       /* There are at most 4 contacts per packet */
+       contacts_to_send = min(4, wacom->num_contacts_left);
+
+       for (i = 0; i < contacts_to_send; i++) {
+               int offset = (WACOM_BYTES_PER_24HDT_PACKET * i) + 1;
+               bool touch = data[offset] & 0x1 && !wacom->shared->stylus_in_proximity;
+               int id = data[offset + 1];
+               int slot = find_slot_from_contactid(wacom, id);
+
+               if (slot < 0)
+                       continue;
+               input_mt_slot(input, slot);
+               input_mt_report_slot_state(input, MT_TOOL_FINGER, touch);
+
+               if (touch) {
+                       int t_x = le16_to_cpup((__le16 *)&data[offset + 2]);
+                       int c_x = le16_to_cpup((__le16 *)&data[offset + 4]);
+                       int t_y = le16_to_cpup((__le16 *)&data[offset + 6]);
+                       int c_y = le16_to_cpup((__le16 *)&data[offset + 8]);
+                       int w = le16_to_cpup((__le16 *)&data[offset + 10]);
+                       int h = le16_to_cpup((__le16 *)&data[offset + 12]);
+
+                       input_report_abs(input, ABS_MT_POSITION_X, t_x);
+                       input_report_abs(input, ABS_MT_POSITION_Y, t_y);
+                       input_report_abs(input, ABS_MT_TOUCH_MAJOR, min(w,h));
+                       input_report_abs(input, ABS_MT_WIDTH_MAJOR, min(w, h) + int_dist(t_x, t_y, c_x, c_y));
+                       input_report_abs(input, ABS_MT_WIDTH_MINOR, min(w, h));
+                       input_report_abs(input, ABS_MT_ORIENTATION, w > h);
+               }
+               wacom->slots[slot] = touch ? id : -1;
+       }
+
+       input_mt_report_pointer_emulation(input, true);
+
+       wacom->num_contacts_left -= contacts_to_send;
+       if (wacom->num_contacts_left <= 0)
+               wacom->num_contacts_left = 0;
+
+       return 1;
+}
+
 static int wacom_mt_touch(struct wacom_wac *wacom)
 {
        struct input_dev *input = wacom->input;
@@ -1255,6 +1319,10 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
                sync = wacom_intuos_irq(wacom_wac);
                break;
 
+       case WACOM_24HDT:
+               sync = wacom_24hdt_irq(wacom_wac);
+               break;
+
        case INTUOS5S:
        case INTUOS5:
        case INTUOS5L:
@@ -1340,7 +1408,8 @@ void wacom_setup_device_quirks(struct wacom_features *features)
 
        /* these device have multiple inputs */
        if (features->type >= WIRELESS ||
-           (features->type >= INTUOS5S && features->type <= INTUOS5L))
+           (features->type >= INTUOS5S && features->type <= INTUOS5L) ||
+           (features->oVid && features->oPid))
                features->quirks |= WACOM_QUIRK_MULTI_INPUT;
 
        /* quirk for bamboo touch with 2 low res touches */
@@ -1449,6 +1518,9 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
 
                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);
                break;
 
@@ -1575,6 +1647,15 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
                __set_bit(INPUT_PROP_POINTER, input_dev->propbit);
                break;
 
+       case WACOM_24HDT:
+               if (features->device_type == BTN_TOOL_FINGER) {
+                       input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, features->x_max, 0, 0);
+                       input_set_abs_params(input_dev, ABS_MT_WIDTH_MAJOR, 0, features->x_max, 0, 0);
+                       input_set_abs_params(input_dev, ABS_MT_WIDTH_MINOR, 0, features->y_max, 0, 0);
+                       input_set_abs_params(input_dev, ABS_MT_ORIENTATION, 0, 1, 0, 0);
+               }
+               /* fall through */
+
        case MTSCREEN:
                if (features->device_type == BTN_TOOL_FINGER) {
                        wacom_wac->slots = kmalloc(features->touch_max *
@@ -1869,8 +1950,11 @@ static const struct wacom_features wacom_features_0xF4 =
        { "Wacom Cintiq 24HD",       WACOM_PKGLEN_INTUOS,   104480, 65600, 2047,
          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,
-         63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+       { "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 };
+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 };
 static const struct wacom_features wacom_features_0x3F =
        { "Wacom Cintiq 21UX",    WACOM_PKGLEN_INTUOS,    87200, 65600, 1023,
          63, CINTIQ, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
@@ -2113,6 +2197,7 @@ const struct usb_device_id wacom_ids[] = {
        { USB_DEVICE_WACOM(0x47) },
        { USB_DEVICE_WACOM(0xF4) },
        { USB_DEVICE_WACOM(0xF8) },
+       { USB_DEVICE_WACOM(0xF6) },
        { USB_DEVICE_WACOM(0xFA) },
        { USB_DEVICE_LENOVO(0x6004) },
        { }
index 96c185cc301eb95bf062440e59c49114458c0028..345f1e76975ef76ef6b251ae772a7c2b807c21ff 100644 (file)
@@ -29,6 +29,7 @@
 
 /* wacom data size per MT contact */
 #define WACOM_BYTES_PER_MT_PACKET      11
+#define WACOM_BYTES_PER_24HDT_PACKET   14
 
 /* device IDs */
 #define STYLUS_DEVICE_ID       0x02
@@ -49,6 +50,7 @@
 #define WACOM_REPORT_TPCHID            15
 #define WACOM_REPORT_TPCST             16
 #define WACOM_REPORT_TPC1FGE           18
+#define WACOM_REPORT_24HDT             1
 
 /* device quirks */
 #define WACOM_QUIRK_MULTI_INPUT                0x0001
@@ -81,6 +83,7 @@ enum {
        WACOM_MO,
        WIRELESS,
        BAMBOO_PT,
+       WACOM_24HDT,
        TABLETPC,   /* add new TPC below */
        TABLETPCE,
        TABLETPC2FG,
@@ -109,6 +112,8 @@ struct wacom_features {
        int distance_fuzz;
        unsigned quirks;
        unsigned touch_max;
+       int oVid;
+       int oPid;
 };
 
 struct wacom_shared {
index 1ba232cbc09d4e8744e1a827c3939ad7292e85a6..f7668b24c378aeed3b4ca4fc1c09d025255eccc1 100644 (file)
@@ -239,7 +239,7 @@ config TOUCHSCREEN_EETI
 
 config TOUCHSCREEN_EGALAX
        tristate "EETI eGalax multi-touch panel support"
-       depends on I2C
+       depends on I2C && OF
        help
          Say Y here to enable support for I2C connected EETI
          eGalax multi-touch panels.
index f02028ec3db6a6384dc194e7633ee12e8bbb7685..78e5d9ab0ba7fd991e55cff240257248f42b7ba1 100644 (file)
@@ -955,7 +955,8 @@ static int ads7846_resume(struct device *dev)
 
 static SIMPLE_DEV_PM_OPS(ads7846_pm, ads7846_suspend, ads7846_resume);
 
-static int __devinit ads7846_setup_pendown(struct spi_device *spi, struct ads7846 *ts)
+static int __devinit ads7846_setup_pendown(struct spi_device *spi,
+                                          struct ads7846 *ts)
 {
        struct ads7846_platform_data *pdata = spi->dev.platform_data;
        int err;
@@ -981,6 +982,9 @@ static int __devinit ads7846_setup_pendown(struct spi_device *spi, struct ads784
 
                ts->gpio_pendown = pdata->gpio_pendown;
 
+               if (pdata->gpio_pendown_debounce)
+                       gpio_set_debounce(pdata->gpio_pendown,
+                                         pdata->gpio_pendown_debounce);
        } else {
                dev_err(&spi->dev, "no get_pendown_state nor gpio_pendown?\n");
                return -EINVAL;
index c1e3460f1195aed3953c0e09542c9718d8664421..13fa62fdfb0b4160f76484bd2aadc92151597ab8 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/slab.h>
 #include <linux/bitops.h>
 #include <linux/input/mt.h>
+#include <linux/of_gpio.h>
 
 /*
  * Mouse Mode: some panel may configure the controller to mouse mode,
@@ -122,9 +123,17 @@ static irqreturn_t egalax_ts_interrupt(int irq, void *dev_id)
 /* wake up controller by an falling edge of interrupt gpio.  */
 static int egalax_wake_up_device(struct i2c_client *client)
 {
-       int gpio = irq_to_gpio(client->irq);
+       struct device_node *np = client->dev.of_node;
+       int gpio;
        int ret;
 
+       if (!np)
+               return -ENODEV;
+
+       gpio = of_get_named_gpio(np, "wakeup-gpios", 0);
+       if (!gpio_is_valid(gpio))
+               return -ENODEV;
+
        ret = gpio_request(gpio, "egalax_irq");
        if (ret < 0) {
                dev_err(&client->dev,
@@ -181,7 +190,11 @@ static int __devinit egalax_ts_probe(struct i2c_client *client,
        ts->input_dev = input_dev;
 
        /* controller may be in sleep, wake it up. */
-       egalax_wake_up_device(client);
+       error = egalax_wake_up_device(client);
+       if (error) {
+               dev_err(&client->dev, "Failed to wake up the controller\n");
+               goto err_free_dev;
+       }
 
        ret = egalax_firmware_version(client);
        if (ret < 0) {
@@ -274,11 +287,17 @@ static int egalax_ts_resume(struct device *dev)
 
 static SIMPLE_DEV_PM_OPS(egalax_ts_pm_ops, egalax_ts_suspend, egalax_ts_resume);
 
+static struct of_device_id egalax_ts_dt_ids[] = {
+       { .compatible = "eeti,egalax_ts" },
+       { /* sentinel */ }
+};
+
 static struct i2c_driver egalax_ts_driver = {
        .driver = {
                .name   = "egalax_ts",
                .owner  = THIS_MODULE,
                .pm     = &egalax_ts_pm_ops,
+               .of_match_table = of_match_ptr(egalax_ts_dt_ids),
        },
        .id_table       = egalax_ts_id,
        .probe          = egalax_ts_probe,
index 63209aaa55f01f1baf65a8a1632c8c2ce4056870..eb96f168fb9d53c68032c172faec9d2652dcfa70 100644 (file)
@@ -107,7 +107,6 @@ static int tsc_connect(struct serio *serio, struct serio_driver *drv)
        __set_bit(BTN_TOUCH, input_dev->keybit);
        input_set_abs_params(ptsc->dev, ABS_X, 0, 0x3ff, 0, 0);
        input_set_abs_params(ptsc->dev, ABS_Y, 0, 0x3ff, 0, 0);
-       input_set_abs_params(ptsc->dev, ABS_PRESSURE, 0, 0, 0, 0);
 
        serio_set_drvdata(serio, ptsc);
 
index 18b0d99bd4d6686b3727f83896769d0a116dcf1f..81837b0710a9ba0240b1eba3c1b3f8b51d997e2f 100644 (file)
@@ -1599,21 +1599,46 @@ static void __init free_on_init_error(void)
 #endif
 }
 
+/* SB IOAPIC is always on this device in AMD systems */
+#define IOAPIC_SB_DEVID                ((0x00 << 8) | PCI_DEVFN(0x14, 0))
+
 static bool __init check_ioapic_information(void)
 {
+       bool ret, has_sb_ioapic;
        int idx;
 
-       for (idx = 0; idx < nr_ioapics; idx++) {
-               int id = mpc_ioapic_id(idx);
+       has_sb_ioapic = false;
+       ret           = false;
 
-               if (get_ioapic_devid(id) < 0) {
-                       pr_err(FW_BUG "AMD-Vi: IO-APIC[%d] not in IVRS table\n", id);
-                       pr_err("AMD-Vi: Disabling interrupt remapping due to BIOS Bug\n");
-                       return false;
+       for (idx = 0; idx < nr_ioapics; idx++) {
+               int devid, id = mpc_ioapic_id(idx);
+
+               devid = get_ioapic_devid(id);
+               if (devid < 0) {
+                       pr_err(FW_BUG "AMD-Vi: IOAPIC[%d] not in IVRS table\n", id);
+                       ret = false;
+               } else if (devid == IOAPIC_SB_DEVID) {
+                       has_sb_ioapic = true;
+                       ret           = true;
                }
        }
 
-       return true;
+       if (!has_sb_ioapic) {
+               /*
+                * We expect the SB IOAPIC to be listed in the IVRS
+                * table. The system timer is connected to the SB IOAPIC
+                * and if we don't have it in the list the system will
+                * panic at boot time.  This situation usually happens
+                * when the BIOS is buggy and provides us the wrong
+                * device id for the IOAPIC in the system.
+                */
+               pr_err(FW_BUG "AMD-Vi: No southbridge IOAPIC found in IVRS table\n");
+       }
+
+       if (!ret)
+               pr_err("AMD-Vi: Disabling interrupt remapping due to BIOS Bug(s)\n");
+
+       return ret;
 }
 
 static void __init free_dma_resources(void)
index d4a4cd445cabb40504bd2a1c7d5300656feceaff..0badfa48b32b7e84a16449ebc8804e461529c8b9 100644 (file)
@@ -4108,7 +4108,7 @@ static void swap_pci_ref(struct pci_dev **from, struct pci_dev *to)
 static int intel_iommu_add_device(struct device *dev)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
-       struct pci_dev *bridge, *dma_pdev;
+       struct pci_dev *bridge, *dma_pdev = NULL;
        struct iommu_group *group;
        int ret;
 
@@ -4122,7 +4122,7 @@ static int intel_iommu_add_device(struct device *dev)
                        dma_pdev = pci_get_domain_bus_and_slot(
                                                pci_domain_nr(pdev->bus),
                                                bridge->subordinate->number, 0);
-               else
+               if (!dma_pdev)
                        dma_pdev = pci_dev_get(bridge);
        } else
                dma_pdev = pci_dev_get(pdev);
index 0b4d62e0c64573cea96dc38f237436a036aa74cf..c0f7a42662635a288fc8c98fabe3d8f1b35f1141 100644 (file)
@@ -200,7 +200,7 @@ enum {
 
 #define SMMU_ADDR_TO_PFN(addr) ((addr) >> 12)
 #define SMMU_ADDR_TO_PDN(addr) ((addr) >> 22)
-#define SMMU_PDN_TO_ADDR(addr) ((pdn) << 22)
+#define SMMU_PDN_TO_ADDR(pdn)  ((pdn) << 22)
 
 #define _READABLE      (1 << SMMU_PTB_DATA_ASID_READABLE_SHIFT)
 #define _WRITABLE      (1 << SMMU_PTB_DATA_ASID_WRITABLE_SHIFT)
@@ -1054,6 +1054,7 @@ static int smmu_debugfs_stats_show(struct seq_file *s, void *v)
                        stats[i], val, offs);
        }
        seq_printf(s, "\n");
+       dput(dent);
 
        return 0;
 }
index dc670ccc6978614330a85fa4138c0df47febcfba..16c78f1c5ef25ad4121b1ee7e2b7fab30cedce95 100644 (file)
@@ -168,7 +168,8 @@ static int __init armctrl_of_init(struct device_node *node,
 }
 
 static struct of_device_id irq_of_match[] __initconst = {
-       { .compatible = "brcm,bcm2835-armctrl-ic", .data = armctrl_of_init }
+       { .compatible = "brcm,bcm2835-armctrl-ic", .data = armctrl_of_init },
+       { }
 };
 
 void __init bcm2835_init_irq(void)
index a233ed53913a67bb67150ce9d35abf6f8aa42297..86cd75a0e84da69469ef10b5712285f4ce4e84f2 100644 (file)
@@ -4,7 +4,7 @@
 
 menuconfig ISDN
        bool "ISDN support"
-       depends on NET
+       depends on NET && NETDEVICES
        depends on !S390 && !UML
        ---help---
          ISDN ("Integrated Services Digital Network", called RNIS in France)
index 5275887089483b6b8ff8ffdc1e9fad46ac1f81fb..c44950d3eb7b48f8a81fd16db9e46ecd15343a39 100644 (file)
@@ -617,7 +617,13 @@ static void int_in_work(struct work_struct *work)
        if (rc == 0)
                /* success, resubmit interrupt read URB */
                rc = usb_submit_urb(urb, GFP_ATOMIC);
-       if (rc != 0 && rc != -ENODEV) {
+
+       switch (rc) {
+       case 0:         /* success */
+       case -ENODEV:   /* device gone */
+       case -EINVAL:   /* URB already resubmitted, or terminal badness */
+               break;
+       default:        /* failure: try to recover by resetting the device */
                dev_err(cs->dev, "clear halt failed: %s\n", get_usb_rcmsg(rc));
                rc = usb_lock_device_for_reset(ucs->udev, ucs->interface);
                if (rc == 0) {
@@ -2442,7 +2448,9 @@ static void gigaset_disconnect(struct usb_interface *interface)
 }
 
 /* gigaset_suspend
- * This function is called before the USB connection is suspended.
+ * This function is called before the USB connection is suspended
+ * or before the USB device is reset.
+ * In the latter case, message == PMSG_ON.
  */
 static int gigaset_suspend(struct usb_interface *intf, pm_message_t message)
 {
@@ -2498,7 +2506,12 @@ static int gigaset_suspend(struct usb_interface *intf, pm_message_t message)
        del_timer_sync(&ucs->timer_atrdy);
        del_timer_sync(&ucs->timer_cmd_in);
        del_timer_sync(&ucs->timer_int_in);
-       cancel_work_sync(&ucs->int_in_wq);
+
+       /* don't try to cancel int_in_wq from within reset as it
+        * might be the one requesting the reset
+        */
+       if (message.event != PM_EVENT_ON)
+               cancel_work_sync(&ucs->int_in_wq);
 
        gig_dbg(DEBUG_SUSPEND, "suspend complete");
        return 0;
index 2302fbe70ac62badd292a5e455a24042687f2b09..9c6650ea848ece07f2a369cbc0e7a17b26fc035b 100644 (file)
@@ -6,7 +6,7 @@ if ISDN_I4L
 
 config ISDN_PPP
        bool "Support synchronous PPP"
-       depends on INET && NETDEVICES
+       depends on INET
        select SLHC
        help
          Over digital connections such as ISDN, there is no need to
index 8c610fa6782b67925e4c286f651e044a37a53b62..e2a945ee9f05c558eec64ee6a18df91beee318c2 100644 (file)
@@ -1312,7 +1312,6 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg)
                        } else
                                return -EINVAL;
                        break;
-#ifdef CONFIG_NETDEVICES
                case IIOCNETGPN:
                        /* Get peer phone number of a connected
                         * isdn network interface */
@@ -1322,7 +1321,6 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg)
                                return isdn_net_getpeer(&phone, argp);
                        } else
                                return -EINVAL;
-#endif
                default:
                        return -EINVAL;
                }
@@ -1352,7 +1350,6 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg)
                case IIOCNETLCR:
                        printk(KERN_INFO "INFO: ISDN_ABC_LCR_SUPPORT not enabled\n");
                        return -ENODEV;
-#ifdef CONFIG_NETDEVICES
                case IIOCNETAIF:
                        /* Add a network-interface */
                        if (arg) {
@@ -1491,7 +1488,6 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg)
                                return -EFAULT;
                        return isdn_net_force_hangup(name);
                        break;
-#endif                          /* CONFIG_NETDEVICES */
                case IIOCSETVER:
                        dev->net_verbose = arg;
                        printk(KERN_INFO "isdn: Verbose-Level is %d\n", dev->net_verbose);
index b312056da14d3c5f9ef602a455d8bbc80fc8c125..4239b3955ff08f27edacbc4311bb09f93231bd69 100644 (file)
@@ -33,8 +33,6 @@
 struct led_trigger_cpu {
        char name[MAX_NAME_LEN];
        struct led_trigger *_trig;
-       struct mutex lock;
-       int lock_is_inited;
 };
 
 static DEFINE_PER_CPU(struct led_trigger_cpu, cpu_trig);
@@ -50,12 +48,6 @@ void ledtrig_cpu(enum cpu_led_event ledevt)
 {
        struct led_trigger_cpu *trig = &__get_cpu_var(cpu_trig);
 
-       /* mutex lock should be initialized before calling mutex_call() */
-       if (!trig->lock_is_inited)
-               return;
-
-       mutex_lock(&trig->lock);
-
        /* Locate the correct CPU LED */
        switch (ledevt) {
        case CPU_LED_IDLE_END:
@@ -75,8 +67,6 @@ void ledtrig_cpu(enum cpu_led_event ledevt)
                /* Will leave the LED as it is */
                break;
        }
-
-       mutex_unlock(&trig->lock);
 }
 EXPORT_SYMBOL(ledtrig_cpu);
 
@@ -117,14 +107,9 @@ static int __init ledtrig_cpu_init(void)
        for_each_possible_cpu(cpu) {
                struct led_trigger_cpu *trig = &per_cpu(cpu_trig, cpu);
 
-               mutex_init(&trig->lock);
-
                snprintf(trig->name, MAX_NAME_LEN, "cpu%d", cpu);
 
-               mutex_lock(&trig->lock);
                led_trigger_register_simple(trig->name, &trig->_trig);
-               trig->lock_is_inited = 1;
-               mutex_unlock(&trig->lock);
        }
 
        register_syscore_ops(&ledtrig_cpu_syscore_ops);
@@ -142,15 +127,9 @@ static void __exit ledtrig_cpu_exit(void)
        for_each_possible_cpu(cpu) {
                struct led_trigger_cpu *trig = &per_cpu(cpu_trig, cpu);
 
-               mutex_lock(&trig->lock);
-
                led_trigger_unregister_simple(trig->_trig);
                trig->_trig = NULL;
                memset(trig->name, 0, MAX_NAME_LEN);
-               trig->lock_is_inited = 0;
-
-               mutex_unlock(&trig->lock);
-               mutex_destroy(&trig->lock);
        }
 
        unregister_syscore_ops(&ledtrig_cpu_syscore_ops);
index 02db9183ca01e8b64ce54a649dacc943c883f38f..77e6eff41cae9bb7c693aac363c509f65c44251d 100644 (file)
@@ -740,8 +740,14 @@ static void rq_completed(struct mapped_device *md, int rw, int run_queue)
        if (!md_in_flight(md))
                wake_up(&md->wait);
 
+       /*
+        * Run this off this callpath, as drivers could invoke end_io while
+        * inside their request_fn (and holding the queue lock). Calling
+        * back into ->request_fn() could deadlock attempting to grab the
+        * queue lock again.
+        */
        if (run_queue)
-               blk_run_queue(md->queue);
+               blk_run_queue_async(md->queue);
 
        /*
         * dm_put() must be at the end of this function. See the comment above
index 45135f69509c89e83b6cc7190f1f25972ae28076..5e7dc772f5deca223ea9142d073cc66785f54b27 100644 (file)
@@ -315,8 +315,11 @@ static int run(struct mddev *mddev)
        }
        conf->nfaults = 0;
 
-       rdev_for_each(rdev, mddev)
+       rdev_for_each(rdev, mddev) {
                conf->rdev = rdev;
+               disk_stack_limits(mddev->gendisk, rdev->bdev,
+                                 rdev->data_offset << 9);
+       }
 
        md_set_array_sectors(mddev, faulty_size(mddev, 0, 0));
        mddev->private = conf;
index 9ab768acfb623f8bbb13870e5f65150a60ecad07..61200717687b85b3fed040f9599ffd1987b8842d 100644 (file)
@@ -1817,10 +1817,10 @@ retry:
                        memset(bbp, 0xff, PAGE_SIZE);
 
                        for (i = 0 ; i < bb->count ; i++) {
-                               u64 internal_bb = *p++;
+                               u64 internal_bb = p[i];
                                u64 store_bb = ((BB_OFFSET(internal_bb) << 10)
                                                | BB_LEN(internal_bb));
-                               *bbp++ = cpu_to_le64(store_bb);
+                               bbp[i] = cpu_to_le64(store_bb);
                        }
                        bb->changed = 0;
                        if (read_seqretry(&bb->lock, seq))
@@ -5294,7 +5294,7 @@ void md_stop_writes(struct mddev *mddev)
 }
 EXPORT_SYMBOL_GPL(md_stop_writes);
 
-void md_stop(struct mddev *mddev)
+static void __md_stop(struct mddev *mddev)
 {
        mddev->ready = 0;
        mddev->pers->stop(mddev);
@@ -5304,6 +5304,18 @@ void md_stop(struct mddev *mddev)
        mddev->pers = NULL;
        clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
 }
+
+void md_stop(struct mddev *mddev)
+{
+       /* stop the array and free an attached data structures.
+        * This is called from dm-raid
+        */
+       __md_stop(mddev);
+       bitmap_destroy(mddev);
+       if (mddev->bio_set)
+               bioset_free(mddev->bio_set);
+}
+
 EXPORT_SYMBOL_GPL(md_stop);
 
 static int md_set_readonly(struct mddev *mddev, struct block_device *bdev)
@@ -5364,7 +5376,7 @@ static int do_md_stop(struct mddev * mddev, int mode,
                        set_disk_ro(disk, 0);
 
                __md_stop_writes(mddev);
-               md_stop(mddev);
+               __md_stop(mddev);
                mddev->queue->merge_bvec_fn = NULL;
                mddev->queue->backing_dev_info.congested_fn = NULL;
 
@@ -7936,9 +7948,9 @@ int md_is_badblock(struct badblocks *bb, sector_t s, int sectors,
                   sector_t *first_bad, int *bad_sectors)
 {
        int hi;
-       int lo = 0;
+       int lo;
        u64 *p = bb->page;
-       int rv = 0;
+       int rv;
        sector_t target = s + sectors;
        unsigned seq;
 
@@ -7953,7 +7965,8 @@ int md_is_badblock(struct badblocks *bb, sector_t s, int sectors,
 
 retry:
        seq = read_seqbegin(&bb->lock);
-
+       lo = 0;
+       rv = 0;
        hi = bb->count;
 
        /* Binary search between lo and hi for 'target'
index 8034fbd6190ce647ec2feb6a281e4bb32b406f8e..636bae0405e8167edcec328e5759b3f949dd0876 100644 (file)
@@ -2710,7 +2710,7 @@ static struct r1conf *setup_conf(struct mddev *mddev)
                    || disk_idx < 0)
                        continue;
                if (test_bit(Replacement, &rdev->flags))
-                       disk = conf->mirrors + conf->raid_disks + disk_idx;
+                       disk = conf->mirrors + mddev->raid_disks + disk_idx;
                else
                        disk = conf->mirrors + disk_idx;
 
index 906ccbd0f7dcdc6710869c5b990f9375d020d370..0d5d0ff2c0f7beb47a02bd4692273b31369b2bc5 100644 (file)
@@ -499,7 +499,7 @@ static void raid10_end_write_request(struct bio *bio, int error)
         */
        one_write_done(r10_bio);
        if (dec_rdev)
-               rdev_dec_pending(conf->mirrors[dev].rdev, conf->mddev);
+               rdev_dec_pending(rdev, conf->mddev);
 }
 
 /*
@@ -1334,18 +1334,21 @@ retry_write:
                        blocked_rdev = rrdev;
                        break;
                }
+               if (rdev && (test_bit(Faulty, &rdev->flags)
+                            || test_bit(Unmerged, &rdev->flags)))
+                       rdev = NULL;
                if (rrdev && (test_bit(Faulty, &rrdev->flags)
                              || test_bit(Unmerged, &rrdev->flags)))
                        rrdev = NULL;
 
                r10_bio->devs[i].bio = NULL;
                r10_bio->devs[i].repl_bio = NULL;
-               if (!rdev || test_bit(Faulty, &rdev->flags) ||
-                   test_bit(Unmerged, &rdev->flags)) {
+
+               if (!rdev && !rrdev) {
                        set_bit(R10BIO_Degraded, &r10_bio->state);
                        continue;
                }
-               if (test_bit(WriteErrorSeen, &rdev->flags)) {
+               if (rdev && test_bit(WriteErrorSeen, &rdev->flags)) {
                        sector_t first_bad;
                        sector_t dev_sector = r10_bio->devs[i].addr;
                        int bad_sectors;
@@ -1387,8 +1390,10 @@ retry_write:
                                        max_sectors = good_sectors;
                        }
                }
-               r10_bio->devs[i].bio = bio;
-               atomic_inc(&rdev->nr_pending);
+               if (rdev) {
+                       r10_bio->devs[i].bio = bio;
+                       atomic_inc(&rdev->nr_pending);
+               }
                if (rrdev) {
                        r10_bio->devs[i].repl_bio = bio;
                        atomic_inc(&rrdev->nr_pending);
@@ -1444,69 +1449,71 @@ retry_write:
        for (i = 0; i < conf->copies; i++) {
                struct bio *mbio;
                int d = r10_bio->devs[i].devnum;
-               if (!r10_bio->devs[i].bio)
-                       continue;
+               if (r10_bio->devs[i].bio) {
+                       struct md_rdev *rdev = conf->mirrors[d].rdev;
+                       mbio = bio_clone_mddev(bio, GFP_NOIO, mddev);
+                       md_trim_bio(mbio, r10_bio->sector - bio->bi_sector,
+                                   max_sectors);
+                       r10_bio->devs[i].bio = mbio;
+
+                       mbio->bi_sector = (r10_bio->devs[i].addr+
+                                          choose_data_offset(r10_bio,
+                                                             rdev));
+                       mbio->bi_bdev = rdev->bdev;
+                       mbio->bi_end_io = raid10_end_write_request;
+                       mbio->bi_rw = WRITE | do_sync | do_fua | do_discard;
+                       mbio->bi_private = r10_bio;
 
-               mbio = bio_clone_mddev(bio, GFP_NOIO, mddev);
-               md_trim_bio(mbio, r10_bio->sector - bio->bi_sector,
-                           max_sectors);
-               r10_bio->devs[i].bio = mbio;
+                       atomic_inc(&r10_bio->remaining);
 
-               mbio->bi_sector = (r10_bio->devs[i].addr+
-                                  choose_data_offset(r10_bio,
-                                                     conf->mirrors[d].rdev));
-               mbio->bi_bdev = conf->mirrors[d].rdev->bdev;
-               mbio->bi_end_io = raid10_end_write_request;
-               mbio->bi_rw = WRITE | do_sync | do_fua | do_discard;
-               mbio->bi_private = r10_bio;
+                       cb = blk_check_plugged(raid10_unplug, mddev,
+                                              sizeof(*plug));
+                       if (cb)
+                               plug = container_of(cb, struct raid10_plug_cb,
+                                                   cb);
+                       else
+                               plug = NULL;
+                       spin_lock_irqsave(&conf->device_lock, flags);
+                       if (plug) {
+                               bio_list_add(&plug->pending, mbio);
+                               plug->pending_cnt++;
+                       } else {
+                               bio_list_add(&conf->pending_bio_list, mbio);
+                               conf->pending_count++;
+                       }
+                       spin_unlock_irqrestore(&conf->device_lock, flags);
+                       if (!plug)
+                               md_wakeup_thread(mddev->thread);
+               }
 
-               atomic_inc(&r10_bio->remaining);
+               if (r10_bio->devs[i].repl_bio) {
+                       struct md_rdev *rdev = conf->mirrors[d].replacement;
+                       if (rdev == NULL) {
+                               /* Replacement just got moved to main 'rdev' */
+                               smp_mb();
+                               rdev = conf->mirrors[d].rdev;
+                       }
+                       mbio = bio_clone_mddev(bio, GFP_NOIO, mddev);
+                       md_trim_bio(mbio, r10_bio->sector - bio->bi_sector,
+                                   max_sectors);
+                       r10_bio->devs[i].repl_bio = mbio;
+
+                       mbio->bi_sector = (r10_bio->devs[i].addr +
+                                          choose_data_offset(
+                                                  r10_bio, rdev));
+                       mbio->bi_bdev = rdev->bdev;
+                       mbio->bi_end_io = raid10_end_write_request;
+                       mbio->bi_rw = WRITE | do_sync | do_fua | do_discard;
+                       mbio->bi_private = r10_bio;
 
-               cb = blk_check_plugged(raid10_unplug, mddev, sizeof(*plug));
-               if (cb)
-                       plug = container_of(cb, struct raid10_plug_cb, cb);
-               else
-                       plug = NULL;
-               spin_lock_irqsave(&conf->device_lock, flags);
-               if (plug) {
-                       bio_list_add(&plug->pending, mbio);
-                       plug->pending_cnt++;
-               } else {
+                       atomic_inc(&r10_bio->remaining);
+                       spin_lock_irqsave(&conf->device_lock, flags);
                        bio_list_add(&conf->pending_bio_list, mbio);
                        conf->pending_count++;
+                       spin_unlock_irqrestore(&conf->device_lock, flags);
+                       if (!mddev_check_plugged(mddev))
+                               md_wakeup_thread(mddev->thread);
                }
-               spin_unlock_irqrestore(&conf->device_lock, flags);
-               if (!plug)
-                       md_wakeup_thread(mddev->thread);
-
-               if (!r10_bio->devs[i].repl_bio)
-                       continue;
-
-               mbio = bio_clone_mddev(bio, GFP_NOIO, mddev);
-               md_trim_bio(mbio, r10_bio->sector - bio->bi_sector,
-                           max_sectors);
-               r10_bio->devs[i].repl_bio = mbio;
-
-               /* We are actively writing to the original device
-                * so it cannot disappear, so the replacement cannot
-                * become NULL here
-                */
-               mbio->bi_sector = (r10_bio->devs[i].addr +
-                                  choose_data_offset(
-                                          r10_bio,
-                                          conf->mirrors[d].replacement));
-               mbio->bi_bdev = conf->mirrors[d].replacement->bdev;
-               mbio->bi_end_io = raid10_end_write_request;
-               mbio->bi_rw = WRITE | do_sync | do_fua | do_discard;
-               mbio->bi_private = r10_bio;
-
-               atomic_inc(&r10_bio->remaining);
-               spin_lock_irqsave(&conf->device_lock, flags);
-               bio_list_add(&conf->pending_bio_list, mbio);
-               conf->pending_count++;
-               spin_unlock_irqrestore(&conf->device_lock, flags);
-               if (!mddev_check_plugged(mddev))
-                       md_wakeup_thread(mddev->thread);
        }
 
        /* Don't remove the bias on 'remaining' (one_write_done) until
@@ -1783,7 +1790,7 @@ static int raid10_add_disk(struct mddev *mddev, struct md_rdev *rdev)
                clear_bit(Unmerged, &rdev->flags);
        }
        md_integrity_add_rdev(rdev, mddev);
-       if (blk_queue_discard(bdev_get_queue(rdev->bdev)))
+       if (mddev->queue && blk_queue_discard(bdev_get_queue(rdev->bdev)))
                queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mddev->queue);
 
        print_conf(conf);
@@ -3613,11 +3620,14 @@ static int run(struct mddev *mddev)
                        discard_supported = true;
        }
 
-       if (discard_supported)
-               queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mddev->queue);
-       else
-               queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, mddev->queue);
-
+       if (mddev->queue) {
+               if (discard_supported)
+                       queue_flag_set_unlocked(QUEUE_FLAG_DISCARD,
+                                               mddev->queue);
+               else
+                       queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD,
+                                                 mddev->queue);
+       }
        /* need to check that every block has at least one working mirror */
        if (!enough(conf, -1)) {
                printk(KERN_ERR "md/raid10:%s: not enough operational mirrors.\n",
index c5439dce0295078ecf82094af5474a649284ce61..a4502686e7a8763fb5aeded988f026b2a9dd1c99 100644 (file)
@@ -2774,10 +2774,12 @@ static void handle_stripe_clean_event(struct r5conf *conf,
                        dev = &sh->dev[i];
                        if (!test_bit(R5_LOCKED, &dev->flags) &&
                            (test_bit(R5_UPTODATE, &dev->flags) ||
-                            test_and_clear_bit(R5_Discard, &dev->flags))) {
+                            test_bit(R5_Discard, &dev->flags))) {
                                /* We can return any write requests */
                                struct bio *wbi, *wbi2;
                                pr_debug("Return write for disc %d\n", i);
+                               if (test_and_clear_bit(R5_Discard, &dev->flags))
+                                       clear_bit(R5_UPTODATE, &dev->flags);
                                wbi = dev->written;
                                dev->written = NULL;
                                while (wbi && wbi->bi_sector <
@@ -2795,7 +2797,8 @@ static void handle_stripe_clean_event(struct r5conf *conf,
                                         !test_bit(STRIPE_DEGRADED, &sh->state),
                                                0);
                        }
-               }
+               } else if (test_bit(R5_Discard, &sh->dev[i].flags))
+                       clear_bit(R5_Discard, &sh->dev[i].flags);
 
        if (test_and_clear_bit(STRIPE_FULL_WRITE, &sh->state))
                if (atomic_dec_and_test(&conf->pending_full_writes))
@@ -3490,40 +3493,6 @@ static void handle_stripe(struct stripe_head *sh)
                        handle_failed_sync(conf, sh, &s);
        }
 
-       /*
-        * might be able to return some write requests if the parity blocks
-        * are safe, or on a failed drive
-        */
-       pdev = &sh->dev[sh->pd_idx];
-       s.p_failed = (s.failed >= 1 && s.failed_num[0] == sh->pd_idx)
-               || (s.failed >= 2 && s.failed_num[1] == sh->pd_idx);
-       qdev = &sh->dev[sh->qd_idx];
-       s.q_failed = (s.failed >= 1 && s.failed_num[0] == sh->qd_idx)
-               || (s.failed >= 2 && s.failed_num[1] == sh->qd_idx)
-               || conf->level < 6;
-
-       if (s.written &&
-           (s.p_failed || ((test_bit(R5_Insync, &pdev->flags)
-                            && !test_bit(R5_LOCKED, &pdev->flags)
-                            && (test_bit(R5_UPTODATE, &pdev->flags) ||
-                                test_bit(R5_Discard, &pdev->flags))))) &&
-           (s.q_failed || ((test_bit(R5_Insync, &qdev->flags)
-                            && !test_bit(R5_LOCKED, &qdev->flags)
-                            && (test_bit(R5_UPTODATE, &qdev->flags) ||
-                                test_bit(R5_Discard, &qdev->flags))))))
-               handle_stripe_clean_event(conf, sh, disks, &s.return_bi);
-
-       /* Now we might consider reading some blocks, either to check/generate
-        * parity, or to satisfy requests
-        * or to load a block that is being partially written.
-        */
-       if (s.to_read || s.non_overwrite
-           || (conf->level == 6 && s.to_write && s.failed)
-           || (s.syncing && (s.uptodate + s.compute < disks))
-           || s.replacing
-           || s.expanding)
-               handle_stripe_fill(sh, &s, disks);
-
        /* Now we check to see if any write operations have recently
         * completed
         */
@@ -3561,6 +3530,40 @@ static void handle_stripe(struct stripe_head *sh)
                        s.dec_preread_active = 1;
        }
 
+       /*
+        * might be able to return some write requests if the parity blocks
+        * are safe, or on a failed drive
+        */
+       pdev = &sh->dev[sh->pd_idx];
+       s.p_failed = (s.failed >= 1 && s.failed_num[0] == sh->pd_idx)
+               || (s.failed >= 2 && s.failed_num[1] == sh->pd_idx);
+       qdev = &sh->dev[sh->qd_idx];
+       s.q_failed = (s.failed >= 1 && s.failed_num[0] == sh->qd_idx)
+               || (s.failed >= 2 && s.failed_num[1] == sh->qd_idx)
+               || conf->level < 6;
+
+       if (s.written &&
+           (s.p_failed || ((test_bit(R5_Insync, &pdev->flags)
+                            && !test_bit(R5_LOCKED, &pdev->flags)
+                            && (test_bit(R5_UPTODATE, &pdev->flags) ||
+                                test_bit(R5_Discard, &pdev->flags))))) &&
+           (s.q_failed || ((test_bit(R5_Insync, &qdev->flags)
+                            && !test_bit(R5_LOCKED, &qdev->flags)
+                            && (test_bit(R5_UPTODATE, &qdev->flags) ||
+                                test_bit(R5_Discard, &qdev->flags))))))
+               handle_stripe_clean_event(conf, sh, disks, &s.return_bi);
+
+       /* Now we might consider reading some blocks, either to check/generate
+        * parity, or to satisfy requests
+        * or to load a block that is being partially written.
+        */
+       if (s.to_read || s.non_overwrite
+           || (conf->level == 6 && s.to_write && s.failed)
+           || (s.syncing && (s.uptodate + s.compute < disks))
+           || s.replacing
+           || s.expanding)
+               handle_stripe_fill(sh, &s, disks);
+
        /* Now to consider new write requests and what else, if anything
         * should be read.  We do not handle new writes when:
         * 1/ A 'write' operation (copy+xor) is already in flight.
@@ -5529,6 +5532,10 @@ static int run(struct mddev *mddev)
                 * discard data disk but write parity disk
                 */
                stripe = stripe * PAGE_SIZE;
+               /* Round up to power of 2, as discard handling
+                * currently assumes that */
+               while ((stripe-1) & stripe)
+                       stripe = (stripe | (stripe-1)) + 1;
                mddev->queue->limits.discard_alignment = stripe;
                mddev->queue->limits.discard_granularity = stripe;
                /*
index 1b48f2094806c75fa8914657978f1b7bf814ae93..75619711a9e7904000f89b30769a084b4094a27a 100644 (file)
@@ -272,6 +272,7 @@ static struct mfd_cell early_devs[] = {
 static struct mfd_cell wm5102_devs[] = {
        { .name = "arizona-extcon" },
        { .name = "arizona-gpio" },
+       { .name = "arizona-haptics" },
        { .name = "arizona-micsupp" },
        { .name = "arizona-pwm" },
        { .name = "wm5102-codec" },
@@ -280,6 +281,7 @@ static struct mfd_cell wm5102_devs[] = {
 static struct mfd_cell wm5110_devs[] = {
        { .name = "arizona-extcon" },
        { .name = "arizona-gpio" },
+       { .name = "arizona-haptics" },
        { .name = "arizona-micsupp" },
        { .name = "arizona-pwm" },
        { .name = "wm5110-codec" },
index 5bb1877810749da2581aff03c6d7d50c18b875c3..d07a9eda7fff4a29aebc43892658b339b4ebb196 100644 (file)
@@ -18,6 +18,8 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 
+#include <linux/of.h>
+
 /* Serialize access to ssc_list and user count */
 static DEFINE_SPINLOCK(user_lock);
 static LIST_HEAD(ssc_list);
@@ -29,7 +31,13 @@ struct ssc_device *ssc_request(unsigned int ssc_num)
 
        spin_lock(&user_lock);
        list_for_each_entry(ssc, &ssc_list, list) {
-               if (ssc->pdev->id == ssc_num) {
+               if (ssc->pdev->dev.of_node) {
+                       if (of_alias_get_id(ssc->pdev->dev.of_node, "ssc")
+                               == ssc_num) {
+                               ssc_valid = 1;
+                               break;
+                       }
+               } else if (ssc->pdev->id == ssc_num) {
                        ssc_valid = 1;
                        break;
                }
@@ -68,39 +76,93 @@ void ssc_free(struct ssc_device *ssc)
 }
 EXPORT_SYMBOL(ssc_free);
 
-static int __init ssc_probe(struct platform_device *pdev)
+static struct atmel_ssc_platform_data at91rm9200_config = {
+       .use_dma = 0,
+};
+
+static struct atmel_ssc_platform_data at91sam9g45_config = {
+       .use_dma = 1,
+};
+
+static const struct platform_device_id atmel_ssc_devtypes[] = {
+       {
+               .name = "at91rm9200_ssc",
+               .driver_data = (unsigned long) &at91rm9200_config,
+       }, {
+               .name = "at91sam9g45_ssc",
+               .driver_data = (unsigned long) &at91sam9g45_config,
+       }, {
+               /* sentinel */
+       }
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id atmel_ssc_dt_ids[] = {
+       {
+               .compatible = "atmel,at91rm9200-ssc",
+               .data = &at91rm9200_config,
+       }, {
+               .compatible = "atmel,at91sam9g45-ssc",
+               .data = &at91sam9g45_config,
+       }, {
+               /* sentinel */
+       }
+};
+MODULE_DEVICE_TABLE(of, atmel_ssc_dt_ids);
+#endif
+
+static inline const struct atmel_ssc_platform_data * __init
+       atmel_ssc_get_driver_data(struct platform_device *pdev)
+{
+       if (pdev->dev.of_node) {
+               const struct of_device_id *match;
+               match = of_match_node(atmel_ssc_dt_ids, pdev->dev.of_node);
+               if (match == NULL)
+                       return NULL;
+               return match->data;
+       }
+
+       return (struct atmel_ssc_platform_data *)
+               platform_get_device_id(pdev)->driver_data;
+}
+
+static int ssc_probe(struct platform_device *pdev)
 {
-       int retval = 0;
        struct resource *regs;
        struct ssc_device *ssc;
+       const struct atmel_ssc_platform_data *plat_dat;
 
-       ssc = kzalloc(sizeof(struct ssc_device), GFP_KERNEL);
+       ssc = devm_kzalloc(&pdev->dev, sizeof(struct ssc_device), GFP_KERNEL);
        if (!ssc) {
                dev_dbg(&pdev->dev, "out of memory\n");
-               retval = -ENOMEM;
-               goto out;
+               return -ENOMEM;
        }
 
+       ssc->pdev = pdev;
+
+       plat_dat = atmel_ssc_get_driver_data(pdev);
+       if (!plat_dat)
+               return -ENODEV;
+       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");
-               retval = -ENXIO;
-               goto out_free;
+               return -ENXIO;
        }
 
-       ssc->clk = clk_get(&pdev->dev, "pclk");
-       if (IS_ERR(ssc->clk)) {
-               dev_dbg(&pdev->dev, "no pclk clock defined\n");
-               retval = -ENXIO;
-               goto out_free;
-       }
-
-       ssc->pdev = pdev;
-       ssc->regs = ioremap(regs->start, resource_size(regs));
+       ssc->regs = devm_request_and_ioremap(&pdev->dev, regs);
        if (!ssc->regs) {
                dev_dbg(&pdev->dev, "ioremap failed\n");
-               retval = -EINVAL;
-               goto out_clk;
+               return -EINVAL;
+       }
+
+       ssc->phybase = regs->start;
+
+       ssc->clk = devm_clk_get(&pdev->dev, "pclk");
+       if (IS_ERR(ssc->clk)) {
+               dev_dbg(&pdev->dev, "no pclk clock defined\n");
+               return -ENXIO;
        }
 
        /* disable all interrupts */
@@ -112,8 +174,7 @@ static int __init ssc_probe(struct platform_device *pdev)
        ssc->irq = platform_get_irq(pdev, 0);
        if (!ssc->irq) {
                dev_dbg(&pdev->dev, "could not get irq\n");
-               retval = -ENXIO;
-               goto out_unmap;
+               return -ENXIO;
        }
 
        spin_lock(&user_lock);
@@ -125,16 +186,7 @@ static int __init ssc_probe(struct platform_device *pdev)
        dev_info(&pdev->dev, "Atmel SSC device at 0x%p (irq %d)\n",
                        ssc->regs, ssc->irq);
 
-       goto out;
-
-out_unmap:
-       iounmap(ssc->regs);
-out_clk:
-       clk_put(ssc->clk);
-out_free:
-       kfree(ssc);
-out:
-       return retval;
+       return 0;
 }
 
 static int __devexit ssc_remove(struct platform_device *pdev)
@@ -142,34 +194,23 @@ static int __devexit ssc_remove(struct platform_device *pdev)
        struct ssc_device *ssc = platform_get_drvdata(pdev);
 
        spin_lock(&user_lock);
-       iounmap(ssc->regs);
-       clk_put(ssc->clk);
        list_del(&ssc->list);
-       kfree(ssc);
        spin_unlock(&user_lock);
 
        return 0;
 }
 
 static struct platform_driver ssc_driver = {
-       .remove         = __devexit_p(ssc_remove),
        .driver         = {
                .name           = "ssc",
                .owner          = THIS_MODULE,
+               .of_match_table = of_match_ptr(atmel_ssc_dt_ids),
        },
+       .id_table       = atmel_ssc_devtypes,
+       .probe          = ssc_probe,
+       .remove         = __devexit_p(ssc_remove),
 };
-
-static int __init ssc_init(void)
-{
-       return platform_driver_probe(&ssc_driver, ssc_probe);
-}
-module_init(ssc_init);
-
-static void __exit ssc_exit(void)
-{
-       platform_driver_unregister(&ssc_driver);
-}
-module_exit(ssc_exit);
+module_platform_driver(ssc_driver);
 
 MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>");
 MODULE_DESCRIPTION("SSC driver for Atmel AVR32 and AT91");
index 660bbc528862fc67915b79def806cf689d4ac755..4d50da618166e33c03856fe5845e780d785ece46 100644 (file)
@@ -208,7 +208,7 @@ static unsigned long exynos5250_dwmmc_caps[4] = {
        MMC_CAP_CMD23,
 };
 
-static struct dw_mci_drv_data exynos5250_drv_data = {
+static const struct dw_mci_drv_data exynos5250_drv_data = {
        .caps                   = exynos5250_dwmmc_caps,
        .init                   = dw_mci_exynos_priv_init,
        .setup_clock            = dw_mci_exynos_setup_clock,
@@ -220,14 +220,14 @@ static struct dw_mci_drv_data exynos5250_drv_data = {
 
 static const struct of_device_id dw_mci_exynos_match[] = {
        { .compatible = "samsung,exynos5250-dw-mshc",
-                       .data = (void *)&exynos5250_drv_data, },
+                       .data = &exynos5250_drv_data, },
        {},
 };
-MODULE_DEVICE_TABLE(of, dw_mci_pltfm_match);
+MODULE_DEVICE_TABLE(of, dw_mci_exynos_match);
 
 int dw_mci_exynos_probe(struct platform_device *pdev)
 {
-       struct dw_mci_drv_data *drv_data;
+       const struct dw_mci_drv_data *drv_data;
        const struct of_device_id *match;
 
        match = of_match_node(dw_mci_exynos_match, pdev->dev.of_node);
index c960ca7ffbe694fa367ff7ca88c83003b3da59a6..917936bee5d50514103fbe8501a2ee40c0a4db3a 100644 (file)
@@ -24,7 +24,7 @@
 #include "dw_mmc.h"
 
 int dw_mci_pltfm_register(struct platform_device *pdev,
-                               struct dw_mci_drv_data *drv_data)
+                               const struct dw_mci_drv_data *drv_data)
 {
        struct dw_mci *host;
        struct resource *regs;
@@ -50,8 +50,8 @@ int dw_mci_pltfm_register(struct platform_device *pdev,
        if (!host->regs)
                return -ENOMEM;
 
-       if (host->drv_data->init) {
-               ret = host->drv_data->init(host);
+       if (drv_data && drv_data->init) {
+               ret = drv_data->init(host);
                if (ret)
                        return ret;
        }
index 301f24541fc2f20f2b4c65b6cb7a8d05b1f53abe..2ac37b81de4d2774f3f468922284243090f16fd9 100644 (file)
@@ -13,7 +13,7 @@
 #define _DW_MMC_PLTFM_H_
 
 extern int dw_mci_pltfm_register(struct platform_device *pdev,
-                               struct dw_mci_drv_data *drv_data);
+                               const struct dw_mci_drv_data *drv_data);
 extern int __devexit dw_mci_pltfm_remove(struct platform_device *pdev);
 extern const struct dev_pm_ops dw_mci_pltfm_pmops;
 
index c2828f35c3b8812b4de12cb0fd4b75c28fa09bbf..c0667c8af2bd7c78502151e0f6e8a2c3f8e148bc 100644 (file)
@@ -232,6 +232,7 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd)
 {
        struct mmc_data *data;
        struct dw_mci_slot *slot = mmc_priv(mmc);
+       struct dw_mci_drv_data *drv_data = slot->host->drv_data;
        u32 cmdr;
        cmd->error = -EINPROGRESS;
 
@@ -261,8 +262,8 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd)
                        cmdr |= SDMMC_CMD_DAT_WR;
        }
 
-       if (slot->host->drv_data->prepare_command)
-               slot->host->drv_data->prepare_command(slot->host, &cmdr);
+       if (drv_data && drv_data->prepare_command)
+               drv_data->prepare_command(slot->host, &cmdr);
 
        return cmdr;
 }
@@ -434,7 +435,7 @@ static int dw_mci_idmac_init(struct dw_mci *host)
        return 0;
 }
 
-static struct dw_mci_dma_ops dw_mci_idmac_ops = {
+static const struct dw_mci_dma_ops dw_mci_idmac_ops = {
        .init = dw_mci_idmac_init,
        .start = dw_mci_idmac_start_dma,
        .stop = dw_mci_idmac_stop_dma,
@@ -772,6 +773,7 @@ static void dw_mci_request(struct mmc_host *mmc, struct mmc_request *mrq)
 static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
        struct dw_mci_slot *slot = mmc_priv(mmc);
+       struct dw_mci_drv_data *drv_data = slot->host->drv_data;
        u32 regs;
 
        /* set default 1 bit mode */
@@ -807,8 +809,8 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
                slot->clock = ios->clock;
        }
 
-       if (slot->host->drv_data->set_ios)
-               slot->host->drv_data->set_ios(slot->host, ios);
+       if (drv_data && drv_data->set_ios)
+               drv_data->set_ios(slot->host, ios);
 
        switch (ios->power_mode) {
        case MMC_POWER_UP:
@@ -1815,6 +1817,7 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
 {
        struct mmc_host *mmc;
        struct dw_mci_slot *slot;
+       struct dw_mci_drv_data *drv_data = host->drv_data;
        int ctrl_id, ret;
        u8 bus_width;
 
@@ -1854,8 +1857,8 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
        } else {
                ctrl_id = to_platform_device(host->dev)->id;
        }
-       if (host->drv_data && host->drv_data->caps)
-               mmc->caps |= host->drv_data->caps[ctrl_id];
+       if (drv_data && drv_data->caps)
+               mmc->caps |= drv_data->caps[ctrl_id];
 
        if (host->pdata->caps2)
                mmc->caps2 = host->pdata->caps2;
@@ -1867,10 +1870,10 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
        else
                bus_width = 1;
 
-       if (host->drv_data->setup_bus) {
+       if (drv_data && drv_data->setup_bus) {
                struct device_node *slot_np;
                slot_np = dw_mci_of_find_slot_node(host->dev, slot->id);
-               ret = host->drv_data->setup_bus(host, slot_np, bus_width);
+               ret = drv_data->setup_bus(host, slot_np, bus_width);
                if (ret)
                        goto err_setup_bus;
        }
@@ -1968,7 +1971,7 @@ static void dw_mci_init_dma(struct dw_mci *host)
        /* Determine which DMA interface to use */
 #ifdef CONFIG_MMC_DW_IDMAC
        host->dma_ops = &dw_mci_idmac_ops;
-       dev_info(&host->dev, "Using internal DMA controller.\n");
+       dev_info(host->dev, "Using internal DMA controller.\n");
 #endif
 
        if (!host->dma_ops)
@@ -2035,6 +2038,7 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
        struct dw_mci_board *pdata;
        struct device *dev = host->dev;
        struct device_node *np = dev->of_node;
+       struct dw_mci_drv_data *drv_data = host->drv_data;
        int idx, ret;
 
        pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
@@ -2062,8 +2066,8 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
 
        of_property_read_u32(np, "card-detect-delay", &pdata->detect_delay_ms);
 
-       if (host->drv_data->parse_dt) {
-               ret = host->drv_data->parse_dt(host);
+       if (drv_data && drv_data->parse_dt) {
+               ret = drv_data->parse_dt(host);
                if (ret)
                        return ERR_PTR(ret);
        }
@@ -2080,6 +2084,7 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
 
 int dw_mci_probe(struct dw_mci *host)
 {
+       struct dw_mci_drv_data *drv_data = host->drv_data;
        int width, i, ret = 0;
        u32 fifo_size;
        int init_slots = 0;
@@ -2127,8 +2132,8 @@ int dw_mci_probe(struct dw_mci *host)
        else
                host->bus_hz = clk_get_rate(host->ciu_clk);
 
-       if (host->drv_data->setup_clock) {
-               ret = host->drv_data->setup_clock(host);
+       if (drv_data && drv_data->setup_clock) {
+               ret = drv_data->setup_clock(host);
                if (ret) {
                        dev_err(host->dev,
                                "implementation specific clock setup failed\n");
@@ -2228,6 +2233,21 @@ int dw_mci_probe(struct dw_mci *host)
        else
                host->num_slots = ((mci_readl(host, HCON) >> 1) & 0x1F) + 1;
 
+       /*
+        * Enable interrupts for command done, data over, data empty, card det,
+        * receive ready and error such as transmit, receive timeout, crc error
+        */
+       mci_writel(host, RINTSTS, 0xFFFFFFFF);
+       mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER |
+                  SDMMC_INT_TXDR | SDMMC_INT_RXDR |
+                  DW_MCI_ERROR_FLAGS | SDMMC_INT_CD);
+       mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); /* Enable mci interrupt */
+
+       dev_info(host->dev, "DW MMC controller at irq %d, "
+                "%d bit host data width, "
+                "%u deep fifo\n",
+                host->irq, width, fifo_size);
+
        /* We need at least one slot to succeed */
        for (i = 0; i < host->num_slots; i++) {
                ret = dw_mci_init_slot(host, i);
@@ -2257,20 +2277,6 @@ int dw_mci_probe(struct dw_mci *host)
        else
                host->data_offset = DATA_240A_OFFSET;
 
-       /*
-        * Enable interrupts for command done, data over, data empty, card det,
-        * receive ready and error such as transmit, receive timeout, crc error
-        */
-       mci_writel(host, RINTSTS, 0xFFFFFFFF);
-       mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER |
-                  SDMMC_INT_TXDR | SDMMC_INT_RXDR |
-                  DW_MCI_ERROR_FLAGS | SDMMC_INT_CD);
-       mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); /* Enable mci interrupt */
-
-       dev_info(host->dev, "DW MMC controller at irq %d, "
-                "%d bit host data width, "
-                "%u deep fifo\n",
-                host->irq, width, fifo_size);
        if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO)
                dev_info(host->dev, "Internal DMAC interrupt fix enabled.\n");
 
index 565c2e4fac75cecd8890ec2d9885ffb50cc23060..6290b7f1ccfec2d56f31675663923e057a1570c8 100644 (file)
@@ -1134,4 +1134,4 @@ module_platform_driver(mxcmci_driver);
 MODULE_DESCRIPTION("i.MX Multimedia Card Interface Driver");
 MODULE_AUTHOR("Sascha Hauer, Pengutronix");
 MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:imx-mmc");
+MODULE_ALIAS("platform:mxc-mmc");
index 54bfd0cc106b92280cd75818310d81aa56c48ccb..fedd258cc4ea2effe547f1fc15729f60277d8c33 100644 (file)
@@ -178,7 +178,8 @@ struct omap_hsmmc_host {
 
 static int omap_hsmmc_card_detect(struct device *dev, int slot)
 {
-       struct omap_mmc_platform_data *mmc = dev->platform_data;
+       struct omap_hsmmc_host *host = dev_get_drvdata(dev);
+       struct omap_mmc_platform_data *mmc = host->pdata;
 
        /* NOTE: assumes card detect signal is active-low */
        return !gpio_get_value_cansleep(mmc->slots[0].switch_pin);
@@ -186,7 +187,8 @@ static int omap_hsmmc_card_detect(struct device *dev, int slot)
 
 static int omap_hsmmc_get_wp(struct device *dev, int slot)
 {
-       struct omap_mmc_platform_data *mmc = dev->platform_data;
+       struct omap_hsmmc_host *host = dev_get_drvdata(dev);
+       struct omap_mmc_platform_data *mmc = host->pdata;
 
        /* NOTE: assumes write protect signal is active-high */
        return gpio_get_value_cansleep(mmc->slots[0].gpio_wp);
@@ -194,7 +196,8 @@ static int omap_hsmmc_get_wp(struct device *dev, int slot)
 
 static int omap_hsmmc_get_cover_state(struct device *dev, int slot)
 {
-       struct omap_mmc_platform_data *mmc = dev->platform_data;
+       struct omap_hsmmc_host *host = dev_get_drvdata(dev);
+       struct omap_mmc_platform_data *mmc = host->pdata;
 
        /* NOTE: assumes card detect signal is active-low */
        return !gpio_get_value_cansleep(mmc->slots[0].switch_pin);
@@ -204,7 +207,8 @@ static int omap_hsmmc_get_cover_state(struct device *dev, int slot)
 
 static int omap_hsmmc_suspend_cdirq(struct device *dev, int slot)
 {
-       struct omap_mmc_platform_data *mmc = dev->platform_data;
+       struct omap_hsmmc_host *host = dev_get_drvdata(dev);
+       struct omap_mmc_platform_data *mmc = host->pdata;
 
        disable_irq(mmc->slots[0].card_detect_irq);
        return 0;
@@ -212,7 +216,8 @@ static int omap_hsmmc_suspend_cdirq(struct device *dev, int slot)
 
 static int omap_hsmmc_resume_cdirq(struct device *dev, int slot)
 {
-       struct omap_mmc_platform_data *mmc = dev->platform_data;
+       struct omap_hsmmc_host *host = dev_get_drvdata(dev);
+       struct omap_mmc_platform_data *mmc = host->pdata;
 
        enable_irq(mmc->slots[0].card_detect_irq);
        return 0;
@@ -2009,9 +2014,9 @@ static int __devexit omap_hsmmc_remove(struct platform_device *pdev)
                clk_put(host->dbclk);
        }
 
-       mmc_free_host(host->mmc);
+       omap_hsmmc_gpio_free(host->pdata);
        iounmap(host->base);
-       omap_hsmmc_gpio_free(pdev->dev.platform_data);
+       mmc_free_host(host->mmc);
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (res)
index 90140eb03e36a2766ffc40470271a0e63be34845..8fd50a211037126df4a4beea26dd6fc3aaa71c94 100644 (file)
@@ -19,6 +19,7 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/err.h>
 #include <linux/io.h>
 #include <linux/clk.h>
 #include <linux/err.h>
@@ -84,30 +85,32 @@ static int __devinit sdhci_dove_probe(struct platform_device *pdev)
        struct sdhci_dove_priv *priv;
        int ret;
 
-       ret = sdhci_pltfm_register(pdev, &sdhci_dove_pdata);
-       if (ret)
-               goto sdhci_dove_register_fail;
-
        priv = devm_kzalloc(&pdev->dev, sizeof(struct sdhci_dove_priv),
                            GFP_KERNEL);
        if (!priv) {
                dev_err(&pdev->dev, "unable to allocate private data");
-               ret = -ENOMEM;
-               goto sdhci_dove_allocate_fail;
+               return -ENOMEM;
        }
 
+       priv->clk = clk_get(&pdev->dev, NULL);
+       if (!IS_ERR(priv->clk))
+               clk_prepare_enable(priv->clk);
+
+       ret = sdhci_pltfm_register(pdev, &sdhci_dove_pdata);
+       if (ret)
+               goto sdhci_dove_register_fail;
+
        host = platform_get_drvdata(pdev);
        pltfm_host = sdhci_priv(host);
        pltfm_host->priv = priv;
 
-       priv->clk = clk_get(&pdev->dev, NULL);
-       if (!IS_ERR(priv->clk))
-               clk_prepare_enable(priv->clk);
        return 0;
 
-sdhci_dove_allocate_fail:
-       sdhci_pltfm_unregister(pdev);
 sdhci_dove_register_fail:
+       if (!IS_ERR(priv->clk)) {
+               clk_disable_unprepare(priv->clk);
+               clk_put(priv->clk);
+       }
        return ret;
 }
 
@@ -117,14 +120,13 @@ static int __devexit sdhci_dove_remove(struct platform_device *pdev)
        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
        struct sdhci_dove_priv *priv = pltfm_host->priv;
 
-       if (priv->clk) {
-               if (!IS_ERR(priv->clk)) {
-                       clk_disable_unprepare(priv->clk);
-                       clk_put(priv->clk);
-               }
-               devm_kfree(&pdev->dev, priv->clk);
+       sdhci_pltfm_unregister(pdev);
+
+       if (!IS_ERR(priv->clk)) {
+               clk_disable_unprepare(priv->clk);
+               clk_put(priv->clk);
        }
-       return sdhci_pltfm_unregister(pdev);
+       return 0;
 }
 
 static const struct of_device_id sdhci_dove_of_match_table[] __devinitdata = {
index ae5fcbfa1eef5986ec832616ed1ad350106e64ef..63d219f57caebcd3a4cd0216ec17aca2500cb257 100644 (file)
@@ -169,6 +169,16 @@ static void esdhc_of_resume(struct sdhci_host *host)
 }
 #endif
 
+static void esdhc_of_platform_init(struct sdhci_host *host)
+{
+       u32 vvn;
+
+       vvn = in_be32(host->ioaddr + SDHCI_SLOT_INT_STATUS);
+       vvn = (vvn & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT;
+       if (vvn == VENDOR_V_22)
+               host->quirks2 |= SDHCI_QUIRK2_HOST_NO_CMD23;
+}
+
 static struct sdhci_ops sdhci_esdhc_ops = {
        .read_l = esdhc_readl,
        .read_w = esdhc_readw,
@@ -180,6 +190,7 @@ static struct sdhci_ops sdhci_esdhc_ops = {
        .enable_dma = esdhc_of_enable_dma,
        .get_max_clock = esdhc_of_get_max_clock,
        .get_min_clock = esdhc_of_get_min_clock,
+       .platform_init = esdhc_of_platform_init,
 #ifdef CONFIG_PM
        .platform_suspend = esdhc_of_suspend,
        .platform_resume = esdhc_of_resume,
index 4bb74b042a06483cb3cea750dac26f56c4ab68cd..04936f353ced53461a35545b22add0460c582d3a 100644 (file)
@@ -1196,7 +1196,7 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot(
                return ERR_PTR(-ENODEV);
        }
 
-       if (pci_resource_len(pdev, bar) != 0x100) {
+       if (pci_resource_len(pdev, bar) < 0x100) {
                dev_err(&pdev->dev, "Invalid iomem size. You may "
                        "experience problems.\n");
        }
index 65551a9709ccc86e893be96dfead3fe2919677e3..27164457f861dce37da3e12b00b399bf81b00e1e 100644 (file)
@@ -150,6 +150,13 @@ struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev,
                goto err_remap;
        }
 
+       /*
+        * Some platforms need to probe the controller to be able to
+        * determine which caps should be used.
+        */
+       if (host->ops && host->ops->platform_init)
+               host->ops->platform_init(host);
+
        platform_set_drvdata(pdev, host);
 
        return host;
index 2903949594c6a1d3168d5a021c82ebec795ed138..a54dd5d7a5f94b1b3e550e799ee95999c5e54df8 100644 (file)
@@ -211,8 +211,8 @@ static void sdhci_s3c_set_clock(struct sdhci_host *host, unsigned int clock)
        if (ourhost->cur_clk != best_src) {
                struct clk *clk = ourhost->clk_bus[best_src];
 
-               clk_enable(clk);
-               clk_disable(ourhost->clk_bus[ourhost->cur_clk]);
+               clk_prepare_enable(clk);
+               clk_disable_unprepare(ourhost->clk_bus[ourhost->cur_clk]);
 
                /* turn clock off to card before changing clock source */
                writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL);
@@ -607,7 +607,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
        }
 
        /* enable the local io clock and keep it running for the moment. */
-       clk_enable(sc->clk_io);
+       clk_prepare_enable(sc->clk_io);
 
        for (clks = 0, ptr = 0; ptr < MAX_BUS_CLK; ptr++) {
                struct clk *clk;
@@ -638,7 +638,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
        }
 
 #ifndef CONFIG_PM_RUNTIME
-       clk_enable(sc->clk_bus[sc->cur_clk]);
+       clk_prepare_enable(sc->clk_bus[sc->cur_clk]);
 #endif
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -747,13 +747,14 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
                sdhci_s3c_setup_card_detect_gpio(sc);
 
 #ifdef CONFIG_PM_RUNTIME
-       clk_disable(sc->clk_io);
+       if (pdata->cd_type != S3C_SDHCI_CD_INTERNAL)
+               clk_disable_unprepare(sc->clk_io);
 #endif
        return 0;
 
  err_req_regs:
 #ifndef CONFIG_PM_RUNTIME
-       clk_disable(sc->clk_bus[sc->cur_clk]);
+       clk_disable_unprepare(sc->clk_bus[sc->cur_clk]);
 #endif
        for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) {
                if (sc->clk_bus[ptr]) {
@@ -762,7 +763,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
        }
 
  err_no_busclks:
-       clk_disable(sc->clk_io);
+       clk_disable_unprepare(sc->clk_io);
        clk_put(sc->clk_io);
 
  err_io_clk:
@@ -794,7 +795,8 @@ static int __devexit sdhci_s3c_remove(struct platform_device *pdev)
                gpio_free(sc->ext_cd_gpio);
 
 #ifdef CONFIG_PM_RUNTIME
-       clk_enable(sc->clk_io);
+       if (pdata->cd_type != S3C_SDHCI_CD_INTERNAL)
+               clk_prepare_enable(sc->clk_io);
 #endif
        sdhci_remove_host(host, 1);
 
@@ -802,14 +804,14 @@ static int __devexit sdhci_s3c_remove(struct platform_device *pdev)
        pm_runtime_disable(&pdev->dev);
 
 #ifndef CONFIG_PM_RUNTIME
-       clk_disable(sc->clk_bus[sc->cur_clk]);
+       clk_disable_unprepare(sc->clk_bus[sc->cur_clk]);
 #endif
        for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) {
                if (sc->clk_bus[ptr]) {
                        clk_put(sc->clk_bus[ptr]);
                }
        }
-       clk_disable(sc->clk_io);
+       clk_disable_unprepare(sc->clk_io);
        clk_put(sc->clk_io);
 
        if (pdev->dev.of_node) {
@@ -849,8 +851,8 @@ static int sdhci_s3c_runtime_suspend(struct device *dev)
 
        ret = sdhci_runtime_suspend_host(host);
 
-       clk_disable(ourhost->clk_bus[ourhost->cur_clk]);
-       clk_disable(busclk);
+       clk_disable_unprepare(ourhost->clk_bus[ourhost->cur_clk]);
+       clk_disable_unprepare(busclk);
        return ret;
 }
 
@@ -861,8 +863,8 @@ static int sdhci_s3c_runtime_resume(struct device *dev)
        struct clk *busclk = ourhost->clk_io;
        int ret;
 
-       clk_enable(busclk);
-       clk_enable(ourhost->clk_bus[ourhost->cur_clk]);
+       clk_prepare_enable(busclk);
+       clk_prepare_enable(ourhost->clk_bus[ourhost->cur_clk]);
        ret = sdhci_runtime_resume_host(host);
        return ret;
 }
index 7922adb4238625c1b4c9e1d489dea04a3d0e2353..c7851c0aabce52226d118d50bbe95fe61b4094c2 100644 (file)
@@ -1315,16 +1315,19 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
                 */
                if ((host->flags & SDHCI_NEEDS_RETUNING) &&
                    !(present_state & (SDHCI_DOING_WRITE | SDHCI_DOING_READ))) {
-                       /* eMMC uses cmd21 while sd and sdio use cmd19 */
-                       tuning_opcode = mmc->card->type == MMC_TYPE_MMC ?
-                               MMC_SEND_TUNING_BLOCK_HS200 :
-                               MMC_SEND_TUNING_BLOCK;
-                       spin_unlock_irqrestore(&host->lock, flags);
-                       sdhci_execute_tuning(mmc, tuning_opcode);
-                       spin_lock_irqsave(&host->lock, flags);
-
-                       /* Restore original mmc_request structure */
-                       host->mrq = mrq;
+                       if (mmc->card) {
+                               /* eMMC uses cmd21 but sd and sdio use cmd19 */
+                               tuning_opcode =
+                                       mmc->card->type == MMC_TYPE_MMC ?
+                                       MMC_SEND_TUNING_BLOCK_HS200 :
+                                       MMC_SEND_TUNING_BLOCK;
+                               spin_unlock_irqrestore(&host->lock, flags);
+                               sdhci_execute_tuning(mmc, tuning_opcode);
+                               spin_lock_irqsave(&host->lock, flags);
+
+                               /* Restore original mmc_request structure */
+                               host->mrq = mrq;
+                       }
                }
 
                if (mrq->sbc && !(host->flags & SDHCI_AUTO_CMD23))
@@ -2837,6 +2840,9 @@ int sdhci_add_host(struct sdhci_host *host)
        if (!(host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA))
                mmc->caps |= MMC_CAP_4_BIT_DATA;
 
+       if (host->quirks2 & SDHCI_QUIRK2_HOST_NO_CMD23)
+               mmc->caps &= ~MMC_CAP_CMD23;
+
        if (caps[0] & SDHCI_CAN_DO_HISPD)
                mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED;
 
@@ -2846,9 +2852,12 @@ int sdhci_add_host(struct sdhci_host *host)
 
        /* If vqmmc regulator and no 1.8V signalling, then there's no UHS */
        host->vqmmc = regulator_get(mmc_dev(mmc), "vqmmc");
-       if (IS_ERR(host->vqmmc)) {
-               pr_info("%s: no vqmmc regulator found\n", mmc_hostname(mmc));
-               host->vqmmc = NULL;
+       if (IS_ERR_OR_NULL(host->vqmmc)) {
+               if (PTR_ERR(host->vqmmc) < 0) {
+                       pr_info("%s: no vqmmc regulator found\n",
+                               mmc_hostname(mmc));
+                       host->vqmmc = NULL;
+               }
        }
        else if (regulator_is_supported_voltage(host->vqmmc, 1800000, 1800000))
                regulator_enable(host->vqmmc);
@@ -2904,9 +2913,12 @@ int sdhci_add_host(struct sdhci_host *host)
        ocr_avail = 0;
 
        host->vmmc = regulator_get(mmc_dev(mmc), "vmmc");
-       if (IS_ERR(host->vmmc)) {
-               pr_info("%s: no vmmc regulator found\n", mmc_hostname(mmc));
-               host->vmmc = NULL;
+       if (IS_ERR_OR_NULL(host->vmmc)) {
+               if (PTR_ERR(host->vmmc) < 0) {
+                       pr_info("%s: no vmmc regulator found\n",
+                               mmc_hostname(mmc));
+                       host->vmmc = NULL;
+               }
        } else
                regulator_enable(host->vmmc);
 
index 97653ea8942ba82393f47b6291942e28c2435204..71a4a7ed46c5095653ce43e90ffd6754815f98da 100644 (file)
@@ -278,6 +278,7 @@ struct sdhci_ops {
        void    (*hw_reset)(struct sdhci_host *host);
        void    (*platform_suspend)(struct sdhci_host *host);
        void    (*platform_resume)(struct sdhci_host *host);
+       void    (*platform_init)(struct sdhci_host *host);
 };
 
 #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
index 11d2bc3b51d578a357fd9b857084db1a89a91741..d25bc97dc5c60063bb609b22973e41790ced9762 100644 (file)
@@ -1466,9 +1466,9 @@ static int __devexit sh_mmcif_remove(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, NULL);
 
+       clk_disable(host->hclk);
        mmc_free_host(host->mmc);
        pm_runtime_put_sync(&pdev->dev);
-       clk_disable(host->hclk);
        pm_runtime_disable(&pdev->dev);
 
        return 0;
index 8f52fc858e48bec08f900963996c0d37bd4601cb..5a5cd2ace4a6b05126e642e06d04950f52108ab8 100644 (file)
@@ -240,7 +240,7 @@ static int parse_cmdline(char *devname, char *szstart, char *szlength)
 
        if (*(szlength) != '+') {
                devlength = simple_strtoul(szlength, &buffer, 0);
-               devlength = handle_unit(devlength, buffer) - devstart;
+               devlength = handle_unit(devlength, buffer);
                if (devlength < devstart)
                        goto err_out;
 
index ec6841d8e956f74f5224363392632900a39e1f8e..1a03b7f673ce0d59c8613144fd51d1ffb299e4fd 100644 (file)
@@ -2983,13 +2983,15 @@ static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip,
        /*
         * Field definitions are in the following datasheets:
         * Old style (4,5 byte ID): Samsung K9GAG08U0M (p.32)
-        * New style   (6 byte ID): Samsung K9GAG08U0F (p.44)
+        * New Samsung (6 byte ID): Samsung K9GAG08U0F (p.44)
         * Hynix MLC   (6 byte ID): Hynix H27UBG8T2B (p.22)
         *
-        * Check for ID length, cell type, and Hynix/Samsung ID to decide what
-        * to do.
+        * Check for ID length, non-zero 6th byte, cell type, and Hynix/Samsung
+        * ID to decide what to do.
         */
-       if (id_len == 6 && id_data[0] == NAND_MFR_SAMSUNG) {
+       if (id_len == 6 && id_data[0] == NAND_MFR_SAMSUNG &&
+                       (chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
+                       id_data[5] != 0x00) {
                /* Calc pagesize */
                mtd->writesize = 2048 << (extid & 0x03);
                extid >>= 2;
index 64be8f0848b075cdccb647309ff88d12b3fa547d..d9127e2ed808eab6ddfe5835c68cfa88ef490cf0 100644 (file)
@@ -121,7 +121,7 @@ static int parse_ofoldpart_partitions(struct mtd_info *master,
        nr_parts = plen / sizeof(part[0]);
 
        *pparts = kzalloc(nr_parts * sizeof(*(*pparts)), GFP_KERNEL);
-       if (!pparts)
+       if (!*pparts)
                return -ENOMEM;
 
        names = of_get_property(dp, "partition-names", &plen);
index 7153e0d27101e3eed06ac17addcdbd4734c7ccc3..b3f41f200622b39f5ef7d46ab6b772ed2eb9e97e 100644 (file)
@@ -3694,7 +3694,7 @@ static int flexonenand_check_blocks_erased(struct mtd_info *mtd, int start, int
  * flexonenand_set_boundary    - Writes the SLC boundary
  * @param mtd                  - mtd info structure
  */
-int flexonenand_set_boundary(struct mtd_info *mtd, int die,
+static int flexonenand_set_boundary(struct mtd_info *mtd, int die,
                                    int boundary, int lock)
 {
        struct onenand_chip *this = mtd->priv;
index b2530b00212558411f917abbe077ec75cb985f5e..5f5b69f37d2e50d4a6ebbe91f4c3bc1346e042e3 100644 (file)
@@ -1379,6 +1379,8 @@ static void bond_compute_features(struct bonding *bond)
        struct net_device *bond_dev = bond->dev;
        netdev_features_t vlan_features = BOND_VLAN_FEATURES;
        unsigned short max_hard_header_len = ETH_HLEN;
+       unsigned int gso_max_size = GSO_MAX_SIZE;
+       u16 gso_max_segs = GSO_MAX_SEGS;
        int i;
        unsigned int flags, dst_release_flag = IFF_XMIT_DST_RELEASE;
 
@@ -1394,11 +1396,16 @@ static void bond_compute_features(struct bonding *bond)
                dst_release_flag &= slave->dev->priv_flags;
                if (slave->dev->hard_header_len > max_hard_header_len)
                        max_hard_header_len = slave->dev->hard_header_len;
+
+               gso_max_size = min(gso_max_size, slave->dev->gso_max_size);
+               gso_max_segs = min(gso_max_segs, slave->dev->gso_max_segs);
        }
 
 done:
        bond_dev->vlan_features = vlan_features;
        bond_dev->hard_header_len = max_hard_header_len;
+       bond_dev->gso_max_segs = gso_max_segs;
+       netif_set_gso_max_size(bond_dev, gso_max_size);
 
        flags = bond_dev->priv_flags & ~IFF_XMIT_DST_RELEASE;
        bond_dev->priv_flags = flags | dst_release_flag;
index dc15d248443fd833ae17199a41f28ab6712b5d5c..ef8d2a080d17f4c61b8f28aa7e07bc54ed5c0abc 100644 (file)
@@ -1060,7 +1060,7 @@ static ssize_t bonding_store_primary(struct device *d,
                goto out;
        }
 
-       sscanf(buf, "%16s", ifname); /* IFNAMSIZ */
+       sscanf(buf, "%15s", ifname); /* IFNAMSIZ */
 
        /* check to see if we are clearing primary */
        if (!strlen(ifname) || buf[0] == '\n') {
@@ -1237,7 +1237,7 @@ static ssize_t bonding_store_active_slave(struct device *d,
                goto out;
        }
 
-       sscanf(buf, "%16s", ifname); /* IFNAMSIZ */
+       sscanf(buf, "%15s", ifname); /* IFNAMSIZ */
 
        /* check to see if we are clearing active */
        if (!strlen(ifname) || buf[0] == '\n') {
index c78ecfca1e4582b8e57a2a42a2e14152f3640483..a412bf6d73ef6b0464f5441c85df94c3ab6b4f15 100644 (file)
 
 #define FLEXCAN_MB_CODE_MASK           (0xf0ffffff)
 
-/* FLEXCAN hardware feature flags */
+/*
+ * FLEXCAN hardware feature flags
+ *
+ * Below is some version info we got:
+ *    SOC   Version   IP-Version  Glitch-  [TR]WRN_INT
+ *                                Filter?   connected?
+ *   MX25  FlexCAN2  03.00.00.00     no         no
+ *   MX28  FlexCAN2  03.00.04.00    yes        yes
+ *   MX35  FlexCAN2  03.00.00.00     no         no
+ *   MX53  FlexCAN2  03.00.00.00    yes         no
+ *   MX6s  FlexCAN3  10.00.12.00    yes        yes
+ *
+ * Some SOCs do not have the RX_WARN & TX_WARN interrupt line connected.
+ */
 #define FLEXCAN_HAS_V10_FEATURES       BIT(1) /* For core version >= 10 */
-#define FLEXCAN_HAS_BROKEN_ERR_STATE   BIT(2) /* Broken error state handling */
+#define FLEXCAN_HAS_BROKEN_ERR_STATE   BIT(2) /* [TR]WRN_INT not connected */
 
 /* Structure of the message buffer */
 struct flexcan_mb {
@@ -205,7 +218,7 @@ static struct flexcan_devtype_data fsl_p1010_devtype_data = {
 };
 static struct flexcan_devtype_data fsl_imx28_devtype_data;
 static struct flexcan_devtype_data fsl_imx6q_devtype_data = {
-       .features = FLEXCAN_HAS_V10_FEATURES | FLEXCAN_HAS_BROKEN_ERR_STATE,
+       .features = FLEXCAN_HAS_V10_FEATURES,
 };
 
 static const struct can_bittiming_const flexcan_bittiming_const = {
index f5b82aeb2540af2646f38dce966096ac221e3eaf..6525dbcca4e3c6d4d15d0c86d92fc9350f8a09c7 100644 (file)
 
 #include "sja1000.h"
 
-MODULE_AUTHOR("Wolfgang Grandegger <wg@grandegger.com>");
+MODULE_AUTHOR("Stephane Grosjean <s.grosjean@peak-system.com>");
 MODULE_DESCRIPTION("Socket-CAN driver for PEAK PCAN PCI family cards");
 MODULE_SUPPORTED_DEVICE("PEAK PCAN PCI/PCIe/PCIeC miniPCI CAN cards");
+MODULE_SUPPORTED_DEVICE("PEAK PCAN miniPCIe/cPCI PC/104+ PCI/104e CAN Cards");
 MODULE_LICENSE("GPL v2");
 
 #define DRV_NAME  "peak_pci"
@@ -64,7 +65,11 @@ struct peak_pci_chan {
 #define PEAK_PCI_DEVICE_ID     0x0001  /* for PCI/PCIe slot cards */
 #define PEAK_PCIEC_DEVICE_ID   0x0002  /* for ExpressCard slot cards */
 #define PEAK_PCIE_DEVICE_ID    0x0003  /* for nextgen PCIe slot cards */
-#define PEAK_MPCI_DEVICE_ID    0x0008  /* The miniPCI slot cards */
+#define PEAK_CPCI_DEVICE_ID    0x0004  /* for nextgen cPCI slot cards */
+#define PEAK_MPCI_DEVICE_ID    0x0005  /* for nextgen miniPCI slot cards */
+#define PEAK_PC_104P_DEVICE_ID 0x0006  /* PCAN-PC/104+ cards */
+#define PEAK_PCI_104E_DEVICE_ID        0x0007  /* PCAN-PCI/104 Express cards */
+#define PEAK_MPCIE_DEVICE_ID   0x0008  /* The miniPCIe slot cards */
 
 #define PEAK_PCI_CHAN_MAX      4
 
@@ -76,6 +81,10 @@ static DEFINE_PCI_DEVICE_TABLE(peak_pci_tbl) = {
        {PEAK_PCI_VENDOR_ID, PEAK_PCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
        {PEAK_PCI_VENDOR_ID, PEAK_PCIE_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
        {PEAK_PCI_VENDOR_ID, PEAK_MPCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
+       {PEAK_PCI_VENDOR_ID, PEAK_MPCIE_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
+       {PEAK_PCI_VENDOR_ID, PEAK_PC_104P_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
+       {PEAK_PCI_VENDOR_ID, PEAK_PCI_104E_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
+       {PEAK_PCI_VENDOR_ID, PEAK_CPCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
 #ifdef CONFIG_CAN_PEAK_PCIEC
        {PEAK_PCI_VENDOR_ID, PEAK_PCIEC_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
 #endif
index d04911d33b647080278f81678869c032e1a3c853..47618e505355ae91fc0ade4e50231ec780bcc56f 100644 (file)
@@ -813,6 +813,7 @@ static int __init ne_drv_probe(struct platform_device *pdev)
                dev->irq = irq[this_dev];
                dev->mem_end = bad[this_dev];
        }
+       SET_NETDEV_DEV(dev, &pdev->dev);
        err = do_ne_probe(dev);
        if (err) {
                free_netdev(dev);
index c65295dded39aa5b1965a9dd07e00974863ca297..6e5bdd1a31d92c499c43fa40bc11a95bf7034bb7 100644 (file)
@@ -1702,7 +1702,7 @@ static int bnx2x_set_eee(struct net_device *dev, struct ethtool_eee *edata)
                                      SHMEM_EEE_ADV_STATUS_SHIFT);
        if ((advertised != (eee_cfg & SHMEM_EEE_ADV_STATUS_MASK))) {
                DP(BNX2X_MSG_ETHTOOL,
-                  "Direct manipulation of EEE advertisment is not supported\n");
+                  "Direct manipulation of EEE advertisement is not supported\n");
                return -EINVAL;
        }
 
index e2e45ee5df33fcc75c491c78643dfe406297aabb..f6cfdc6cf20ffd88f6f4472452f27f97067afe60 100644 (file)
 #define LINK_20GTFD            LINK_STATUS_SPEED_AND_DUPLEX_20GTFD
 #define LINK_20GXFD            LINK_STATUS_SPEED_AND_DUPLEX_20GXFD
 
-
+#define LINK_UPDATE_MASK \
+                       (LINK_STATUS_SPEED_AND_DUPLEX_MASK | \
+                        LINK_STATUS_LINK_UP | \
+                        LINK_STATUS_PHYSICAL_LINK_FLAG | \
+                        LINK_STATUS_AUTO_NEGOTIATE_COMPLETE | \
+                        LINK_STATUS_RX_FLOW_CONTROL_FLAG_MASK | \
+                        LINK_STATUS_TX_FLOW_CONTROL_FLAG_MASK | \
+                        LINK_STATUS_PARALLEL_DETECTION_FLAG_MASK | \
+                        LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE | \
+                        LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE)
 
 #define SFP_EEPROM_CON_TYPE_ADDR               0x2
        #define SFP_EEPROM_CON_TYPE_VAL_LC      0x7
@@ -3295,6 +3304,21 @@ static void bnx2x_serdes_deassert(struct bnx2x *bp, u8 port)
               DEFAULT_PHY_DEV_ADDR);
 }
 
+static void bnx2x_xgxs_specific_func(struct bnx2x_phy *phy,
+                                    struct link_params *params,
+                                    u32 action)
+{
+       struct bnx2x *bp = params->bp;
+       switch (action) {
+       case PHY_INIT:
+               /* Set correct devad */
+               REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_ST + params->port*0x18, 0);
+               REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + params->port*0x18,
+                      phy->def_md_devad);
+               break;
+       }
+}
+
 static void bnx2x_xgxs_deassert(struct link_params *params)
 {
        struct bnx2x *bp = params->bp;
@@ -3309,10 +3333,8 @@ static void bnx2x_xgxs_deassert(struct link_params *params)
        REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR, val);
        udelay(500);
        REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_SET, val);
-
-       REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_ST + port*0x18, 0);
-       REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18,
-              params->phy[INT_PHY].def_md_devad);
+       bnx2x_xgxs_specific_func(&params->phy[INT_PHY], params,
+                                PHY_INIT);
 }
 
 static void bnx2x_calc_ieee_aneg_adv(struct bnx2x_phy *phy,
@@ -3545,14 +3567,11 @@ static void bnx2x_warpcore_set_lpi_passthrough(struct bnx2x_phy *phy,
 static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
                                        struct link_params *params,
                                        struct link_vars *vars) {
-       u16 val16 = 0, lane, i;
+       u16 lane, i, cl72_ctrl, an_adv = 0;
+       u16 ucode_ver;
        struct bnx2x *bp = params->bp;
        static struct bnx2x_reg_set reg_set[] = {
                {MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, 0x7},
-               {MDIO_AN_DEVAD, MDIO_WC_REG_PAR_DET_10G_CTRL, 0},
-               {MDIO_WC_DEVAD, MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, 0},
-               {MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL0, 0xff},
-               {MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL1, 0x5555},
                {MDIO_PMA_DEVAD, MDIO_WC_REG_IEEE0BLK_AUTONEGNP, 0x0},
                {MDIO_WC_DEVAD, MDIO_WC_REG_RX66_CONTROL, 0x7415},
                {MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_MISC2, 0x6190},
@@ -3565,12 +3584,19 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
                bnx2x_cl45_write(bp, phy, reg_set[i].devad, reg_set[i].reg,
                                 reg_set[i].val);
 
+       bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+               MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, &cl72_ctrl);
+       cl72_ctrl &= 0xf8ff;
+       cl72_ctrl |= 0x3800;
+       bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+               MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, cl72_ctrl);
+
        /* Check adding advertisement for 1G KX */
        if (((vars->line_speed == SPEED_AUTO_NEG) &&
             (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) ||
            (vars->line_speed == SPEED_1000)) {
                u32 addr = MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2;
-               val16 |= (1<<5);
+               an_adv |= (1<<5);
 
                /* Enable CL37 1G Parallel Detect */
                bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD, addr, 0x1);
@@ -3580,11 +3606,14 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
             (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) ||
            (vars->line_speed ==  SPEED_10000)) {
                /* Check adding advertisement for 10G KR */
-               val16 |= (1<<7);
+               an_adv |= (1<<7);
                /* Enable 10G Parallel Detect */
+               CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
+                                 MDIO_AER_BLOCK_AER_REG, 0);
+
                bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
                                 MDIO_WC_REG_PAR_DET_10G_CTRL, 1);
-
+               bnx2x_set_aer_mmd(params, phy);
                DP(NETIF_MSG_LINK, "Advertize 10G\n");
        }
 
@@ -3604,7 +3633,7 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
 
        /* Advertised speeds */
        bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
-                        MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, val16);
+                        MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, an_adv);
 
        /* Advertised and set FEC (Forward Error Correction) */
        bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
@@ -3628,9 +3657,10 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
        /* Set KR Autoneg Work-Around flag for Warpcore version older than D108
         */
        bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-                       MDIO_WC_REG_UC_INFO_B1_VERSION, &val16);
-       if (val16 < 0xd108) {
-               DP(NETIF_MSG_LINK, "Enable AN KR work-around\n");
+                       MDIO_WC_REG_UC_INFO_B1_VERSION, &ucode_ver);
+       if (ucode_ver < 0xd108) {
+               DP(NETIF_MSG_LINK, "Enable AN KR work-around. WC ver:0x%x\n",
+                              ucode_ver);
                vars->rx_tx_asic_rst = MAX_KR_LINK_RETRY;
        }
        bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
@@ -3651,21 +3681,16 @@ static void bnx2x_warpcore_set_10G_KR(struct bnx2x_phy *phy,
                                      struct link_vars *vars)
 {
        struct bnx2x *bp = params->bp;
-       u16 i;
+       u16 val16, i, lane;
        static struct bnx2x_reg_set reg_set[] = {
                /* Disable Autoneg */
                {MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, 0x7},
-               {MDIO_AN_DEVAD, MDIO_WC_REG_PAR_DET_10G_CTRL, 0},
                {MDIO_WC_DEVAD, MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL,
                        0x3f00},
                {MDIO_AN_DEVAD, MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, 0},
                {MDIO_AN_DEVAD, MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x0},
                {MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL3_UP1, 0x1},
                {MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL5_MISC7, 0xa},
-               /* Disable CL36 PCS Tx */
-               {MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL0, 0x0},
-               /* Double Wide Single Data Rate @ pll rate */
-               {MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL1, 0xFFFF},
                /* Leave cl72 training enable, needed for KR */
                {MDIO_PMA_DEVAD,
                MDIO_WC_REG_PMD_IEEE9BLK_TENGBASE_KR_PMD_CONTROL_REGISTER_150,
@@ -3676,11 +3701,24 @@ static void bnx2x_warpcore_set_10G_KR(struct bnx2x_phy *phy,
                bnx2x_cl45_write(bp, phy, reg_set[i].devad, reg_set[i].reg,
                                 reg_set[i].val);
 
-       /* Leave CL72 enabled */
-       bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
-                                MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL,
-                                0x3800);
+       lane = bnx2x_get_warpcore_lane(phy, params);
+       /* Global registers */
+       CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
+                         MDIO_AER_BLOCK_AER_REG, 0);
+       /* Disable CL36 PCS Tx */
+       bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+                       MDIO_WC_REG_XGXSBLK1_LANECTRL0, &val16);
+       val16 &= ~(0x0011 << lane);
+       bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+                        MDIO_WC_REG_XGXSBLK1_LANECTRL0, val16);
 
+       bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+                       MDIO_WC_REG_XGXSBLK1_LANECTRL1, &val16);
+       val16 |= (0x0303 << (lane << 1));
+       bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+                        MDIO_WC_REG_XGXSBLK1_LANECTRL1, val16);
+       /* Restore AER */
+       bnx2x_set_aer_mmd(params, phy);
        /* Set speed via PMA/PMD register */
        bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD,
                         MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x2040);
@@ -4303,7 +4341,7 @@ static void bnx2x_warpcore_link_reset(struct bnx2x_phy *phy,
                                      struct link_params *params)
 {
        struct bnx2x *bp = params->bp;
-       u16 val16;
+       u16 val16, lane;
        bnx2x_sfp_e3_set_transmitter(params, phy, 0);
        bnx2x_set_mdio_clk(bp, params->chip_id, params->port);
        bnx2x_set_aer_mmd(params, phy);
@@ -4340,6 +4378,30 @@ static void bnx2x_warpcore_link_reset(struct bnx2x_phy *phy,
                         MDIO_WC_REG_XGXSBLK1_LANECTRL2,
                         val16 & 0xff00);
 
+       lane = bnx2x_get_warpcore_lane(phy, params);
+       /* Disable CL36 PCS Tx */
+       bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+                       MDIO_WC_REG_XGXSBLK1_LANECTRL0, &val16);
+       val16 |= (0x11 << lane);
+       if (phy->flags & FLAGS_WC_DUAL_MODE)
+               val16 |= (0x22 << lane);
+       bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+                        MDIO_WC_REG_XGXSBLK1_LANECTRL0, val16);
+
+       bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+                       MDIO_WC_REG_XGXSBLK1_LANECTRL1, &val16);
+       val16 &= ~(0x0303 << (lane << 1));
+       val16 |= (0x0101 << (lane << 1));
+       if (phy->flags & FLAGS_WC_DUAL_MODE) {
+               val16 &= ~(0x0c0c << (lane << 1));
+               val16 |= (0x0404 << (lane << 1));
+       }
+
+       bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+                        MDIO_WC_REG_XGXSBLK1_LANECTRL1, val16);
+       /* Restore AER */
+       bnx2x_set_aer_mmd(params, phy);
+
 }
 
 static void bnx2x_set_warpcore_loopback(struct bnx2x_phy *phy,
@@ -6296,15 +6358,7 @@ static int bnx2x_update_link_down(struct link_params *params,
        vars->mac_type = MAC_TYPE_NONE;
 
        /* Update shared memory */
-       vars->link_status &= ~(LINK_STATUS_SPEED_AND_DUPLEX_MASK |
-                              LINK_STATUS_LINK_UP |
-                              LINK_STATUS_PHYSICAL_LINK_FLAG |
-                              LINK_STATUS_AUTO_NEGOTIATE_COMPLETE |
-                              LINK_STATUS_RX_FLOW_CONTROL_FLAG_MASK |
-                              LINK_STATUS_TX_FLOW_CONTROL_FLAG_MASK |
-                              LINK_STATUS_PARALLEL_DETECTION_FLAG_MASK |
-                              LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE |
-                              LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE);
+       vars->link_status &= ~LINK_UPDATE_MASK;
        vars->line_speed = 0;
        bnx2x_update_mng(params, vars->link_status);
 
@@ -6452,6 +6506,7 @@ int bnx2x_link_update(struct link_params *params, struct link_vars *vars)
        u16 ext_phy_line_speed = 0, prev_line_speed = vars->line_speed;
        u8 active_external_phy = INT_PHY;
        vars->phy_flags &= ~PHY_HALF_OPEN_CONN_FLAG;
+       vars->link_status &= ~LINK_UPDATE_MASK;
        for (phy_index = INT_PHY; phy_index < params->num_phys;
              phy_index++) {
                phy_vars[phy_index].flow_ctrl = 0;
@@ -7579,7 +7634,7 @@ static void bnx2x_warpcore_power_module(struct link_params *params,
 static int bnx2x_warpcore_read_sfp_module_eeprom(struct bnx2x_phy *phy,
                                                 struct link_params *params,
                                                 u16 addr, u8 byte_cnt,
-                                                u8 *o_buf)
+                                                u8 *o_buf, u8 is_init)
 {
        int rc = 0;
        u8 i, j = 0, cnt = 0;
@@ -7596,10 +7651,10 @@ static int bnx2x_warpcore_read_sfp_module_eeprom(struct bnx2x_phy *phy,
        /* 4 byte aligned address */
        addr32 = addr & (~0x3);
        do {
-               if (cnt == I2C_WA_PWR_ITER) {
+               if ((!is_init) && (cnt == I2C_WA_PWR_ITER)) {
                        bnx2x_warpcore_power_module(params, phy, 0);
                        /* Note that 100us are not enough here */
-                       usleep_range(1000,1000);
+                       usleep_range(1000, 2000);
                        bnx2x_warpcore_power_module(params, phy, 1);
                }
                rc = bnx2x_bsc_read(params, phy, 0xa0, addr32, 0, byte_cnt,
@@ -7719,7 +7774,7 @@ int bnx2x_read_sfp_module_eeprom(struct bnx2x_phy *phy,
        break;
        case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
                rc = bnx2x_warpcore_read_sfp_module_eeprom(phy, params, addr,
-                                                          byte_cnt, o_buf);
+                                                          byte_cnt, o_buf, 0);
        break;
        }
        return rc;
@@ -7923,6 +7978,7 @@ static int bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy,
 
 {
        u8 val;
+       int rc;
        struct bnx2x *bp = params->bp;
        u16 timeout;
        /* Initialization time after hot-plug may take up to 300ms for
@@ -7930,8 +7986,14 @@ static int bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy,
         */
 
        for (timeout = 0; timeout < 60; timeout++) {
-               if (bnx2x_read_sfp_module_eeprom(phy, params, 1, 1, &val)
-                   == 0) {
+               if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT)
+                       rc = bnx2x_warpcore_read_sfp_module_eeprom(phy,
+                                                                  params, 1,
+                                                                  1, &val, 1);
+               else
+                       rc = bnx2x_read_sfp_module_eeprom(phy, params, 1, 1,
+                                                         &val);
+               if (rc == 0) {
                        DP(NETIF_MSG_LINK,
                           "SFP+ module initialization took %d ms\n",
                           timeout * 5);
@@ -7939,7 +8001,8 @@ static int bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy,
                }
                usleep_range(5000, 10000);
        }
-       return -EINVAL;
+       rc = bnx2x_read_sfp_module_eeprom(phy, params, 1, 1, &val);
+       return rc;
 }
 
 static void bnx2x_8727_power_module(struct bnx2x *bp,
@@ -9878,7 +9941,7 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
                else
                        rc = bnx2x_8483x_disable_eee(phy, params, vars);
                if (rc) {
-                       DP(NETIF_MSG_LINK, "Failed to set EEE advertisment\n");
+                       DP(NETIF_MSG_LINK, "Failed to set EEE advertisement\n");
                        return rc;
                }
        } else {
@@ -10993,7 +11056,7 @@ static struct bnx2x_phy phy_xgxs = {
        .format_fw_ver  = (format_fw_ver_t)NULL,
        .hw_reset       = (hw_reset_t)NULL,
        .set_link_led   = (set_link_led_t)NULL,
-       .phy_specific_func = (phy_specific_func_t)NULL
+       .phy_specific_func = (phy_specific_func_t)bnx2x_xgxs_specific_func
 };
 static struct bnx2x_phy phy_warpcore = {
        .type           = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT,
@@ -11465,6 +11528,11 @@ static int bnx2x_populate_int_phy(struct bnx2x *bp, u32 shmem_base, u8 port,
                        phy->media_type = ETH_PHY_BASE_T;
                        break;
                case PORT_HW_CFG_NET_SERDES_IF_XFI:
+                       phy->supported &= (SUPPORTED_1000baseT_Full |
+                                          SUPPORTED_10000baseT_Full |
+                                          SUPPORTED_FIBRE |
+                                          SUPPORTED_Pause |
+                                          SUPPORTED_Asym_Pause);
                        phy->media_type = ETH_PHY_XFP_FIBER;
                        break;
                case PORT_HW_CFG_NET_SERDES_IF_SFI:
@@ -12919,7 +12987,7 @@ static u8 bnx2x_analyze_link_error(struct link_params *params,
                DP(NETIF_MSG_LINK, "Analyze TX Fault\n");
                break;
        default:
-               DP(NETIF_MSG_LINK, "Analyze UNKOWN\n");
+               DP(NETIF_MSG_LINK, "Analyze UNKNOWN\n");
        }
        DP(NETIF_MSG_LINK, "Link changed:[%x %x]->%x\n", vars->link_up,
           old_status, status);
index d5648fc666bdf6f663505bbb433abebac08dbd48..01611b33a93de82c8b735b2e1c3e115a9b8e807f 100644 (file)
@@ -6794,8 +6794,9 @@ static int bnx2x_init_hw_port(struct bnx2x *bp)
 
        bnx2x_init_block(bp, BLOCK_DORQ, init_phase);
 
+       bnx2x_init_block(bp, BLOCK_BRB1, init_phase);
+
        if (CHIP_IS_E1(bp) || CHIP_IS_E1H(bp)) {
-               bnx2x_init_block(bp, BLOCK_BRB1, init_phase);
 
                if (IS_MF(bp))
                        low = ((bp->flags & ONE_PORT_FLAG) ? 160 : 246);
@@ -9544,10 +9545,13 @@ static int __devinit bnx2x_prev_unload_common(struct bnx2x *bp)
  */
 static void __devinit bnx2x_prev_interrupted_dmae(struct bnx2x *bp)
 {
-       u32 val = REG_RD(bp, PGLUE_B_REG_PGLUE_B_INT_STS);
-       if (val & PGLUE_B_PGLUE_B_INT_STS_REG_WAS_ERROR_ATTN) {
-               BNX2X_ERR("was error bit was found to be set in pglueb upon startup. Clearing");
-               REG_WR(bp, PGLUE_B_REG_WAS_ERROR_PF_7_0_CLR, 1 << BP_FUNC(bp));
+       if (!CHIP_IS_E1x(bp)) {
+               u32 val = REG_RD(bp, PGLUE_B_REG_PGLUE_B_INT_STS);
+               if (val & PGLUE_B_PGLUE_B_INT_STS_REG_WAS_ERROR_ATTN) {
+                       BNX2X_ERR("was error bit was found to be set in pglueb upon startup. Clearing");
+                       REG_WR(bp, PGLUE_B_REG_WAS_ERROR_PF_7_0_CLR,
+                              1 << BP_FUNC(bp));
+               }
        }
 }
 
@@ -11902,7 +11906,15 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
        /* disable FCOE L2 queue for E1x */
        if (CHIP_IS_E1x(bp))
                bp->flags |= NO_FCOE_FLAG;
-
+       /* disable FCOE for 57840 device, until FW supports it */
+       switch (ent->driver_data) {
+       case BCM57840_O:
+       case BCM57840_4_10:
+       case BCM57840_2_20:
+       case BCM57840_MFO:
+       case BCM57840_MF:
+               bp->flags |= NO_FCOE_FLAG;
+       }
 #endif
 
 
index a4da893ac1e15cfd02a2d071503afaa21838e51c..378988b5709a2262b98c0a790072be38b837cdf3 100644 (file)
@@ -251,6 +251,8 @@ struct adapter_params {
        unsigned char rev;                /* chip revision */
        unsigned char offload;
 
+       unsigned char bypass;
+
        unsigned int ofldq_wr_cred;
 };
 
@@ -642,6 +644,23 @@ extern int dbfifo_int_thresh;
 #define for_each_port(adapter, iter) \
        for (iter = 0; iter < (adapter)->params.nports; ++iter)
 
+static inline int is_bypass(struct adapter *adap)
+{
+       return adap->params.bypass;
+}
+
+static inline int is_bypass_device(int device)
+{
+       /* this should be set based upon device capabilities */
+       switch (device) {
+       case 0x440b:
+       case 0x440c:
+               return 1;
+       default:
+               return 0;
+       }
+}
+
 static inline unsigned int core_ticks_per_usec(const struct adapter *adap)
 {
        return adap->params.vpd.cclk / 1000;
index 604f4f87f550c879a087fd128892d97450aa2d19..0df1284df497d8247fbf602d6578381099619d06 100644 (file)
@@ -3415,16 +3415,6 @@ static int adap_init0_config(struct adapter *adapter, int reset)
                         "mismatch: [fini] csum=%#x, computed csum=%#x\n",
                         finicsum, cfcsum);
 
-       /*
-        * If we're a pure NIC driver then disable all offloading facilities.
-        * This will allow the firmware to optimize aspects of the hardware
-        * configuration which will result in improved performance.
-        */
-       caps_cmd.ofldcaps = 0;
-       caps_cmd.iscsicaps = 0;
-       caps_cmd.rdmacaps = 0;
-       caps_cmd.fcoecaps = 0;
-
        /*
         * And now tell the firmware to use the configuration we just loaded.
         */
@@ -3513,18 +3503,6 @@ static int adap_init0_no_config(struct adapter *adapter, int reset)
        if (ret < 0)
                goto bye;
 
-#ifndef CONFIG_CHELSIO_T4_OFFLOAD
-       /*
-        * If we're a pure NIC driver then disable all offloading facilities.
-        * This will allow the firmware to optimize aspects of the hardware
-        * configuration which will result in improved performance.
-        */
-       caps_cmd.ofldcaps = 0;
-       caps_cmd.iscsicaps = 0;
-       caps_cmd.rdmacaps = 0;
-       caps_cmd.fcoecaps = 0;
-#endif
-
        if (caps_cmd.niccaps & htons(FW_CAPS_CONFIG_NIC_VM)) {
                if (!vf_acls)
                        caps_cmd.niccaps ^= htons(FW_CAPS_CONFIG_NIC_VM);
@@ -3745,6 +3723,7 @@ static int adap_init0(struct adapter *adap)
        u32 v, port_vec;
        enum dev_state state;
        u32 params[7], val[7];
+       struct fw_caps_config_cmd caps_cmd;
        int reset = 1, j;
 
        /*
@@ -3898,6 +3877,9 @@ static int adap_init0(struct adapter *adap)
                        goto bye;
        }
 
+       if (is_bypass_device(adap->pdev->device))
+               adap->params.bypass = 1;
+
        /*
         * Grab some of our basic fundamental operating parameters.
         */
@@ -3940,13 +3922,12 @@ static int adap_init0(struct adapter *adap)
                adap->tids.aftid_end = val[1];
        }
 
-#ifdef CONFIG_CHELSIO_T4_OFFLOAD
        /*
         * Get device capabilities so we can determine what resources we need
         * to manage.
         */
        memset(&caps_cmd, 0, sizeof(caps_cmd));
-       caps_cmd.op_to_write = htonl(V_FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
+       caps_cmd.op_to_write = htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
                                     FW_CMD_REQUEST | FW_CMD_READ);
        caps_cmd.retval_len16 = htonl(FW_LEN16(caps_cmd));
        ret = t4_wr_mbox(adap, adap->mbox, &caps_cmd, sizeof(caps_cmd),
@@ -3991,15 +3972,6 @@ static int adap_init0(struct adapter *adap)
                adap->vres.ddp.size = val[4] - val[3] + 1;
                adap->params.ofldq_wr_cred = val[5];
 
-               params[0] = FW_PARAM_PFVF(ETHOFLD_START);
-               params[1] = FW_PARAM_PFVF(ETHOFLD_END);
-               ret = t4_query_params(adap, adap->mbox, adap->fn, 0, 2,
-                                     params, val);
-               if ((val[0] != val[1]) && (ret >= 0)) {
-                       adap->tids.uotid_base = val[0];
-                       adap->tids.nuotids = val[1] - val[0] + 1;
-               }
-
                adap->params.offload = 1;
        }
        if (caps_cmd.rdmacaps) {
@@ -4048,7 +4020,6 @@ static int adap_init0(struct adapter *adap)
        }
 #undef FW_PARAM_PFVF
 #undef FW_PARAM_DEV
-#endif /* CONFIG_CHELSIO_T4_OFFLOAD */
 
        /*
         * These are finalized by FW initialization, load their values now.
index 1b899fea1a91427bac31b171cd799fad2fc384f0..39bec73ff87c5879a9b1f6ca9ad1425d4d78c9b2 100644 (file)
@@ -102,6 +102,9 @@ struct tid_info {
        unsigned int ftid_base;
        unsigned int aftid_base;
        unsigned int aftid_end;
+       /* Server filter region */
+       unsigned int sftid_base;
+       unsigned int nsftids;
 
        spinlock_t atid_lock ____cacheline_aligned_in_smp;
        union aopen_entry *afree;
index 32eec15fe4c2cd8425f89661231797e96007c5b1..730ae2cfa49e34ee5d361d73ac437ff715d4e50d 100644 (file)
@@ -2519,6 +2519,7 @@ int t4_fw_bye(struct adapter *adap, unsigned int mbox)
 {
        struct fw_bye_cmd c;
 
+       memset(&c, 0, sizeof(c));
        INIT_CMD(c, BYE, WRITE);
        return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
 }
@@ -2535,6 +2536,7 @@ int t4_early_init(struct adapter *adap, unsigned int mbox)
 {
        struct fw_initialize_cmd c;
 
+       memset(&c, 0, sizeof(c));
        INIT_CMD(c, INITIALIZE, WRITE);
        return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
 }
@@ -2551,6 +2553,7 @@ int t4_fw_reset(struct adapter *adap, unsigned int mbox, int reset)
 {
        struct fw_reset_cmd c;
 
+       memset(&c, 0, sizeof(c));
        INIT_CMD(c, RESET, WRITE);
        c.val = htonl(reset);
        return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
@@ -2828,7 +2831,7 @@ int t4_fixup_host_params(struct adapter *adap, unsigned int page_size,
                     HOSTPAGESIZEPF7(sge_hps));
 
        t4_set_reg_field(adap, SGE_CONTROL,
-                        INGPADBOUNDARY(INGPADBOUNDARY_MASK) |
+                        INGPADBOUNDARY_MASK |
                         EGRSTATUSPAGESIZE_MASK,
                         INGPADBOUNDARY(fl_align_log - 5) |
                         EGRSTATUSPAGESIZE(stat_len != 64));
@@ -3278,6 +3281,7 @@ int t4_identify_port(struct adapter *adap, unsigned int mbox, unsigned int viid,
 {
        struct fw_vi_enable_cmd c;
 
+       memset(&c, 0, sizeof(c));
        c.op_to_viid = htonl(FW_CMD_OP(FW_VI_ENABLE_CMD) | FW_CMD_REQUEST |
                             FW_CMD_EXEC | FW_VI_ENABLE_CMD_VIID(viid));
        c.ien_to_len16 = htonl(FW_VI_ENABLE_CMD_LED | FW_LEN16(c));
index 1d03dcdd5e5686bb6e76cb71069607a44d8d4eb2..19ac096cb07b702fd988d53a224d03119c674e59 100644 (file)
@@ -1353,8 +1353,11 @@ static int gfar_restore(struct device *dev)
        struct gfar_private *priv = dev_get_drvdata(dev);
        struct net_device *ndev = priv->ndev;
 
-       if (!netif_running(ndev))
+       if (!netif_running(ndev)) {
+               netif_device_attach(ndev);
+
                return 0;
+       }
 
        gfar_init_bds(ndev);
        init_registers(ndev);
index b9db0e0405636780bf02bc598b12e79ea5f71074..2e5daee0438a55891072595400d643bd8ad1340b 100644 (file)
@@ -478,7 +478,7 @@ static int gianfar_ptp_probe(struct platform_device *dev)
                pr_err("no resource\n");
                goto no_resource;
        }
-       if (request_resource(&ioport_resource, etsects->rsrc)) {
+       if (request_resource(&iomem_resource, etsects->rsrc)) {
                pr_err("resource busy\n");
                goto no_resource;
        }
index 56b20d17d0e4c5577828040fddf8bd294868c84d..116f0e901bee2305324c4fa9035d19e6c5676b37 100644 (file)
@@ -2673,6 +2673,9 @@ static int ixgbe_get_ts_info(struct net_device *dev,
        case ixgbe_mac_X540:
        case ixgbe_mac_82599EB:
                info->so_timestamping =
+                       SOF_TIMESTAMPING_TX_SOFTWARE |
+                       SOF_TIMESTAMPING_RX_SOFTWARE |
+                       SOF_TIMESTAMPING_SOFTWARE |
                        SOF_TIMESTAMPING_TX_HARDWARE |
                        SOF_TIMESTAMPING_RX_HARDWARE |
                        SOF_TIMESTAMPING_RAW_HARDWARE;
index f8064df10cc4ca1d1c6bcf05b42858ae5c9071fc..60ac46f4ac085380630c5f35af7892e65cc980f5 100644 (file)
@@ -1860,10 +1860,14 @@ jme_open(struct net_device *netdev)
        jme_clear_pm(jme);
        JME_NAPI_ENABLE(jme);
 
-       tasklet_enable(&jme->linkch_task);
-       tasklet_enable(&jme->txclean_task);
-       tasklet_hi_enable(&jme->rxclean_task);
-       tasklet_hi_enable(&jme->rxempty_task);
+       tasklet_init(&jme->linkch_task, jme_link_change_tasklet,
+                    (unsigned long) jme);
+       tasklet_init(&jme->txclean_task, jme_tx_clean_tasklet,
+                    (unsigned long) jme);
+       tasklet_init(&jme->rxclean_task, jme_rx_clean_tasklet,
+                    (unsigned long) jme);
+       tasklet_init(&jme->rxempty_task, jme_rx_empty_tasklet,
+                    (unsigned long) jme);
 
        rc = jme_request_irq(jme);
        if (rc)
@@ -1948,10 +1952,10 @@ jme_close(struct net_device *netdev)
 
        JME_NAPI_DISABLE(jme);
 
-       tasklet_disable(&jme->linkch_task);
-       tasklet_disable(&jme->txclean_task);
-       tasklet_disable(&jme->rxclean_task);
-       tasklet_disable(&jme->rxempty_task);
+       tasklet_kill(&jme->linkch_task);
+       tasklet_kill(&jme->txclean_task);
+       tasklet_kill(&jme->rxclean_task);
+       tasklet_kill(&jme->rxempty_task);
 
        jme_disable_rx_engine(jme);
        jme_disable_tx_engine(jme);
@@ -3079,22 +3083,6 @@ jme_init_one(struct pci_dev *pdev,
        tasklet_init(&jme->pcc_task,
                     jme_pcc_tasklet,
                     (unsigned long) jme);
-       tasklet_init(&jme->linkch_task,
-                    jme_link_change_tasklet,
-                    (unsigned long) jme);
-       tasklet_init(&jme->txclean_task,
-                    jme_tx_clean_tasklet,
-                    (unsigned long) jme);
-       tasklet_init(&jme->rxclean_task,
-                    jme_rx_clean_tasklet,
-                    (unsigned long) jme);
-       tasklet_init(&jme->rxempty_task,
-                    jme_rx_empty_tasklet,
-                    (unsigned long) jme);
-       tasklet_disable_nosync(&jme->linkch_task);
-       tasklet_disable_nosync(&jme->txclean_task);
-       tasklet_disable_nosync(&jme->rxclean_task);
-       tasklet_disable_nosync(&jme->rxempty_task);
        jme->dpi.cur = PCC_P1;
 
        jme->reg_ghc = 0;
index 9b9c2ac5c4c214d65366782c05d6406a1859cb17..d19a143aa5a8690db119630228f40bd896d1f84f 100644 (file)
@@ -4026,7 +4026,7 @@ static void __devexit skge_remove(struct pci_dev *pdev)
        dev0 = hw->dev[0];
        unregister_netdev(dev0);
 
-       tasklet_disable(&hw->phy_task);
+       tasklet_kill(&hw->phy_task);
 
        spin_lock_irq(&hw->hw_lock);
        hw->intr_mask = 0;
index c10e3a6de09f042a02be933d8aa1ca928207fe6d..b35094c590ba94206be751643a7ad3a17cab9b7f 100644 (file)
@@ -143,7 +143,6 @@ void mlx4_en_destroy_tx_ring(struct mlx4_en_priv *priv,
                mlx4_bf_free(mdev->dev, &ring->bf);
        mlx4_qp_remove(mdev->dev, &ring->qp);
        mlx4_qp_free(mdev->dev, &ring->qp);
-       mlx4_qp_release_range(mdev->dev, ring->qpn, 1);
        mlx4_en_unmap_buffer(&ring->wqres.buf);
        mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size);
        kfree(ring->bounce_buf);
@@ -712,7 +711,7 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
        if (bounce)
                tx_desc = mlx4_en_bounce_to_desc(priv, ring, index, desc_size);
 
-       if (ring->bf_enabled && desc_size <= MAX_BF && !bounce && !vlan_tag) {
+       if (ring->bf_enabled && desc_size <= MAX_BF && !bounce && !vlan_tx_tag_present(skb)) {
                *(__be32 *) (&tx_desc->ctrl.vlan_tag) |= cpu_to_be32(ring->doorbell_qpn);
                op_own |= htonl((bf_index & 0xffff) << 8);
                /* Ensure new descirptor hits memory
index 51c764901ad257bce17199496d895f788a647f8b..b84a88bc44dc2a5e7391ca7bc7116344dd63a97f 100644 (file)
@@ -329,9 +329,6 @@ int set_and_calc_slave_port_state(struct mlx4_dev *dev, int slave,
        ctx = &priv->mfunc.master.slave_state[slave];
        spin_lock_irqsave(&ctx->lock, flags);
 
-       mlx4_dbg(dev, "%s: slave: %d, current state: %d new event :%d\n",
-                __func__, slave, cur_state, event);
-
        switch (cur_state) {
        case SLAVE_PORT_DOWN:
                if (MLX4_PORT_STATE_DEV_EVENT_PORT_UP == event)
@@ -366,9 +363,6 @@ int set_and_calc_slave_port_state(struct mlx4_dev *dev, int slave,
                        goto out;
        }
        ret = mlx4_get_slave_port_state(dev, slave, port);
-       mlx4_dbg(dev, "%s: slave: %d, current state: %d new event"
-                " :%d gen_event: %d\n",
-                __func__, slave, cur_state, event, *gen_event);
 
 out:
        spin_unlock_irqrestore(&ctx->lock, flags);
@@ -843,6 +837,18 @@ static void __iomem *mlx4_get_eq_uar(struct mlx4_dev *dev, struct mlx4_eq *eq)
        return priv->eq_table.uar_map[index] + 0x800 + 8 * (eq->eqn % 4);
 }
 
+static void mlx4_unmap_uar(struct mlx4_dev *dev)
+{
+       struct mlx4_priv *priv = mlx4_priv(dev);
+       int i;
+
+       for (i = 0; i < mlx4_num_eq_uar(dev); ++i)
+               if (priv->eq_table.uar_map[i]) {
+                       iounmap(priv->eq_table.uar_map[i]);
+                       priv->eq_table.uar_map[i] = NULL;
+               }
+}
+
 static int mlx4_create_eq(struct mlx4_dev *dev, int nent,
                          u8 intr, struct mlx4_eq *eq)
 {
@@ -1207,6 +1213,7 @@ err_out_unmap:
        mlx4_free_irqs(dev);
 
 err_out_bitmap:
+       mlx4_unmap_uar(dev);
        mlx4_bitmap_cleanup(&priv->eq_table.bitmap);
 
 err_out_free:
@@ -1231,10 +1238,7 @@ void mlx4_cleanup_eq_table(struct mlx4_dev *dev)
        if (!mlx4_is_slave(dev))
                mlx4_unmap_clr_int(dev);
 
-       for (i = 0; i < mlx4_num_eq_uar(dev); ++i)
-               if (priv->eq_table.uar_map[i])
-                       iounmap(priv->eq_table.uar_map[i]);
-
+       mlx4_unmap_uar(dev);
        mlx4_bitmap_cleanup(&priv->eq_table.bitmap);
 
        kfree(priv->eq_table.uar_map);
index 80df2ab0177c398122725a85c82133788b711198..2aa80afd98d20038b2a174ac38a52a5eb003eaba 100644 (file)
@@ -1405,7 +1405,10 @@ unmap_bf:
        unmap_bf_area(dev);
 
 err_close:
-       mlx4_close_hca(dev);
+       if (mlx4_is_slave(dev))
+               mlx4_slave_exit(dev);
+       else
+               mlx4_CLOSE_HCA(dev, 0);
 
 err_free_icm:
        if (!mlx4_is_slave(dev))
index 926c911c0ac4b184d9d0f3fa70632b5ed84cb33b..b05705f50f0fae529e3f728471280ea4a1a1d753 100644 (file)
@@ -330,9 +330,6 @@ static void update_pkey_index(struct mlx4_dev *dev, int slave,
 
        new_index = priv->virt2phys_pkey[slave][port - 1][orig_index];
        *(u8 *)(inbox->buf + 35) = new_index;
-
-       mlx4_dbg(dev, "port = %d, orig pkey index = %d, "
-                "new pkey index = %d\n", port, orig_index, new_index);
 }
 
 static void update_gid(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *inbox,
@@ -351,9 +348,6 @@ static void update_gid(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *inbox,
                if (optpar & MLX4_QP_OPTPAR_ALT_ADDR_PATH)
                        qp_ctx->alt_path.mgid_index = slave & 0x7F;
        }
-
-       mlx4_dbg(dev, "slave %d, new gid index: 0x%x ",
-               slave, qp_ctx->pri_path.mgid_index);
 }
 
 static int mpt_mask(struct mlx4_dev *dev)
index 318fee91c79dad0eeaa6673bd04adb68e43b6f63..69e01977a1dd0cf14466bb397bfe6e0b27c11f36 100644 (file)
@@ -5407,8 +5407,8 @@ static int netdev_close(struct net_device *dev)
                /* Delay for receive task to stop scheduling itself. */
                msleep(2000 / HZ);
 
-               tasklet_disable(&hw_priv->rx_tasklet);
-               tasklet_disable(&hw_priv->tx_tasklet);
+               tasklet_kill(&hw_priv->rx_tasklet);
+               tasklet_kill(&hw_priv->tx_tasklet);
                free_irq(dev->irq, hw_priv->dev);
 
                transmit_cleanup(hw_priv, 0);
@@ -5459,8 +5459,10 @@ static int prepare_hardware(struct net_device *dev)
        rc = request_irq(dev->irq, netdev_intr, IRQF_SHARED, dev->name, dev);
        if (rc)
                return rc;
-       tasklet_enable(&hw_priv->rx_tasklet);
-       tasklet_enable(&hw_priv->tx_tasklet);
+       tasklet_init(&hw_priv->rx_tasklet, rx_proc_task,
+                    (unsigned long) hw_priv);
+       tasklet_init(&hw_priv->tx_tasklet, tx_proc_task,
+                    (unsigned long) hw_priv);
 
        hw->promiscuous = 0;
        hw->all_multi = 0;
@@ -7033,16 +7035,6 @@ static int __devinit pcidev_init(struct pci_dev *pdev,
        spin_lock_init(&hw_priv->hwlock);
        mutex_init(&hw_priv->lock);
 
-       /* tasklet is enabled. */
-       tasklet_init(&hw_priv->rx_tasklet, rx_proc_task,
-               (unsigned long) hw_priv);
-       tasklet_init(&hw_priv->tx_tasklet, tx_proc_task,
-               (unsigned long) hw_priv);
-
-       /* tasklet_enable will decrement the atomic counter. */
-       tasklet_disable(&hw_priv->rx_tasklet);
-       tasklet_disable(&hw_priv->tx_tasklet);
-
        for (i = 0; i < TOTAL_PORT_NUM; i++)
                init_waitqueue_head(&hw_priv->counter[i].counter);
 
index 53743f7a2ca9604d6f264de3a2e3c727556a0619..af8b4142088c3d6a9114fd8c218336f54fcbcc19 100644 (file)
@@ -1524,6 +1524,7 @@ static int lpc_eth_drv_remove(struct platform_device *pdev)
                                  pldat->dma_buff_base_p);
        free_irq(ndev->irq, ndev);
        iounmap(pldat->net_base);
+       mdiobus_unregister(pldat->mii_bus);
        mdiobus_free(pldat->mii_bus);
        clk_disable(pldat->clk);
        clk_put(pldat->clk);
index b2a94d02a5217db7638164962d59b16f8def20ad..4c4fe5b1a29a5422cb272cd9ed7e26ae9ec5eee3 100644 (file)
@@ -338,26 +338,6 @@ static void pch_gbe_wait_clr_bit(void *reg, u32 bit)
                pr_err("Error: busy bit is not cleared\n");
 }
 
-/**
- * pch_gbe_wait_clr_bit_irq - Wait to clear a bit for interrupt context
- * @reg:       Pointer of register
- * @busy:      Busy bit
- */
-static int pch_gbe_wait_clr_bit_irq(void *reg, u32 bit)
-{
-       u32 tmp;
-       int ret = -1;
-       /* wait busy */
-       tmp = 20;
-       while ((ioread32(reg) & bit) && --tmp)
-               udelay(5);
-       if (!tmp)
-               pr_err("Error: busy bit is not cleared\n");
-       else
-               ret = 0;
-       return ret;
-}
-
 /**
  * pch_gbe_mac_mar_set - Set MAC address register
  * @hw:            Pointer to the HW structure
@@ -409,15 +389,20 @@ static void pch_gbe_mac_reset_hw(struct pch_gbe_hw *hw)
        return;
 }
 
-static void pch_gbe_mac_reset_rx(struct pch_gbe_hw *hw)
+static void pch_gbe_disable_mac_rx(struct pch_gbe_hw *hw)
 {
-       /* Read the MAC addresses. and store to the private data */
-       pch_gbe_mac_read_mac_addr(hw);
-       iowrite32(PCH_GBE_RX_RST, &hw->reg->RESET);
-       pch_gbe_wait_clr_bit_irq(&hw->reg->RESET, PCH_GBE_RX_RST);
-       /* Setup the MAC addresses */
-       pch_gbe_mac_mar_set(hw, hw->mac.addr, 0);
-       return;
+       u32 rctl;
+       /* Disables Receive MAC */
+       rctl = ioread32(&hw->reg->MAC_RX_EN);
+       iowrite32((rctl & ~PCH_GBE_MRE_MAC_RX_EN), &hw->reg->MAC_RX_EN);
+}
+
+static void pch_gbe_enable_mac_rx(struct pch_gbe_hw *hw)
+{
+       u32 rctl;
+       /* Enables Receive MAC */
+       rctl = ioread32(&hw->reg->MAC_RX_EN);
+       iowrite32((rctl | PCH_GBE_MRE_MAC_RX_EN), &hw->reg->MAC_RX_EN);
 }
 
 /**
@@ -913,7 +898,7 @@ static void pch_gbe_setup_rctl(struct pch_gbe_adapter *adapter)
 static void pch_gbe_configure_rx(struct pch_gbe_adapter *adapter)
 {
        struct pch_gbe_hw *hw = &adapter->hw;
-       u32 rdba, rdlen, rctl, rxdma;
+       u32 rdba, rdlen, rxdma;
 
        pr_debug("dma adr = 0x%08llx  size = 0x%08x\n",
                 (unsigned long long)adapter->rx_ring->dma,
@@ -921,9 +906,7 @@ static void pch_gbe_configure_rx(struct pch_gbe_adapter *adapter)
 
        pch_gbe_mac_force_mac_fc(hw);
 
-       /* Disables Receive MAC */
-       rctl = ioread32(&hw->reg->MAC_RX_EN);
-       iowrite32((rctl & ~PCH_GBE_MRE_MAC_RX_EN), &hw->reg->MAC_RX_EN);
+       pch_gbe_disable_mac_rx(hw);
 
        /* Disables Receive DMA */
        rxdma = ioread32(&hw->reg->DMA_CTRL);
@@ -1316,38 +1299,17 @@ void pch_gbe_update_stats(struct pch_gbe_adapter *adapter)
        spin_unlock_irqrestore(&adapter->stats_lock, flags);
 }
 
-static void pch_gbe_stop_receive(struct pch_gbe_adapter *adapter)
+static void pch_gbe_disable_dma_rx(struct pch_gbe_hw *hw)
 {
-       struct pch_gbe_hw *hw = &adapter->hw;
        u32 rxdma;
-       u16 value;
-       int ret;
 
        /* Disable Receive DMA */
        rxdma = ioread32(&hw->reg->DMA_CTRL);
        rxdma &= ~PCH_GBE_RX_DMA_EN;
        iowrite32(rxdma, &hw->reg->DMA_CTRL);
-       /* Wait Rx DMA BUS is IDLE */
-       ret = pch_gbe_wait_clr_bit_irq(&hw->reg->RX_DMA_ST, PCH_GBE_IDLE_CHECK);
-       if (ret) {
-               /* Disable Bus master */
-               pci_read_config_word(adapter->pdev, PCI_COMMAND, &value);
-               value &= ~PCI_COMMAND_MASTER;
-               pci_write_config_word(adapter->pdev, PCI_COMMAND, value);
-               /* Stop Receive */
-               pch_gbe_mac_reset_rx(hw);
-               /* Enable Bus master */
-               value |= PCI_COMMAND_MASTER;
-               pci_write_config_word(adapter->pdev, PCI_COMMAND, value);
-       } else {
-               /* Stop Receive */
-               pch_gbe_mac_reset_rx(hw);
-       }
-       /* reprogram multicast address register after reset */
-       pch_gbe_set_multi(adapter->netdev);
 }
 
-static void pch_gbe_start_receive(struct pch_gbe_hw *hw)
+static void pch_gbe_enable_dma_rx(struct pch_gbe_hw *hw)
 {
        u32 rxdma;
 
@@ -1355,9 +1317,6 @@ static void pch_gbe_start_receive(struct pch_gbe_hw *hw)
        rxdma = ioread32(&hw->reg->DMA_CTRL);
        rxdma |= PCH_GBE_RX_DMA_EN;
        iowrite32(rxdma, &hw->reg->DMA_CTRL);
-       /* Enables Receive */
-       iowrite32(PCH_GBE_MRE_MAC_RX_EN, &hw->reg->MAC_RX_EN);
-       return;
 }
 
 /**
@@ -1393,7 +1352,7 @@ static irqreturn_t pch_gbe_intr(int irq, void *data)
                        int_en = ioread32(&hw->reg->INT_EN);
                        iowrite32((int_en & ~PCH_GBE_INT_RX_FIFO_ERR),
                                  &hw->reg->INT_EN);
-                       pch_gbe_stop_receive(adapter);
+                       pch_gbe_disable_dma_rx(&adapter->hw);
                        int_st |= ioread32(&hw->reg->INT_ST);
                        int_st = int_st & ioread32(&hw->reg->INT_EN);
                }
@@ -1971,12 +1930,12 @@ int pch_gbe_up(struct pch_gbe_adapter *adapter)
        struct net_device *netdev = adapter->netdev;
        struct pch_gbe_tx_ring *tx_ring = adapter->tx_ring;
        struct pch_gbe_rx_ring *rx_ring = adapter->rx_ring;
-       int err;
+       int err = -EINVAL;
 
        /* Ensure we have a valid MAC */
        if (!is_valid_ether_addr(adapter->hw.mac.addr)) {
                pr_err("Error: Invalid MAC address\n");
-               return -EINVAL;
+               goto out;
        }
 
        /* hardware has been reset, we need to reload some things */
@@ -1989,18 +1948,19 @@ int pch_gbe_up(struct pch_gbe_adapter *adapter)
 
        err = pch_gbe_request_irq(adapter);
        if (err) {
-               pr_err("Error: can't bring device up\n");
-               return err;
+               pr_err("Error: can't bring device up - irq request failed\n");
+               goto out;
        }
        err = pch_gbe_alloc_rx_buffers_pool(adapter, rx_ring, rx_ring->count);
        if (err) {
-               pr_err("Error: can't bring device up\n");
-               return err;
+               pr_err("Error: can't bring device up - alloc rx buffers pool failed\n");
+               goto freeirq;
        }
        pch_gbe_alloc_tx_buffers(adapter, tx_ring);
        pch_gbe_alloc_rx_buffers(adapter, rx_ring, rx_ring->count);
        adapter->tx_queue_len = netdev->tx_queue_len;
-       pch_gbe_start_receive(&adapter->hw);
+       pch_gbe_enable_dma_rx(&adapter->hw);
+       pch_gbe_enable_mac_rx(&adapter->hw);
 
        mod_timer(&adapter->watchdog_timer, jiffies);
 
@@ -2009,6 +1969,11 @@ int pch_gbe_up(struct pch_gbe_adapter *adapter)
        netif_start_queue(adapter->netdev);
 
        return 0;
+
+freeirq:
+       pch_gbe_free_irq(adapter);
+out:
+       return err;
 }
 
 /**
@@ -2405,7 +2370,6 @@ static int pch_gbe_napi_poll(struct napi_struct *napi, int budget)
        int work_done = 0;
        bool poll_end_flag = false;
        bool cleaned = false;
-       u32 int_en;
 
        pr_debug("budget : %d\n", budget);
 
@@ -2422,19 +2386,13 @@ static int pch_gbe_napi_poll(struct napi_struct *napi, int budget)
 
        if (poll_end_flag) {
                napi_complete(napi);
-               if (adapter->rx_stop_flag) {
-                       adapter->rx_stop_flag = false;
-                       pch_gbe_start_receive(&adapter->hw);
-               }
                pch_gbe_irq_enable(adapter);
-       } else
-               if (adapter->rx_stop_flag) {
-                       adapter->rx_stop_flag = false;
-                       pch_gbe_start_receive(&adapter->hw);
-                       int_en = ioread32(&adapter->hw.reg->INT_EN);
-                       iowrite32((int_en | PCH_GBE_INT_RX_FIFO_ERR),
-                               &adapter->hw.reg->INT_EN);
-               }
+       }
+
+       if (adapter->rx_stop_flag) {
+               adapter->rx_stop_flag = false;
+               pch_gbe_enable_dma_rx(&adapter->hw);
+       }
 
        pr_debug("poll_end_flag : %d  work_done : %d  budget : %d\n",
                 poll_end_flag, work_done, budget);
index df09b1cb742fb211f639e0e6a16d658a768cf7d6..6407d0d77e810f038da14dfdf1447bae50794a8c 100644 (file)
@@ -2525,6 +2525,13 @@ static int ql_alloc_net_req_rsp_queues(struct ql3_adapter *qdev)
        qdev->req_q_size =
            (u32) (NUM_REQ_Q_ENTRIES * sizeof(struct ob_mac_iocb_req));
 
+       qdev->rsp_q_size = NUM_RSP_Q_ENTRIES * sizeof(struct net_rsp_iocb);
+
+       /* The barrier is required to ensure request and response queue
+        * addr writes to the registers.
+        */
+       wmb();
+
        qdev->req_q_virt_addr =
            pci_alloc_consistent(qdev->pdev,
                                 (size_t) qdev->req_q_size,
@@ -2536,8 +2543,6 @@ static int ql_alloc_net_req_rsp_queues(struct ql3_adapter *qdev)
                return -ENOMEM;
        }
 
-       qdev->rsp_q_size = NUM_RSP_Q_ENTRIES * sizeof(struct net_rsp_iocb);
-
        qdev->rsp_q_virt_addr =
            pci_alloc_consistent(qdev->pdev,
                                 (size_t) qdev->rsp_q_size,
index 1c818254b7bec650da02fc352625570a3937b6f8..b01f83a044c4d77f70141c81fee3815cd050f258 100644 (file)
@@ -979,17 +979,6 @@ static void cp_init_hw (struct cp_private *cp)
        cpw32_f (MAC0 + 0, le32_to_cpu (*(__le32 *) (dev->dev_addr + 0)));
        cpw32_f (MAC0 + 4, le32_to_cpu (*(__le32 *) (dev->dev_addr + 4)));
 
-       cpw32_f(HiTxRingAddr, 0);
-       cpw32_f(HiTxRingAddr + 4, 0);
-
-       ring_dma = cp->ring_dma;
-       cpw32_f(RxRingAddr, ring_dma & 0xffffffff);
-       cpw32_f(RxRingAddr + 4, (ring_dma >> 16) >> 16);
-
-       ring_dma += sizeof(struct cp_desc) * CP_RX_RING_SIZE;
-       cpw32_f(TxRingAddr, ring_dma & 0xffffffff);
-       cpw32_f(TxRingAddr + 4, (ring_dma >> 16) >> 16);
-
        cp_start_hw(cp);
        cpw8(TxThresh, 0x06); /* XXX convert magic num to a constant */
 
@@ -1003,6 +992,17 @@ static void cp_init_hw (struct cp_private *cp)
 
        cpw8(Config5, cpr8(Config5) & PMEStatus);
 
+       cpw32_f(HiTxRingAddr, 0);
+       cpw32_f(HiTxRingAddr + 4, 0);
+
+       ring_dma = cp->ring_dma;
+       cpw32_f(RxRingAddr, ring_dma & 0xffffffff);
+       cpw32_f(RxRingAddr + 4, (ring_dma >> 16) >> 16);
+
+       ring_dma += sizeof(struct cp_desc) * CP_RX_RING_SIZE;
+       cpw32_f(TxRingAddr, ring_dma & 0xffffffff);
+       cpw32_f(TxRingAddr + 4, (ring_dma >> 16) >> 16);
+
        cpw16(MultiIntr, 0);
 
        cpw8_f(Cfg9346, Cfg9346_Lock);
index e7ff886e8047ac3d3a926e8c0384b3ec7568068b..927aa33d43497eae636a6d3b4a0e93e15fc93b27 100644 (file)
@@ -3827,6 +3827,8 @@ static void rtl_wol_suspend_quirk(struct rtl8169_private *tp)
        void __iomem *ioaddr = tp->mmio_addr;
 
        switch (tp->mac_version) {
+       case RTL_GIGA_MAC_VER_25:
+       case RTL_GIGA_MAC_VER_26:
        case RTL_GIGA_MAC_VER_29:
        case RTL_GIGA_MAC_VER_30:
        case RTL_GIGA_MAC_VER_32:
@@ -4519,6 +4521,9 @@ static void rtl_set_rx_mode(struct net_device *dev)
                mc_filter[1] = swab32(data);
        }
 
+       if (tp->mac_version == RTL_GIGA_MAC_VER_35)
+               mc_filter[1] = mc_filter[0] = 0xffffffff;
+
        RTL_W32(MAR0 + 4, mc_filter[1]);
        RTL_W32(MAR0 + 0, mc_filter[0]);
 
index fb9f6b38511f97beddbff380c2ae7d31878e4ff4..edf5edb13140fb5908f0197298d17cf3b1cb7503 100644 (file)
@@ -2479,7 +2479,7 @@ static int sis900_resume(struct pci_dev *pci_dev)
        netif_start_queue(net_dev);
 
        /* Workaround for EDB */
-       sis900_set_mode(ioaddr, HW_SPEED_10_MBPS, FDX_CAPABLE_HALF_SELECTED);
+       sis900_set_mode(sis_priv, HW_SPEED_10_MBPS, FDX_CAPABLE_HALF_SELECTED);
 
        /* Enable all known interrupts by setting the interrupt mask. */
        sw32(imr, RxSOVR | RxORN | RxERR | RxOK | TxURN | TxERR | TxIDLE);
index 62d1baf111ea8f7afb3f1fa049b63666853861f5..c53c0f4e2ce311cc5083d218bff9f5d1ed8e56e0 100644 (file)
@@ -2110,7 +2110,7 @@ static void __devinit smsc911x_read_mac_address(struct net_device *dev)
 static int __devinit smsc911x_init(struct net_device *dev)
 {
        struct smsc911x_data *pdata = netdev_priv(dev);
-       unsigned int byte_test;
+       unsigned int byte_test, mask;
        unsigned int to = 100;
 
        SMSC_TRACE(pdata, probe, "Driver Parameters:");
@@ -2130,9 +2130,22 @@ static int __devinit smsc911x_init(struct net_device *dev)
        /*
         * poll the READY bit in PMT_CTRL. Any other access to the device is
         * forbidden while this bit isn't set. Try for 100ms
+        *
+        * Note that this test is done before the WORD_SWAP register is
+        * programmed. So in some configurations the READY bit is at 16 before
+        * WORD_SWAP is written to. This issue is worked around by waiting
+        * until either bit 0 or bit 16 gets set in PMT_CTRL.
+        *
+        * SMSC has confirmed that checking bit 16 (marked as reserved in
+        * the datasheet) is fine since these bits "will either never be set
+        * or can only go high after READY does (so also indicate the device
+        * is ready)".
         */
-       while (!(smsc911x_reg_read(pdata, PMT_CTRL) & PMT_CTRL_READY_) && --to)
+
+       mask = PMT_CTRL_READY_ | swahw32(PMT_CTRL_READY_);
+       while (!(smsc911x_reg_read(pdata, PMT_CTRL) & mask) && --to)
                udelay(1000);
+
        if (to == 0) {
                pr_err("Device not READY in 100ms aborting\n");
                return -ENODEV;
index b26cbda5efa9b5264dd4e2bb885d35ea7e26b692..2c41894d54726e86b70ee9d4e8aba4c6200437b5 100644 (file)
@@ -5,7 +5,7 @@
 config NET_VENDOR_TI
        bool "Texas Instruments (TI) devices"
        default y
-       depends on PCI || EISA || AR7 || (ARM && (ARCH_DAVINCI || ARCH_OMAP3))
+       depends on PCI || EISA || AR7 || (ARM && (ARCH_DAVINCI || ARCH_OMAP3 || SOC_AM33XX))
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
          and read the Ethernet-HOWTO, available from
index 4e2a1628484dfbc3a6fff901d976cf751bf8c151..66e025ad5df1a6e998ce0115f7057f89067b7bd3 100644 (file)
@@ -917,7 +917,7 @@ static int tile_net_setup_interrupts(struct net_device *dev)
        ingress_irq = rc;
        tile_irq_activate(ingress_irq, TILE_IRQ_PERCPU);
        rc = request_irq(ingress_irq, tile_net_handle_ingress_irq,
-                        0, NULL, NULL);
+                        0, "tile_net", NULL);
        if (rc != 0) {
                netdev_err(dev, "request_irq failed: %d\n", rc);
                destroy_irq(ingress_irq);
@@ -1334,11 +1334,11 @@ static int tso_count_edescs(struct sk_buff *skb)
 {
        struct skb_shared_info *sh = skb_shinfo(skb);
        unsigned int sh_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
-       unsigned int data_len = skb->data_len + skb->hdr_len - sh_len;
+       unsigned int data_len = skb->len - sh_len;
        unsigned int p_len = sh->gso_size;
        long f_id = -1;    /* id of the current fragment */
-       long f_size = skb->hdr_len;  /* size of the current fragment */
-       long f_used = sh_len;  /* bytes used from the current fragment */
+       long f_size = skb_headlen(skb) - sh_len;  /* current fragment size */
+       long f_used = 0;  /* bytes used from the current fragment */
        long n;            /* size of the current piece of payload */
        int num_edescs = 0;
        int segment;
@@ -1353,7 +1353,7 @@ static int tso_count_edescs(struct sk_buff *skb)
                        /* Advance as needed. */
                        while (f_used >= f_size) {
                                f_id++;
-                               f_size = sh->frags[f_id].size;
+                               f_size = skb_frag_size(&sh->frags[f_id]);
                                f_used = 0;
                        }
 
@@ -1384,13 +1384,13 @@ static void tso_headers_prepare(struct sk_buff *skb, unsigned char *headers,
        struct iphdr *ih;
        struct tcphdr *th;
        unsigned int sh_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
-       unsigned int data_len = skb->data_len + skb->hdr_len - sh_len;
+       unsigned int data_len = skb->len - sh_len;
        unsigned char *data = skb->data;
        unsigned int ih_off, th_off, p_len;
        unsigned int isum_seed, tsum_seed, id, seq;
        long f_id = -1;    /* id of the current fragment */
-       long f_size = skb->hdr_len;  /* size of the current fragment */
-       long f_used = sh_len;  /* bytes used from the current fragment */
+       long f_size = skb_headlen(skb) - sh_len;  /* current fragment size */
+       long f_used = 0;  /* bytes used from the current fragment */
        long n;            /* size of the current piece of payload */
        int segment;
 
@@ -1405,7 +1405,7 @@ static void tso_headers_prepare(struct sk_buff *skb, unsigned char *headers,
        isum_seed = ((0xFFFF - ih->check) +
                     (0xFFFF - ih->tot_len) +
                     (0xFFFF - ih->id));
-       tsum_seed = th->check + (0xFFFF ^ htons(sh_len + data_len));
+       tsum_seed = th->check + (0xFFFF ^ htons(skb->len));
        id = ntohs(ih->id);
        seq = ntohl(th->seq);
 
@@ -1444,7 +1444,7 @@ static void tso_headers_prepare(struct sk_buff *skb, unsigned char *headers,
                        /* Advance as needed. */
                        while (f_used >= f_size) {
                                f_id++;
-                               f_size = sh->frags[f_id].size;
+                               f_size = skb_frag_size(&sh->frags[f_id]);
                                f_used = 0;
                        }
 
@@ -1478,14 +1478,14 @@ static void tso_egress(struct net_device *dev, gxio_mpipe_equeue_t *equeue,
        struct tile_net_priv *priv = netdev_priv(dev);
        struct skb_shared_info *sh = skb_shinfo(skb);
        unsigned int sh_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
-       unsigned int data_len = skb->data_len + skb->hdr_len - sh_len;
+       unsigned int data_len = skb->len - sh_len;
        unsigned int p_len = sh->gso_size;
        gxio_mpipe_edesc_t edesc_head = { { 0 } };
        gxio_mpipe_edesc_t edesc_body = { { 0 } };
        long f_id = -1;    /* id of the current fragment */
-       long f_size = skb->hdr_len;  /* size of the current fragment */
-       long f_used = sh_len;  /* bytes used from the current fragment */
-       void *f_data = skb->data;
+       long f_size = skb_headlen(skb) - sh_len;  /* current fragment size */
+       long f_used = 0;  /* bytes used from the current fragment */
+       void *f_data = skb->data + sh_len;
        long n;            /* size of the current piece of payload */
        unsigned long tx_packets = 0, tx_bytes = 0;
        unsigned int csum_start;
@@ -1516,15 +1516,18 @@ static void tso_egress(struct net_device *dev, gxio_mpipe_equeue_t *equeue,
 
                /* Egress the payload. */
                while (p_used < p_len) {
+                       void *va;
 
                        /* Advance as needed. */
                        while (f_used >= f_size) {
                                f_id++;
-                               f_size = sh->frags[f_id].size;
-                               f_used = 0;
+                               f_size = skb_frag_size(&sh->frags[f_id]);
                                f_data = tile_net_frag_buf(&sh->frags[f_id]);
+                               f_used = 0;
                        }
 
+                       va = f_data + f_used;
+
                        /* Use bytes from the current fragment. */
                        n = p_len - p_used;
                        if (n > f_size - f_used)
@@ -1533,7 +1536,7 @@ static void tso_egress(struct net_device *dev, gxio_mpipe_equeue_t *equeue,
                        p_used += n;
 
                        /* Egress a piece of the payload. */
-                       edesc_body.va = va_to_tile_io_addr(f_data) + f_used;
+                       edesc_body.va = va_to_tile_io_addr(va);
                        edesc_body.xfer_size = n;
                        edesc_body.bound = !(p_used < p_len);
                        gxio_mpipe_equeue_put_at(equeue, edesc_body, slot);
index 0793299bd39ec9489908a206b073c32e0e8b3923..a788501e978e116908cf0e7a0c92745c275b2009 100644 (file)
@@ -894,6 +894,8 @@ out:
        return IRQ_HANDLED;
 }
 
+static void axienet_dma_err_handler(unsigned long data);
+
 /**
  * axienet_open - Driver open routine.
  * @ndev:      Pointer to net_device structure
@@ -942,6 +944,10 @@ static int axienet_open(struct net_device *ndev)
                phy_start(lp->phy_dev);
        }
 
+       /* Enable tasklets for Axi DMA error handling */
+       tasklet_init(&lp->dma_err_tasklet, axienet_dma_err_handler,
+                    (unsigned long) lp);
+
        /* Enable interrupts for Axi DMA Tx */
        ret = request_irq(lp->tx_irq, axienet_tx_irq, 0, ndev->name, ndev);
        if (ret)
@@ -950,8 +956,7 @@ static int axienet_open(struct net_device *ndev)
        ret = request_irq(lp->rx_irq, axienet_rx_irq, 0, ndev->name, ndev);
        if (ret)
                goto err_rx_irq;
-       /* Enable tasklets for Axi DMA error handling */
-       tasklet_enable(&lp->dma_err_tasklet);
+
        return 0;
 
 err_rx_irq:
@@ -960,6 +965,7 @@ err_tx_irq:
        if (lp->phy_dev)
                phy_disconnect(lp->phy_dev);
        lp->phy_dev = NULL;
+       tasklet_kill(&lp->dma_err_tasklet);
        dev_err(lp->dev, "request_irq() failed\n");
        return ret;
 }
@@ -990,7 +996,7 @@ static int axienet_stop(struct net_device *ndev)
        axienet_setoptions(ndev, lp->options &
                           ~(XAE_OPTION_TXEN | XAE_OPTION_RXEN));
 
-       tasklet_disable(&lp->dma_err_tasklet);
+       tasklet_kill(&lp->dma_err_tasklet);
 
        free_irq(lp->tx_irq, ndev);
        free_irq(lp->rx_irq, ndev);
@@ -1613,10 +1619,6 @@ static int __devinit axienet_of_probe(struct platform_device *op)
                goto err_iounmap_2;
        }
 
-       tasklet_init(&lp->dma_err_tasklet, axienet_dma_err_handler,
-                    (unsigned long) lp);
-       tasklet_disable(&lp->dma_err_tasklet);
-
        return 0;
 
 err_iounmap_2:
index 98934bdf6acffc053fcd317721e8d92cf649ba14..477d6729b17f7f391c34a520bc08f8031bfbd4ae 100644 (file)
@@ -1102,10 +1102,12 @@ static int init_queues(struct port *port)
 {
        int i;
 
-       if (!ports_open)
-               if (!(dma_pool = dma_pool_create(DRV_NAME, NULL,
-                                                POOL_ALLOC_SIZE, 32, 0)))
+       if (!ports_open) {
+               dma_pool = dma_pool_create(DRV_NAME, &port->netdev->dev,
+                                          POOL_ALLOC_SIZE, 32, 0);
+               if (!dma_pool)
                        return -ENOMEM;
+       }
 
        if (!(port->desc_tab = dma_pool_alloc(dma_pool, GFP_KERNEL,
                                              &port->desc_tab_phys)))
index 5039f08f5a5b23cacd0f145cd790a30fce47806e..43e9ab4f4d7edc0b6771c1664d2064c164e37ec3 100644 (file)
@@ -222,7 +222,7 @@ static void sirdev_config_fsm(struct work_struct *work)
                        break;
 
                case SIRDEV_STATE_DONGLE_SPEED:
-                       if (dev->dongle_drv->reset) {
+                       if (dev->dongle_drv->set_speed) {
                                ret = dev->dongle_drv->set_speed(dev, fsm->param);
                                if (ret < 0) {
                                        fsm->result = ret;
index 983bbf4d5ef6a7437118ac2d21ba2cb66599bc8c..961f0b2939132b0b2e50a94e7610cfb72ce8faf4 100644 (file)
@@ -15,6 +15,11 @@ if PHYLIB
 
 comment "MII PHY device drivers"
 
+config AT803X_PHY
+       tristate "Drivers for Atheros AT803X PHYs"
+       ---help---
+         Currently supports the AT8030 and AT8035 model
+
 config AMD_PHY
        tristate "Drivers for the AMD PHYs"
        ---help---
index 426674debae44dfb9967e305ad571f7012010afb..9645e389a58d34fbdb0c74a737d61b33a4885b6a 100644 (file)
@@ -25,6 +25,7 @@ obj-$(CONFIG_STE10XP)         += ste10Xp.o
 obj-$(CONFIG_MICREL_PHY)       += micrel.o
 obj-$(CONFIG_MDIO_OCTEON)      += mdio-octeon.o
 obj-$(CONFIG_MICREL_KS8995MA)  += spi_ks8995.o
+obj-$(CONFIG_AT803X_PHY)       += at803x.o
 obj-$(CONFIG_AMD_PHY)          += amd.o
 obj-$(CONFIG_MDIO_BUS_MUX)     += mdio-mux.o
 obj-$(CONFIG_MDIO_BUS_MUX_GPIO)        += mdio-mux-gpio.o
diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
new file mode 100644 (file)
index 0000000..45cbc10
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * drivers/net/phy/at803x.c
+ *
+ * Driver for Atheros 803x PHY
+ *
+ * Author: Matus Ujhelyi <ujhelyi.m@gmail.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/phy.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+
+#define AT803X_INTR_ENABLE                     0x12
+#define AT803X_INTR_STATUS                     0x13
+#define AT803X_WOL_ENABLE                      0x01
+#define AT803X_DEVICE_ADDR                     0x03
+#define AT803X_LOC_MAC_ADDR_0_15_OFFSET                0x804C
+#define AT803X_LOC_MAC_ADDR_16_31_OFFSET       0x804B
+#define AT803X_LOC_MAC_ADDR_32_47_OFFSET       0x804A
+#define AT803X_MMD_ACCESS_CONTROL              0x0D
+#define AT803X_MMD_ACCESS_CONTROL_DATA         0x0E
+#define AT803X_FUNC_DATA                       0x4003
+
+MODULE_DESCRIPTION("Atheros 803x PHY driver");
+MODULE_AUTHOR("Matus Ujhelyi");
+MODULE_LICENSE("GPL");
+
+static void at803x_set_wol_mac_addr(struct phy_device *phydev)
+{
+       struct net_device *ndev = phydev->attached_dev;
+       const u8 *mac;
+       unsigned int i, offsets[] = {
+               AT803X_LOC_MAC_ADDR_32_47_OFFSET,
+               AT803X_LOC_MAC_ADDR_16_31_OFFSET,
+               AT803X_LOC_MAC_ADDR_0_15_OFFSET,
+       };
+
+       if (!ndev)
+               return;
+
+       mac = (const u8 *) ndev->dev_addr;
+
+       if (!is_valid_ether_addr(mac))
+               return;
+
+       for (i = 0; i < 3; i++) {
+               phy_write(phydev, AT803X_MMD_ACCESS_CONTROL,
+                                 AT803X_DEVICE_ADDR);
+               phy_write(phydev, AT803X_MMD_ACCESS_CONTROL_DATA,
+                                 offsets[i]);
+               phy_write(phydev, AT803X_MMD_ACCESS_CONTROL,
+                                 AT803X_FUNC_DATA);
+               phy_write(phydev, AT803X_MMD_ACCESS_CONTROL_DATA,
+                                 mac[(i * 2) + 1] | (mac[(i * 2)] << 8));
+       }
+}
+
+static int at803x_config_init(struct phy_device *phydev)
+{
+       int val;
+       u32 features;
+       int status;
+
+       features = SUPPORTED_TP | SUPPORTED_MII | SUPPORTED_AUI |
+                  SUPPORTED_FIBRE | SUPPORTED_BNC;
+
+       val = phy_read(phydev, MII_BMSR);
+       if (val < 0)
+               return val;
+
+       if (val & BMSR_ANEGCAPABLE)
+               features |= SUPPORTED_Autoneg;
+       if (val & BMSR_100FULL)
+               features |= SUPPORTED_100baseT_Full;
+       if (val & BMSR_100HALF)
+               features |= SUPPORTED_100baseT_Half;
+       if (val & BMSR_10FULL)
+               features |= SUPPORTED_10baseT_Full;
+       if (val & BMSR_10HALF)
+               features |= SUPPORTED_10baseT_Half;
+
+       if (val & BMSR_ESTATEN) {
+               val = phy_read(phydev, MII_ESTATUS);
+               if (val < 0)
+                       return val;
+
+               if (val & ESTATUS_1000_TFULL)
+                       features |= SUPPORTED_1000baseT_Full;
+               if (val & ESTATUS_1000_THALF)
+                       features |= SUPPORTED_1000baseT_Half;
+       }
+
+       phydev->supported = features;
+       phydev->advertising = features;
+
+       /* enable WOL */
+       at803x_set_wol_mac_addr(phydev);
+       status = phy_write(phydev, AT803X_INTR_ENABLE, AT803X_WOL_ENABLE);
+       status = phy_read(phydev, AT803X_INTR_STATUS);
+
+       return 0;
+}
+
+/* ATHEROS 8035 */
+static struct phy_driver at8035_driver = {
+       .phy_id         = 0x004dd072,
+       .name           = "Atheros 8035 ethernet",
+       .phy_id_mask    = 0xffffffef,
+       .config_init    = at803x_config_init,
+       .features       = PHY_GBIT_FEATURES,
+       .flags          = PHY_HAS_INTERRUPT,
+       .config_aneg    = &genphy_config_aneg,
+       .read_status    = &genphy_read_status,
+       .driver         = {
+               .owner = THIS_MODULE,
+       },
+};
+
+/* ATHEROS 8030 */
+static struct phy_driver at8030_driver = {
+       .phy_id         = 0x004dd076,
+       .name           = "Atheros 8030 ethernet",
+       .phy_id_mask    = 0xffffffef,
+       .config_init    = at803x_config_init,
+       .features       = PHY_GBIT_FEATURES,
+       .flags          = PHY_HAS_INTERRUPT,
+       .config_aneg    = &genphy_config_aneg,
+       .read_status    = &genphy_read_status,
+       .driver         = {
+               .owner = THIS_MODULE,
+       },
+};
+
+static int __init atheros_init(void)
+{
+       int ret;
+
+       ret = phy_driver_register(&at8035_driver);
+       if (ret)
+               goto err1;
+
+       ret = phy_driver_register(&at8030_driver);
+       if (ret)
+               goto err2;
+
+       return 0;
+
+err2:
+       phy_driver_unregister(&at8035_driver);
+err1:
+       return ret;
+}
+
+static void __exit atheros_exit(void)
+{
+       phy_driver_unregister(&at8035_driver);
+       phy_driver_unregister(&at8030_driver);
+}
+
+module_init(atheros_init);
+module_exit(atheros_exit);
+
+static struct mdio_device_id __maybe_unused atheros_tbl[] = {
+       { 0x004dd076, 0xffffffef },
+       { 0x004dd072, 0xffffffef },
+       { }
+};
+
+MODULE_DEVICE_TABLE(mdio, atheros_tbl);
index 899274f2f9b1dd1da0aac0442807b6e42b0cddc2..2ed1140df3e9fc0afbc25bce03e5a6eba7ceb228 100644 (file)
@@ -185,17 +185,20 @@ static int __devinit mdio_gpio_probe(struct platform_device *pdev)
 {
        struct mdio_gpio_platform_data *pdata;
        struct mii_bus *new_bus;
-       int ret;
+       int ret, bus_id;
 
-       if (pdev->dev.of_node)
+       if (pdev->dev.of_node) {
                pdata = mdio_gpio_of_get_data(pdev);
-       else
+               bus_id = of_alias_get_id(pdev->dev.of_node, "mdio-gpio");
+       } else {
                pdata = pdev->dev.platform_data;
+               bus_id = pdev->id;
+       }
 
        if (!pdata)
                return -ENODEV;
 
-       new_bus = mdio_gpio_bus_init(&pdev->dev, pdata, pdev->id);
+       new_bus = mdio_gpio_bus_init(&pdev->dev, pdata, bus_id);
        if (!new_bus)
                return -ENODEV;
 
index 9db0171e93669f483eeae19791ed4e090c333bb0..c5db428e73fa2200f3ef8a5ea5124ceeebb6ef78 100644 (file)
@@ -29,8 +29,8 @@ static bool bc_transmit(struct team *team, struct sk_buff *skb)
                        if (last) {
                                skb2 = skb_clone(skb, GFP_ATOMIC);
                                if (skb2) {
-                                       ret = team_dev_queue_xmit(team, last,
-                                                                 skb2);
+                                       ret = !team_dev_queue_xmit(team, last,
+                                                                  skb2);
                                        if (!sum_ret)
                                                sum_ret = ret;
                                }
@@ -39,7 +39,7 @@ static bool bc_transmit(struct team *team, struct sk_buff *skb)
                }
        }
        if (last) {
-               ret = team_dev_queue_xmit(team, last, skb);
+               ret = !team_dev_queue_xmit(team, last, skb);
                if (!sum_ret)
                        sum_ret = ret;
        }
index c81e278629ff8595b6e246878e805ed51874a5c7..08d55b6bf272bc5293a8a8d059d54d652aca27e1 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/usb/cdc.h>
 #include <linux/usb/usbnet.h>
 #include <linux/gfp.h>
+#include <linux/if_vlan.h>
 
 
 /*
@@ -92,7 +93,7 @@ static int eem_bind(struct usbnet *dev, struct usb_interface *intf)
 
        /* no jumbogram (16K) support for now */
 
-       dev->net->hard_header_len += EEM_HEAD + ETH_FCS_LEN;
+       dev->net->hard_header_len += EEM_HEAD + ETH_FCS_LEN + VLAN_HLEN;
        dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
 
        return 0;
index a03de71970499b7daaad750768318f4d08af6160..d0129827602b2867380ca4f8f774bfa104f2eef2 100644 (file)
@@ -592,6 +592,32 @@ static const struct usb_device_id  products [] = {
        .driver_info            = 0,
 },
 
+/* Novatel USB551L and MC551 - handled by qmi_wwan */
+{
+       .match_flags    =   USB_DEVICE_ID_MATCH_VENDOR
+                | USB_DEVICE_ID_MATCH_PRODUCT
+                | USB_DEVICE_ID_MATCH_INT_INFO,
+       .idVendor               = NOVATEL_VENDOR_ID,
+       .idProduct              = 0xB001,
+       .bInterfaceClass        = USB_CLASS_COMM,
+       .bInterfaceSubClass     = USB_CDC_SUBCLASS_ETHERNET,
+       .bInterfaceProtocol     = USB_CDC_PROTO_NONE,
+       .driver_info = 0,
+},
+
+/* Novatel E362 - handled by qmi_wwan */
+{
+       .match_flags    =   USB_DEVICE_ID_MATCH_VENDOR
+                | USB_DEVICE_ID_MATCH_PRODUCT
+                | USB_DEVICE_ID_MATCH_INT_INFO,
+       .idVendor               = NOVATEL_VENDOR_ID,
+       .idProduct              = 0x9010,
+       .bInterfaceClass        = USB_CLASS_COMM,
+       .bInterfaceSubClass     = USB_CDC_SUBCLASS_ETHERNET,
+       .bInterfaceProtocol     = USB_CDC_PROTO_NONE,
+       .driver_info = 0,
+},
+
 /*
  * WHITELIST!!!
  *
@@ -604,21 +630,6 @@ static const struct usb_device_id  products [] = {
  * because of bugs/quirks in a given product (like Zaurus, above).
  */
 {
-       /* Novatel USB551L */
-       /* This match must come *before* the generic CDC-ETHER match so that
-        * we get FLAG_WWAN set on the device, since it's descriptors are
-        * generic CDC-ETHER.
-        */
-       .match_flags    =   USB_DEVICE_ID_MATCH_VENDOR
-                | USB_DEVICE_ID_MATCH_PRODUCT
-                | USB_DEVICE_ID_MATCH_INT_INFO,
-       .idVendor               = NOVATEL_VENDOR_ID,
-       .idProduct              = 0xB001,
-       .bInterfaceClass        = USB_CLASS_COMM,
-       .bInterfaceSubClass     = USB_CDC_SUBCLASS_ETHERNET,
-       .bInterfaceProtocol     = USB_CDC_PROTO_NONE,
-       .driver_info = (unsigned long)&wwan_info,
-}, {
        /* ZTE (Vodafone) K3805-Z */
        .match_flags    =   USB_DEVICE_ID_MATCH_VENDOR
                 | USB_DEVICE_ID_MATCH_PRODUCT
index 4cd582a4f625d55d5edd8c2cd3952d5571074921..74fab1a4015657b52bd5b4c690990120171dc509 100644 (file)
@@ -540,10 +540,12 @@ advance:
            (ctx->ether_desc == NULL) || (ctx->control != intf))
                goto error;
 
-       /* claim interfaces, if any */
-       temp = usb_driver_claim_interface(driver, ctx->data, dev);
-       if (temp)
-               goto error;
+       /* claim data interface, if different from control */
+       if (ctx->data != ctx->control) {
+               temp = usb_driver_claim_interface(driver, ctx->data, dev);
+               if (temp)
+                       goto error;
+       }
 
        iface_no = ctx->data->cur_altsetting->desc.bInterfaceNumber;
 
@@ -623,6 +625,10 @@ static void cdc_ncm_unbind(struct usbnet *dev, struct usb_interface *intf)
 
        tasklet_kill(&ctx->bh);
 
+       /* handle devices with combined control and data interface */
+       if (ctx->control == ctx->data)
+               ctx->data = NULL;
+
        /* disconnect master --> disconnect slave */
        if (intf == ctx->control && ctx->data) {
                usb_set_intfdata(ctx->data, NULL);
@@ -1245,6 +1251,14 @@ static const struct usb_device_id cdc_devs[] = {
          .driver_info = (unsigned long) &wwan_info,
        },
 
+       /* Huawei NCM devices disguised as vendor specific */
+       { USB_VENDOR_AND_INTERFACE_INFO(0x12d1, 0xff, 0x02, 0x16),
+         .driver_info = (unsigned long)&wwan_info,
+       },
+       { USB_VENDOR_AND_INTERFACE_INFO(0x12d1, 0xff, 0x02, 0x46),
+         .driver_info = (unsigned long)&wwan_info,
+       },
+
        /* Generic CDC-NCM devices */
        { USB_INTERFACE_INFO(USB_CLASS_COMM,
                USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE),
index a28a983d465e6d434a3272a36a9ab35a7b5b3eee..534d8becbbdc779219f26c3df0481cd07171bcc7 100644 (file)
@@ -62,6 +62,7 @@
 #define USB_PRODUCT_IPAD 0x129a
 #define USB_PRODUCT_IPHONE_4_VZW 0x129c
 #define USB_PRODUCT_IPHONE_4S  0x12a0
+#define USB_PRODUCT_IPHONE_5   0x12a8
 
 #define IPHETH_USBINTF_CLASS    255
 #define IPHETH_USBINTF_SUBCLASS 253
@@ -113,6 +114,10 @@ static struct usb_device_id ipheth_table[] = {
                USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_4S,
                IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS,
                IPHETH_USBINTF_PROTO) },
+       { USB_DEVICE_AND_INTERFACE_INFO(
+               USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_5,
+               IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS,
+               IPHETH_USBINTF_PROTO) },
        { }
 };
 MODULE_DEVICE_TABLE(usb, ipheth_table);
index 6883c371c59f5a2eb416466563cad5e1fbaa5b9a..3b566fa0f8e6277ee62f281211a0507dfdf7c227 100644 (file)
@@ -369,18 +369,73 @@ static const struct usb_device_id products[] = {
                USB_VENDOR_AND_INTERFACE_INFO(0x106c, USB_CLASS_VENDOR_SPEC, 0xf1, 0xff),
                .driver_info        = (unsigned long)&qmi_wwan_info,
        },
+       {       /* Novatel USB551L and MC551 */
+               USB_DEVICE_AND_INTERFACE_INFO(0x1410, 0xb001,
+                                             USB_CLASS_COMM,
+                                             USB_CDC_SUBCLASS_ETHERNET,
+                                             USB_CDC_PROTO_NONE),
+               .driver_info        = (unsigned long)&qmi_wwan_info,
+       },
+       {       /* Novatel E362 */
+               USB_DEVICE_AND_INTERFACE_INFO(0x1410, 0x9010,
+                                             USB_CLASS_COMM,
+                                             USB_CDC_SUBCLASS_ETHERNET,
+                                             USB_CDC_PROTO_NONE),
+               .driver_info        = (unsigned long)&qmi_wwan_info,
+       },
 
        /* 3. Combined interface devices matching on interface number */
+       {QMI_FIXED_INTF(0x19d2, 0x0002, 1)},
+       {QMI_FIXED_INTF(0x19d2, 0x0012, 1)},
+       {QMI_FIXED_INTF(0x19d2, 0x0017, 3)},
+       {QMI_FIXED_INTF(0x19d2, 0x0021, 4)},
+       {QMI_FIXED_INTF(0x19d2, 0x0025, 1)},
+       {QMI_FIXED_INTF(0x19d2, 0x0031, 4)},
+       {QMI_FIXED_INTF(0x19d2, 0x0042, 4)},
+       {QMI_FIXED_INTF(0x19d2, 0x0049, 5)},
+       {QMI_FIXED_INTF(0x19d2, 0x0052, 4)},
        {QMI_FIXED_INTF(0x19d2, 0x0055, 1)},    /* ZTE (Vodafone) K3520-Z */
+       {QMI_FIXED_INTF(0x19d2, 0x0058, 4)},
        {QMI_FIXED_INTF(0x19d2, 0x0063, 4)},    /* ZTE (Vodafone) K3565-Z */
        {QMI_FIXED_INTF(0x19d2, 0x0104, 4)},    /* ZTE (Vodafone) K4505-Z */
+       {QMI_FIXED_INTF(0x19d2, 0x0113, 5)},
+       {QMI_FIXED_INTF(0x19d2, 0x0118, 5)},
+       {QMI_FIXED_INTF(0x19d2, 0x0121, 5)},
+       {QMI_FIXED_INTF(0x19d2, 0x0123, 4)},
+       {QMI_FIXED_INTF(0x19d2, 0x0124, 5)},
+       {QMI_FIXED_INTF(0x19d2, 0x0125, 6)},
+       {QMI_FIXED_INTF(0x19d2, 0x0126, 5)},
+       {QMI_FIXED_INTF(0x19d2, 0x0130, 1)},
+       {QMI_FIXED_INTF(0x19d2, 0x0133, 3)},
+       {QMI_FIXED_INTF(0x19d2, 0x0141, 5)},
        {QMI_FIXED_INTF(0x19d2, 0x0157, 5)},    /* ZTE MF683 */
+       {QMI_FIXED_INTF(0x19d2, 0x0158, 3)},
        {QMI_FIXED_INTF(0x19d2, 0x0167, 4)},    /* ZTE MF820D */
+       {QMI_FIXED_INTF(0x19d2, 0x0168, 4)},
+       {QMI_FIXED_INTF(0x19d2, 0x0176, 3)},
+       {QMI_FIXED_INTF(0x19d2, 0x0178, 3)},
+       {QMI_FIXED_INTF(0x19d2, 0x0191, 4)},    /* ZTE EuFi890 */
+       {QMI_FIXED_INTF(0x19d2, 0x0199, 1)},    /* ZTE MF820S */
+       {QMI_FIXED_INTF(0x19d2, 0x0200, 1)},
+       {QMI_FIXED_INTF(0x19d2, 0x0257, 3)},    /* ZTE MF821 */
        {QMI_FIXED_INTF(0x19d2, 0x0326, 4)},    /* ZTE MF821D */
        {QMI_FIXED_INTF(0x19d2, 0x1008, 4)},    /* ZTE (Vodafone) K3570-Z */
        {QMI_FIXED_INTF(0x19d2, 0x1010, 4)},    /* ZTE (Vodafone) K3571-Z */
+       {QMI_FIXED_INTF(0x19d2, 0x1012, 4)},
        {QMI_FIXED_INTF(0x19d2, 0x1018, 3)},    /* ZTE (Vodafone) K5006-Z */
+       {QMI_FIXED_INTF(0x19d2, 0x1021, 2)},
+       {QMI_FIXED_INTF(0x19d2, 0x1245, 4)},
+       {QMI_FIXED_INTF(0x19d2, 0x1247, 4)},
+       {QMI_FIXED_INTF(0x19d2, 0x1252, 4)},
+       {QMI_FIXED_INTF(0x19d2, 0x1254, 4)},
+       {QMI_FIXED_INTF(0x19d2, 0x1255, 3)},
+       {QMI_FIXED_INTF(0x19d2, 0x1255, 4)},
+       {QMI_FIXED_INTF(0x19d2, 0x1256, 4)},
+       {QMI_FIXED_INTF(0x19d2, 0x1401, 2)},
        {QMI_FIXED_INTF(0x19d2, 0x1402, 2)},    /* ZTE MF60 */
+       {QMI_FIXED_INTF(0x19d2, 0x1424, 2)},
+       {QMI_FIXED_INTF(0x19d2, 0x1425, 2)},
+       {QMI_FIXED_INTF(0x19d2, 0x1426, 2)},    /* ZTE MF91 */
        {QMI_FIXED_INTF(0x19d2, 0x2002, 4)},    /* ZTE (Vodafone) K3765-Z */
        {QMI_FIXED_INTF(0x0f3d, 0x68a2, 8)},    /* Sierra Wireless MC7700 */
        {QMI_FIXED_INTF(0x114f, 0x68a2, 8)},    /* Sierra Wireless MC7750 */
index 7479a5761d0d6b35c9a275ae470e49dc959de366..362cb8cfeb92b6021f48995226117ccd0c971faf 100644 (file)
@@ -184,7 +184,7 @@ static int smsc95xx_mdio_read(struct net_device *netdev, int phy_id, int idx)
        /* set the address, index & direction (read from PHY) */
        phy_id &= dev->mii.phy_id_mask;
        idx &= dev->mii.reg_num_mask;
-       addr = (phy_id << 11) | (idx << 6) | MII_READ_;
+       addr = (phy_id << 11) | (idx << 6) | MII_READ_ | MII_BUSY_;
        ret = smsc95xx_write_reg(dev, MII_ADDR, addr);
        check_warn_goto_done(ret, "Error writing MII_ADDR");
 
@@ -221,7 +221,7 @@ static void smsc95xx_mdio_write(struct net_device *netdev, int phy_id, int idx,
        /* set the address, index & direction (write to PHY) */
        phy_id &= dev->mii.phy_id_mask;
        idx &= dev->mii.reg_num_mask;
-       addr = (phy_id << 11) | (idx << 6) | MII_WRITE_;
+       addr = (phy_id << 11) | (idx << 6) | MII_WRITE_ | MII_BUSY_;
        ret = smsc95xx_write_reg(dev, MII_ADDR, addr);
        check_warn_goto_done(ret, "Error writing MII_ADDR");
 
@@ -1344,6 +1344,7 @@ static struct sk_buff *smsc95xx_tx_fixup(struct usbnet *dev,
                } else {
                        u32 csum_preamble = smsc95xx_calc_csum_preamble(skb);
                        skb_push(skb, 4);
+                       cpu_to_le32s(&csum_preamble);
                        memcpy(skb->data, &csum_preamble, 4);
                }
        }
index f9819d10b1f9d41f864dc710e6799ffed9f9d5f0..edb81ed06950624a182ad1e298f2f54d142804e7 100644 (file)
@@ -359,10 +359,12 @@ static enum skb_state defer_bh(struct usbnet *dev, struct sk_buff *skb,
 void usbnet_defer_kevent (struct usbnet *dev, int work)
 {
        set_bit (work, &dev->flags);
-       if (!schedule_work (&dev->kevent))
-               netdev_err(dev->net, "kevent %d may have been dropped\n", work);
-       else
+       if (!schedule_work (&dev->kevent)) {
+               if (net_ratelimit())
+                       netdev_err(dev->net, "kevent %d may have been dropped\n", work);
+       } else {
                netdev_dbg(dev->net, "kevent %d scheduled\n", work);
+       }
 }
 EXPORT_SYMBOL_GPL(usbnet_defer_kevent);
 
@@ -1158,6 +1160,7 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb,
                usb_anchor_urb(urb, &dev->deferred);
                /* no use to process more packets */
                netif_stop_queue(net);
+               usb_put_urb(urb);
                spin_unlock_irqrestore(&dev->txq.lock, flags);
                netdev_dbg(dev->net, "Delaying transmission for resumption\n");
                goto deferred;
@@ -1310,6 +1313,8 @@ void usbnet_disconnect (struct usb_interface *intf)
 
        cancel_work_sync(&dev->kevent);
 
+       usb_scuttle_anchored_urbs(&dev->deferred);
+
        if (dev->driver_info->unbind)
                dev->driver_info->unbind (dev, intf);
 
index ce9d4f2c9776e08d1b543f18de8cb7100fe43a86..0ae1bcc6da730fecd4267f0076b3f3ef422ea7ce 100644 (file)
@@ -744,28 +744,43 @@ vmxnet3_map_pkt(struct sk_buff *skb, struct vmxnet3_tx_ctx *ctx,
 
        for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
                const struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i];
+               u32 buf_size;
 
-               tbi = tq->buf_info + tq->tx_ring.next2fill;
-               tbi->map_type = VMXNET3_MAP_PAGE;
-               tbi->dma_addr = skb_frag_dma_map(&adapter->pdev->dev, frag,
-                                                0, skb_frag_size(frag),
-                                                DMA_TO_DEVICE);
+               buf_offset = 0;
+               len = skb_frag_size(frag);
+               while (len) {
+                       tbi = tq->buf_info + tq->tx_ring.next2fill;
+                       if (len < VMXNET3_MAX_TX_BUF_SIZE) {
+                               buf_size = len;
+                               dw2 |= len;
+                       } else {
+                               buf_size = VMXNET3_MAX_TX_BUF_SIZE;
+                               /* spec says that for TxDesc.len, 0 == 2^14 */
+                       }
+                       tbi->map_type = VMXNET3_MAP_PAGE;
+                       tbi->dma_addr = skb_frag_dma_map(&adapter->pdev->dev, frag,
+                                                        buf_offset, buf_size,
+                                                        DMA_TO_DEVICE);
 
-               tbi->len = skb_frag_size(frag);
+                       tbi->len = buf_size;
 
-               gdesc = tq->tx_ring.base + tq->tx_ring.next2fill;
-               BUG_ON(gdesc->txd.gen == tq->tx_ring.gen);
+                       gdesc = tq->tx_ring.base + tq->tx_ring.next2fill;
+                       BUG_ON(gdesc->txd.gen == tq->tx_ring.gen);
 
-               gdesc->txd.addr = cpu_to_le64(tbi->dma_addr);
-               gdesc->dword[2] = cpu_to_le32(dw2 | skb_frag_size(frag));
-               gdesc->dword[3] = 0;
+                       gdesc->txd.addr = cpu_to_le64(tbi->dma_addr);
+                       gdesc->dword[2] = cpu_to_le32(dw2);
+                       gdesc->dword[3] = 0;
 
-               dev_dbg(&adapter->netdev->dev,
-                       "txd[%u]: 0x%llu %u %u\n",
-                       tq->tx_ring.next2fill, le64_to_cpu(gdesc->txd.addr),
-                       le32_to_cpu(gdesc->dword[2]), gdesc->dword[3]);
-               vmxnet3_cmd_ring_adv_next2fill(&tq->tx_ring);
-               dw2 = tq->tx_ring.gen << VMXNET3_TXD_GEN_SHIFT;
+                       dev_dbg(&adapter->netdev->dev,
+                               "txd[%u]: 0x%llu %u %u\n",
+                               tq->tx_ring.next2fill, le64_to_cpu(gdesc->txd.addr),
+                               le32_to_cpu(gdesc->dword[2]), gdesc->dword[3]);
+                       vmxnet3_cmd_ring_adv_next2fill(&tq->tx_ring);
+                       dw2 = tq->tx_ring.gen << VMXNET3_TXD_GEN_SHIFT;
+
+                       len -= buf_size;
+                       buf_offset += buf_size;
+               }
        }
 
        ctx->eop_txd = gdesc;
@@ -886,6 +901,18 @@ vmxnet3_prepare_tso(struct sk_buff *skb,
        }
 }
 
+static int txd_estimate(const struct sk_buff *skb)
+{
+       int count = VMXNET3_TXD_NEEDED(skb_headlen(skb)) + 1;
+       int i;
+
+       for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+               const struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i];
+
+               count += VMXNET3_TXD_NEEDED(skb_frag_size(frag));
+       }
+       return count;
+}
 
 /*
  * Transmits a pkt thru a given tq
@@ -914,9 +941,7 @@ vmxnet3_tq_xmit(struct sk_buff *skb, struct vmxnet3_tx_queue *tq,
        union Vmxnet3_GenericDesc tempTxDesc;
 #endif
 
-       /* conservatively estimate # of descriptors to use */
-       count = VMXNET3_TXD_NEEDED(skb_headlen(skb)) +
-               skb_shinfo(skb)->nr_frags + 1;
+       count = txd_estimate(skb);
 
        ctx.ipv4 = (vlan_get_protocol(skb) == cpu_to_be16(ETH_P_IP));
 
index 607976c001626a75afbf590411bf6ec1bbff26c0..8b5c6191707626ba64bad7bdceeab2c299e5bcfc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * VXLAN: Virtual eXtensiable Local Area Network
+ * VXLAN: Virtual eXtensible Local Area Network
  *
  * Copyright (c) 2012 Vyatta Inc.
  *
@@ -50,8 +50,8 @@
 
 #define VXLAN_N_VID    (1u << 24)
 #define VXLAN_VID_MASK (VXLAN_N_VID - 1)
-/* VLAN + IP header + UDP + VXLAN */
-#define VXLAN_HEADROOM (4 + 20 + 8 + 8)
+/* IP header + UDP + VXLAN + Ethernet header */
+#define VXLAN_HEADROOM (20 + 8 + 8 + 14)
 
 #define VXLAN_FLAGS 0x08000000 /* struct vxlanhdr.vx_flags required value. */
 
@@ -816,7 +816,7 @@ static void vxlan_cleanup(unsigned long arg)
                                = container_of(p, struct vxlan_fdb, hlist);
                        unsigned long timeout;
 
-                       if (f->state == NUD_PERMANENT)
+                       if (f->state & NUD_PERMANENT)
                                continue;
 
                        timeout = f->used + vxlan->age_interval * HZ;
@@ -1102,6 +1102,10 @@ static int vxlan_newlink(struct net *net, struct net_device *dev,
 
                if (!tb[IFLA_MTU])
                        dev->mtu = lowerdev->mtu - VXLAN_HEADROOM;
+
+               /* update header length based on lower device */
+               dev->hard_header_len = lowerdev->hard_header_len +
+                                      VXLAN_HEADROOM;
        }
 
        if (data[IFLA_VXLAN_TOS])
index 3f575afd8cfcb03f283df0932f6fb33bb1495cca..e9a3da588e954b1ae38b8becf465b132dbbcd22f 100644 (file)
@@ -969,10 +969,12 @@ static int init_hdlc_queues(struct port *port)
 {
        int i;
 
-       if (!ports_open)
-               if (!(dma_pool = dma_pool_create(DRV_NAME, NULL,
-                                                POOL_ALLOC_SIZE, 32, 0)))
+       if (!ports_open) {
+               dma_pool = dma_pool_create(DRV_NAME, &port->netdev->dev,
+                                          POOL_ALLOC_SIZE, 32, 0);
+               if (!dma_pool)
                        return -ENOMEM;
+       }
 
        if (!(port->desc_tab = dma_pool_alloc(dma_pool, GFP_KERNEL,
                                              &port->desc_tab_phys)))
index 89bf94d4d8a1e1799715eacf684bdd6892e419c9..6f7cf49eff4d0d1dd3bd6e6b954ec5c507969a44 100644 (file)
@@ -534,107 +534,107 @@ static const u32 ar9300_2p2_baseband_core[][2] = {
 
 static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = {
        /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
-       {0x0000a2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352},
-       {0x0000a2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584},
-       {0x0000a2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800},
+       {0x0000a2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352},
+       {0x0000a2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584},
+       {0x0000a2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},
        {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
        {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
        {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
        {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
        {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
        {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200},
-       {0x0000a510, 0x15000028, 0x15000028, 0x0f000202, 0x0f000202},
-       {0x0000a514, 0x1b00002b, 0x1b00002b, 0x12000400, 0x12000400},
-       {0x0000a518, 0x1f020028, 0x1f020028, 0x16000402, 0x16000402},
-       {0x0000a51c, 0x2502002b, 0x2502002b, 0x19000404, 0x19000404},
-       {0x0000a520, 0x2a04002a, 0x2a04002a, 0x1c000603, 0x1c000603},
-       {0x0000a524, 0x2e06002a, 0x2e06002a, 0x21000a02, 0x21000a02},
-       {0x0000a528, 0x3302202d, 0x3302202d, 0x25000a04, 0x25000a04},
-       {0x0000a52c, 0x3804202c, 0x3804202c, 0x28000a20, 0x28000a20},
-       {0x0000a530, 0x3c06202c, 0x3c06202c, 0x2c000e20, 0x2c000e20},
-       {0x0000a534, 0x4108202d, 0x4108202d, 0x30000e22, 0x30000e22},
-       {0x0000a538, 0x4506402d, 0x4506402d, 0x34000e24, 0x34000e24},
-       {0x0000a53c, 0x4906222d, 0x4906222d, 0x38001640, 0x38001640},
-       {0x0000a540, 0x4d062231, 0x4d062231, 0x3c001660, 0x3c001660},
-       {0x0000a544, 0x50082231, 0x50082231, 0x3f001861, 0x3f001861},
-       {0x0000a548, 0x5608422e, 0x5608422e, 0x43001a81, 0x43001a81},
-       {0x0000a54c, 0x5a08442e, 0x5a08442e, 0x47001a83, 0x47001a83},
-       {0x0000a550, 0x5e0a4431, 0x5e0a4431, 0x4a001c84, 0x4a001c84},
-       {0x0000a554, 0x640a4432, 0x640a4432, 0x4e001ce3, 0x4e001ce3},
-       {0x0000a558, 0x680a4434, 0x680a4434, 0x52001ce5, 0x52001ce5},
-       {0x0000a55c, 0x6c0a6434, 0x6c0a6434, 0x56001ce9, 0x56001ce9},
-       {0x0000a560, 0x6f0a6633, 0x6f0a6633, 0x5a001ceb, 0x5a001ceb},
-       {0x0000a564, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
-       {0x0000a568, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
-       {0x0000a56c, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
-       {0x0000a570, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
-       {0x0000a574, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
-       {0x0000a578, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
-       {0x0000a57c, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
+       {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202},
+       {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400},
+       {0x0000a518, 0x21002220, 0x21002220, 0x16000402, 0x16000402},
+       {0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404},
+       {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603},
+       {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02},
+       {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04},
+       {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20},
+       {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20},
+       {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22},
+       {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24},
+       {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640},
+       {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660},
+       {0x0000a544, 0x52022470, 0x52022470, 0x3f001861, 0x3f001861},
+       {0x0000a548, 0x55022490, 0x55022490, 0x43001a81, 0x43001a81},
+       {0x0000a54c, 0x59022492, 0x59022492, 0x47001a83, 0x47001a83},
+       {0x0000a550, 0x5d022692, 0x5d022692, 0x4a001c84, 0x4a001c84},
+       {0x0000a554, 0x61022892, 0x61022892, 0x4e001ce3, 0x4e001ce3},
+       {0x0000a558, 0x65024890, 0x65024890, 0x52001ce5, 0x52001ce5},
+       {0x0000a55c, 0x69024892, 0x69024892, 0x56001ce9, 0x56001ce9},
+       {0x0000a560, 0x6e024c92, 0x6e024c92, 0x5a001ceb, 0x5a001ceb},
+       {0x0000a564, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+       {0x0000a568, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+       {0x0000a56c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+       {0x0000a570, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+       {0x0000a574, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+       {0x0000a578, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+       {0x0000a57c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
        {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000},
        {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002},
        {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004},
        {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200},
-       {0x0000a590, 0x15800028, 0x15800028, 0x0f800202, 0x0f800202},
-       {0x0000a594, 0x1b80002b, 0x1b80002b, 0x12800400, 0x12800400},
-       {0x0000a598, 0x1f820028, 0x1f820028, 0x16800402, 0x16800402},
-       {0x0000a59c, 0x2582002b, 0x2582002b, 0x19800404, 0x19800404},
-       {0x0000a5a0, 0x2a84002a, 0x2a84002a, 0x1c800603, 0x1c800603},
-       {0x0000a5a4, 0x2e86002a, 0x2e86002a, 0x21800a02, 0x21800a02},
-       {0x0000a5a8, 0x3382202d, 0x3382202d, 0x25800a04, 0x25800a04},
-       {0x0000a5ac, 0x3884202c, 0x3884202c, 0x28800a20, 0x28800a20},
-       {0x0000a5b0, 0x3c86202c, 0x3c86202c, 0x2c800e20, 0x2c800e20},
-       {0x0000a5b4, 0x4188202d, 0x4188202d, 0x30800e22, 0x30800e22},
-       {0x0000a5b8, 0x4586402d, 0x4586402d, 0x34800e24, 0x34800e24},
-       {0x0000a5bc, 0x4986222d, 0x4986222d, 0x38801640, 0x38801640},
-       {0x0000a5c0, 0x4d862231, 0x4d862231, 0x3c801660, 0x3c801660},
-       {0x0000a5c4, 0x50882231, 0x50882231, 0x3f801861, 0x3f801861},
-       {0x0000a5c8, 0x5688422e, 0x5688422e, 0x43801a81, 0x43801a81},
-       {0x0000a5cc, 0x5a88442e, 0x5a88442e, 0x47801a83, 0x47801a83},
-       {0x0000a5d0, 0x5e8a4431, 0x5e8a4431, 0x4a801c84, 0x4a801c84},
-       {0x0000a5d4, 0x648a4432, 0x648a4432, 0x4e801ce3, 0x4e801ce3},
-       {0x0000a5d8, 0x688a4434, 0x688a4434, 0x52801ce5, 0x52801ce5},
-       {0x0000a5dc, 0x6c8a6434, 0x6c8a6434, 0x56801ce9, 0x56801ce9},
-       {0x0000a5e0, 0x6f8a6633, 0x6f8a6633, 0x5a801ceb, 0x5a801ceb},
-       {0x0000a5e4, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
-       {0x0000a5e8, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
-       {0x0000a5ec, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
-       {0x0000a5f0, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
-       {0x0000a5f4, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
-       {0x0000a5f8, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
-       {0x0000a5fc, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
+       {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202},
+       {0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400},
+       {0x0000a598, 0x21802220, 0x21802220, 0x16800402, 0x16800402},
+       {0x0000a59c, 0x27802223, 0x27802223, 0x19800404, 0x19800404},
+       {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603},
+       {0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02},
+       {0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04},
+       {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20},
+       {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20},
+       {0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22},
+       {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24},
+       {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640},
+       {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660},
+       {0x0000a5c4, 0x52822470, 0x52822470, 0x3f801861, 0x3f801861},
+       {0x0000a5c8, 0x55822490, 0x55822490, 0x43801a81, 0x43801a81},
+       {0x0000a5cc, 0x59822492, 0x59822492, 0x47801a83, 0x47801a83},
+       {0x0000a5d0, 0x5d822692, 0x5d822692, 0x4a801c84, 0x4a801c84},
+       {0x0000a5d4, 0x61822892, 0x61822892, 0x4e801ce3, 0x4e801ce3},
+       {0x0000a5d8, 0x65824890, 0x65824890, 0x52801ce5, 0x52801ce5},
+       {0x0000a5dc, 0x69824892, 0x69824892, 0x56801ce9, 0x56801ce9},
+       {0x0000a5e0, 0x6e824c92, 0x6e824c92, 0x5a801ceb, 0x5a801ceb},
+       {0x0000a5e4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+       {0x0000a5e8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+       {0x0000a5ec, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+       {0x0000a5f0, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+       {0x0000a5f4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+       {0x0000a5f8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+       {0x0000a5fc, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
        {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
        {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a608, 0x01804601, 0x01804601, 0x00000000, 0x00000000},
-       {0x0000a60c, 0x01804601, 0x01804601, 0x00000000, 0x00000000},
-       {0x0000a610, 0x01804601, 0x01804601, 0x00000000, 0x00000000},
-       {0x0000a614, 0x01804601, 0x01804601, 0x01404000, 0x01404000},
-       {0x0000a618, 0x01804601, 0x01804601, 0x01404501, 0x01404501},
-       {0x0000a61c, 0x01804601, 0x01804601, 0x02008501, 0x02008501},
-       {0x0000a620, 0x03408d02, 0x03408d02, 0x0280ca03, 0x0280ca03},
-       {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04},
-       {0x0000a628, 0x03410d04, 0x03410d04, 0x04014c04, 0x04014c04},
-       {0x0000a62c, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
-       {0x0000a630, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
-       {0x0000a634, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
-       {0x0000a638, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
-       {0x0000a63c, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
-       {0x0000b2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352},
-       {0x0000b2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584},
-       {0x0000b2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800},
+       {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a614, 0x02004000, 0x02004000, 0x01404000, 0x01404000},
+       {0x0000a618, 0x02004801, 0x02004801, 0x01404501, 0x01404501},
+       {0x0000a61c, 0x02808a02, 0x02808a02, 0x02008501, 0x02008501},
+       {0x0000a620, 0x0380ce03, 0x0380ce03, 0x0280ca03, 0x0280ca03},
+       {0x0000a624, 0x04411104, 0x04411104, 0x03010c04, 0x03010c04},
+       {0x0000a628, 0x04411104, 0x04411104, 0x04014c04, 0x04014c04},
+       {0x0000a62c, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+       {0x0000a630, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+       {0x0000a634, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+       {0x0000a638, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+       {0x0000a63c, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+       {0x0000b2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352},
+       {0x0000b2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584},
+       {0x0000b2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},
        {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
-       {0x0000c2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352},
-       {0x0000c2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584},
-       {0x0000c2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800},
+       {0x0000c2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352},
+       {0x0000c2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584},
+       {0x0000c2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},
        {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
        {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
-       {0x00016048, 0x61200001, 0x61200001, 0x66480001, 0x66480001},
+       {0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
        {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
        {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
-       {0x00016448, 0x61200001, 0x61200001, 0x66480001, 0x66480001},
+       {0x00016448, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
        {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
        {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
-       {0x00016848, 0x61200001, 0x61200001, 0x66480001, 0x66480001},
+       {0x00016848, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
        {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
 };
 
index 924c4616c3d990dc7f03e46ed299bdc94396d765..f5dda84176c3d4ae8277c069df06fa3bbc11922d 100644 (file)
@@ -38,6 +38,7 @@ static struct usb_device_id ath9k_hif_usb_ids[] = {
        { USB_DEVICE(0x04CA, 0x4605) }, /* Liteon */
        { USB_DEVICE(0x040D, 0x3801) }, /* VIA */
        { USB_DEVICE(0x0cf3, 0xb003) }, /* Ubiquiti WifiStation Ext */
+       { USB_DEVICE(0x0cf3, 0xb002) }, /* Ubiquiti WifiStation */
        { USB_DEVICE(0x057c, 0x8403) }, /* AVM FRITZ!WLAN 11N v2 USB */
 
        { USB_DEVICE(0x0cf3, 0x7015),
index 8e1559aba495a0bd7447ac2c79703d49caf70abd..1829b445d0b01852ea11111692174c766b3c7e55 100644 (file)
@@ -1456,7 +1456,7 @@ static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type)
        switch (type) {
        case ATH9K_RESET_POWER_ON:
                ret = ath9k_hw_set_reset_power_on(ah);
-               if (!ret)
+               if (ret)
                        ah->reset_power_on = true;
                break;
        case ATH9K_RESET_WARM:
index 378bd70256b2c7b8ad6358b2488919198dc42950..741918a2027b56ebe0f561d5175e8a129b8a3059 100644 (file)
@@ -312,6 +312,7 @@ static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc)
        }
 
        bf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list);
+       bf->bf_next = NULL;
        list_del(&bf->list);
 
        spin_unlock_bh(&sc->tx.txbuflock);
@@ -393,7 +394,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
        u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0, seq_first;
        u32 ba[WME_BA_BMP_SIZE >> 5];
        int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0;
-       bool rc_update = true;
+       bool rc_update = true, isba;
        struct ieee80211_tx_rate rates[4];
        struct ath_frame_info *fi;
        int nframes;
@@ -437,13 +438,17 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
        tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK;
        tid = ATH_AN_2_TID(an, tidno);
        seq_first = tid->seq_start;
+       isba = ts->ts_flags & ATH9K_TX_BA;
 
        /*
         * The hardware occasionally sends a tx status for the wrong TID.
         * In this case, the BA status cannot be considered valid and all
         * subframes need to be retransmitted
+        *
+        * Only BlockAcks have a TID and therefore normal Acks cannot be
+        * checked
         */
-       if (tidno != ts->tid)
+       if (isba && tidno != ts->tid)
                txok = false;
 
        isaggr = bf_isaggr(bf);
@@ -1774,6 +1779,7 @@ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
        list_add_tail(&bf->list, &bf_head);
        bf->bf_state.bf_type = 0;
 
+       bf->bf_next = NULL;
        bf->bf_lastbf = bf;
        ath_tx_fill_desc(sc, bf, txq, fi->framelen);
        ath_tx_txqaddbuf(sc, txq, &bf_head, false);
index 73730e94e0ac79fdbdf257f1cf969179e1c62a46..c5a99c8c81687de1b26a79bb2ad777c4d71c2029 100644 (file)
@@ -5404,6 +5404,8 @@ static void b43_bcma_remove(struct bcma_device *core)
        cancel_work_sync(&wldev->restart_work);
 
        B43_WARN_ON(!wl);
+       if (!wldev->fw.ucode.data)
+               return;                 /* NULL if firmware never loaded */
        if (wl->current_dev == wldev && wl->hw_registred) {
                b43_leds_stop(wldev);
                ieee80211_unregister_hw(wl->hw);
@@ -5478,6 +5480,8 @@ static void b43_ssb_remove(struct ssb_device *sdev)
        cancel_work_sync(&wldev->restart_work);
 
        B43_WARN_ON(!wl);
+       if (!wldev->fw.ucode.data)
+               return;                 /* NULL if firmware never loaded */
        if (wl->current_dev == wldev && wl->hw_registred) {
                b43_leds_stop(wldev);
                ieee80211_unregister_hw(wl->hw);
index 192251adf986c97579539025055f91c592f189bd..282eedec675ee17fae313655797716ad1617eec0 100644 (file)
@@ -382,7 +382,7 @@ static void cancel_transfers(struct b43legacy_pioqueue *queue)
 {
        struct b43legacy_pio_txpacket *packet, *tmp_packet;
 
-       tasklet_disable(&queue->txtask);
+       tasklet_kill(&queue->txtask);
 
        list_for_each_entry_safe(packet, tmp_packet, &queue->txrunning, list)
                free_txpacket(packet, 0);
index a2b4b1e71017230b6d7ab262f52b45c4fa353bd7..7a6dfdc67b6cc5ed11ce8e5281cf45c5fa81818a 100644 (file)
@@ -1339,7 +1339,7 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo,
        }
 
        ret = brcmf_bus_start(dev);
-       if (ret == -ENOLINK) {
+       if (ret) {
                brcmf_dbg(ERROR, "dongle is not responding\n");
                brcmf_detach(dev);
                goto fail;
index c1abaa6db59ec97fc9da4a0419ba81ea922cfb42..481345c23ded3250bf68c002089809e815abb3fe 100644 (file)
@@ -3569,7 +3569,7 @@ brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy,
 
        if (!request || !request->n_ssids || !request->n_match_sets) {
                WL_ERR("Invalid sched scan req!! n_ssids:%d\n",
-                      request->n_ssids);
+                      request ? request->n_ssids : 0);
                return -EINVAL;
        }
 
@@ -3972,7 +3972,7 @@ brcmf_set_management_ie(struct brcmf_cfg80211_info *cfg,
        u8  *iovar_ie_buf;
        u8  *curr_ie_buf;
        u8  *mgmt_ie_buf = NULL;
-       u32 mgmt_ie_buf_len = 0;
+       int mgmt_ie_buf_len;
        u32 *mgmt_ie_len = 0;
        u32 del_add_ie_buf_len = 0;
        u32 total_ie_buf_len = 0;
@@ -3982,7 +3982,7 @@ brcmf_set_management_ie(struct brcmf_cfg80211_info *cfg,
        struct parsed_vndr_ie_info *vndrie_info;
        s32 i;
        u8 *ptr;
-       u32 remained_buf_len;
+       int remained_buf_len;
 
        WL_TRACE("bssidx %d, pktflag : 0x%02X\n", bssidx, pktflag);
        iovar_ie_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
@@ -4401,7 +4401,7 @@ static s32 brcmf_mode_to_nl80211_iftype(s32 mode)
 
 static void brcmf_wiphy_pno_params(struct wiphy *wiphy)
 {
-#ifndef CONFIG_BRCMFISCAN
+#ifndef CONFIG_BRCMISCAN
        /* scheduled scan settings */
        wiphy->max_sched_scan_ssids = BRCMF_PNO_MAX_PFN_COUNT;
        wiphy->max_match_sets = BRCMF_PNO_MAX_PFN_COUNT;
@@ -4606,12 +4606,13 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg,
        struct brcmf_cfg80211_profile *profile = cfg->profile;
        struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg);
        struct wiphy *wiphy = cfg_to_wiphy(cfg);
-       struct brcmf_channel_info_le channel_le;
-       struct ieee80211_channel *notify_channel;
+       struct ieee80211_channel *notify_channel = NULL;
        struct ieee80211_supported_band *band;
+       struct brcmf_bss_info_le *bi;
        u32 freq;
        s32 err = 0;
        u32 target_channel;
+       u8 *buf;
 
        WL_TRACE("Enter\n");
 
@@ -4619,11 +4620,22 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg,
        memcpy(profile->bssid, e->addr, ETH_ALEN);
        brcmf_update_bss_info(cfg);
 
-       brcmf_exec_dcmd(ndev, BRCMF_C_GET_CHANNEL, &channel_le,
-                       sizeof(channel_le));
+       buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
+       if (buf == NULL) {
+               err = -ENOMEM;
+               goto done;
+       }
 
-       target_channel = le32_to_cpu(channel_le.target_channel);
-       WL_CONN("Roamed to channel %d\n", target_channel);
+       /* data sent to dongle has to be little endian */
+       *(__le32 *)buf = cpu_to_le32(WL_BSS_INFO_MAX);
+       err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_BSS_INFO, buf, WL_BSS_INFO_MAX);
+
+       if (err)
+               goto done;
+
+       bi = (struct brcmf_bss_info_le *)(buf + 4);
+       target_channel = bi->ctl_ch ? bi->ctl_ch :
+                                     CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec));
 
        if (target_channel <= CH_MAX_2G_CHANNEL)
                band = wiphy->bands[IEEE80211_BAND_2GHZ];
@@ -4633,6 +4645,8 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg,
        freq = ieee80211_channel_to_frequency(target_channel, band->band);
        notify_channel = ieee80211_get_channel(wiphy, freq);
 
+done:
+       kfree(buf);
        cfg80211_roamed(ndev, notify_channel, (u8 *)profile->bssid,
                        conn_info->req_ie, conn_info->req_ie_len,
                        conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL);
@@ -5186,41 +5200,6 @@ brcmf_cfg80211_event(struct net_device *ndev,
                schedule_work(&cfg->event_work);
 }
 
-static s32 brcmf_dongle_mode(struct net_device *ndev, s32 iftype)
-{
-       s32 infra = 0;
-       s32 err = 0;
-
-       switch (iftype) {
-       case NL80211_IFTYPE_MONITOR:
-       case NL80211_IFTYPE_WDS:
-               WL_ERR("type (%d) : currently we do not support this mode\n",
-                      iftype);
-               err = -EINVAL;
-               return err;
-       case NL80211_IFTYPE_ADHOC:
-               infra = 0;
-               break;
-       case NL80211_IFTYPE_STATION:
-               infra = 1;
-               break;
-       case NL80211_IFTYPE_AP:
-               infra = 1;
-               break;
-       default:
-               err = -EINVAL;
-               WL_ERR("invalid type (%d)\n", iftype);
-               return err;
-       }
-       err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_INFRA, &infra);
-       if (err) {
-               WL_ERR("WLC_SET_INFRA error (%d)\n", err);
-               return err;
-       }
-
-       return 0;
-}
-
 static s32 brcmf_dongle_eventmsg(struct net_device *ndev)
 {
        /* Room for "event_msgs" + '\0' + bitvec */
@@ -5439,7 +5418,8 @@ static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg)
                                WL_BEACON_TIMEOUT);
        if (err)
                goto default_conf_out;
-       err = brcmf_dongle_mode(ndev, wdev->iftype);
+       err = brcmf_cfg80211_change_iface(wdev->wiphy, ndev, wdev->iftype,
+                                         NULL, NULL);
        if (err && err != -EINPROGRESS)
                goto default_conf_out;
        err = brcmf_dongle_probecap(cfg);
index 935120fc8c9397daef4cb822b3d00176e0ca0cb8..768bf612533e04317feb756efa17563400ce6ab2 100644 (file)
@@ -10472,7 +10472,7 @@ static void ipw_handle_promiscuous_tx(struct ipw_priv *priv,
                } else
                        len = src->len;
 
-               dst = alloc_skb(len + sizeof(*rt_hdr), GFP_ATOMIC);
+               dst = alloc_skb(len + sizeof(*rt_hdr) + sizeof(u16)*2, GFP_ATOMIC);
                if (!dst)
                        continue;
 
index 349c205d5f62e218d3a76226b983818e92732a95..da5862064195159a7052fd92b327ce017b2d1381 100644 (file)
@@ -518,7 +518,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
         * See iwlagn_mac_channel_switch.
         */
        struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-       struct iwl6000_channel_switch_cmd cmd;
+       struct iwl6000_channel_switch_cmd *cmd;
        u32 switch_time_in_usec, ucode_switch_time;
        u16 ch;
        u32 tsf_low;
@@ -527,18 +527,25 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
        struct ieee80211_vif *vif = ctx->vif;
        struct iwl_host_cmd hcmd = {
                .id = REPLY_CHANNEL_SWITCH,
-               .len = { sizeof(cmd), },
+               .len = { sizeof(*cmd), },
                .flags = CMD_SYNC,
-               .data = { &cmd, },
+               .dataflags[0] = IWL_HCMD_DFL_NOCOPY,
        };
+       int err;
 
-       cmd.band = priv->band == IEEE80211_BAND_2GHZ;
+       cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+       if (!cmd)
+               return -ENOMEM;
+
+       hcmd.data[0] = cmd;
+
+       cmd->band = priv->band == IEEE80211_BAND_2GHZ;
        ch = ch_switch->channel->hw_value;
        IWL_DEBUG_11H(priv, "channel switch from %u to %u\n",
                      ctx->active.channel, ch);
-       cmd.channel = cpu_to_le16(ch);
-       cmd.rxon_flags = ctx->staging.flags;
-       cmd.rxon_filter_flags = ctx->staging.filter_flags;
+       cmd->channel = cpu_to_le16(ch);
+       cmd->rxon_flags = ctx->staging.flags;
+       cmd->rxon_filter_flags = ctx->staging.filter_flags;
        switch_count = ch_switch->count;
        tsf_low = ch_switch->timestamp & 0x0ffffffff;
        /*
@@ -554,23 +561,25 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
                        switch_count = 0;
        }
        if (switch_count <= 1)
-               cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
+               cmd->switch_time = cpu_to_le32(priv->ucode_beacon_time);
        else {
                switch_time_in_usec =
                        vif->bss_conf.beacon_int * switch_count * TIME_UNIT;
                ucode_switch_time = iwl_usecs_to_beacons(priv,
                                                         switch_time_in_usec,
                                                         beacon_interval);
-               cmd.switch_time = iwl_add_beacon_time(priv,
-                                                     priv->ucode_beacon_time,
-                                                     ucode_switch_time,
-                                                     beacon_interval);
+               cmd->switch_time = iwl_add_beacon_time(priv,
+                                                      priv->ucode_beacon_time,
+                                                      ucode_switch_time,
+                                                      beacon_interval);
        }
        IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n",
-                     cmd.switch_time);
-       cmd.expect_beacon = ch_switch->channel->flags & IEEE80211_CHAN_RADAR;
+                     cmd->switch_time);
+       cmd->expect_beacon = ch_switch->channel->flags & IEEE80211_CHAN_RADAR;
 
-       return iwl_dvm_send_cmd(priv, &hcmd);
+       err = iwl_dvm_send_cmd(priv, &hcmd);
+       kfree(cmd);
+       return err;
 }
 
 struct iwl_lib_ops iwl6000_lib = {
index ff8162d4c4543d3d2976c964ed2f790a8f7cb6a1..2d9eee93c743aa0f7bfe6d98330ccacead4fe201 100644 (file)
@@ -521,7 +521,7 @@ static void iwlagn_mac_tx(struct ieee80211_hw *hw,
                     ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate);
 
        if (iwlagn_tx_skb(priv, control->sta, skb))
-               dev_kfree_skb_any(skb);
+               ieee80211_free_txskb(hw, skb);
 }
 
 static void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw,
@@ -1354,6 +1354,20 @@ static int iwlagn_mac_add_interface(struct ieee80211_hw *hw,
        vif_priv->ctx = ctx;
        ctx->vif = vif;
 
+       /*
+        * In SNIFFER device type, the firmware reports the FCS to
+        * the host, rather than snipping it off. Unfortunately,
+        * mac80211 doesn't (yet) provide a per-packet flag for
+        * this, so that we have to set the hardware flag based
+        * on the interfaces added. As the monitor interface can
+        * only be present by itself, and will be removed before
+        * other interfaces are added, this is safe.
+        */
+       if (vif->type == NL80211_IFTYPE_MONITOR)
+               priv->hw->flags |= IEEE80211_HW_RX_INCLUDES_FCS;
+       else
+               priv->hw->flags &= ~IEEE80211_HW_RX_INCLUDES_FCS;
+
        err = iwl_setup_interface(priv, ctx);
        if (!err || reset)
                goto out;
index 7ff3f14306784169f886e5c7ca570d8b217a7309..408132cf83c18285d4eff4ba7a67add5fde64bda 100644 (file)
@@ -2114,7 +2114,7 @@ static void iwl_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb)
 
        info = IEEE80211_SKB_CB(skb);
        iwl_trans_free_tx_cmd(priv->trans, info->driver_data[1]);
-       dev_kfree_skb_any(skb);
+       ieee80211_free_txskb(priv->hw, skb);
 }
 
 static void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state)
index 17c8e5d82681022383d657da550924d48d0d9289..bb69f8f90b3b47c441fde750c14d0a9b9a3a6da0 100644 (file)
@@ -321,6 +321,14 @@ static void iwl_rx_allocate(struct iwl_trans *trans, gfp_t priority)
                        dma_map_page(trans->dev, page, 0,
                                     PAGE_SIZE << trans_pcie->rx_page_order,
                                     DMA_FROM_DEVICE);
+               if (dma_mapping_error(trans->dev, rxb->page_dma)) {
+                       rxb->page = NULL;
+                       spin_lock_irqsave(&rxq->lock, flags);
+                       list_add(&rxb->list, &rxq->rx_used);
+                       spin_unlock_irqrestore(&rxq->lock, flags);
+                       __free_pages(page, trans_pcie->rx_page_order);
+                       return;
+               }
                /* dma address must be no more than 36 bits */
                BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36));
                /* and also 256 byte aligned! */
@@ -488,8 +496,19 @@ static void iwl_rx_handle_rxbuf(struct iwl_trans *trans,
                        dma_map_page(trans->dev, rxb->page, 0,
                                     PAGE_SIZE << trans_pcie->rx_page_order,
                                     DMA_FROM_DEVICE);
-               list_add_tail(&rxb->list, &rxq->rx_free);
-               rxq->free_count++;
+               if (dma_mapping_error(trans->dev, rxb->page_dma)) {
+                       /*
+                        * free the page(s) as well to not break
+                        * the invariant that the items on the used
+                        * list have no page(s)
+                        */
+                       __free_pages(rxb->page, trans_pcie->rx_page_order);
+                       rxb->page = NULL;
+                       list_add_tail(&rxb->list, &rxq->rx_used);
+               } else {
+                       list_add_tail(&rxb->list, &rxq->rx_free);
+                       rxq->free_count++;
+               }
        } else
                list_add_tail(&rxb->list, &rxq->rx_used);
        spin_unlock_irqrestore(&rxq->lock, flags);
index 105e3af3c621b0b9e335fbe42d1ea1e444bfa579..79a4ddc002d3dac1ce4aa9182bd2a2a0cf76630b 100644 (file)
@@ -480,20 +480,12 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo,
 void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id)
 {
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-       u16 rd_ptr, wr_ptr;
-       int n_bd = trans_pcie->txq[txq_id].q.n_bd;
 
        if (!test_and_clear_bit(txq_id, trans_pcie->queue_used)) {
                WARN_ONCE(1, "queue %d not used", txq_id);
                return;
        }
 
-       rd_ptr = iwl_read_prph(trans, SCD_QUEUE_RDPTR(txq_id)) & (n_bd - 1);
-       wr_ptr = iwl_read_prph(trans, SCD_QUEUE_WRPTR(txq_id));
-
-       WARN_ONCE(rd_ptr != wr_ptr, "queue %d isn't empty: [%d,%d]",
-                 txq_id, rd_ptr, wr_ptr);
-
        iwl_txq_set_inactive(trans, txq_id);
        IWL_DEBUG_TX_QUEUES(trans, "Deactivate queue %d\n", txq_id);
 }
index 0679458a1bac44469ddf0d00935e7b165f66f9ed..780d3e168297fcf80c62e4345ac6d29c22007b73 100644 (file)
@@ -1825,8 +1825,6 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy,
                return -EBUSY;
        }
 
-       priv->scan_request = request;
-
        priv->user_scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg),
                                      GFP_KERNEL);
        if (!priv->user_scan_cfg) {
@@ -1834,6 +1832,8 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy,
                return -ENOMEM;
        }
 
+       priv->scan_request = request;
+
        priv->user_scan_cfg->num_ssids = request->n_ssids;
        priv->user_scan_cfg->ssid_list = request->ssids;
 
@@ -1870,6 +1870,9 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy,
        ret = mwifiex_scan_networks(priv, priv->user_scan_cfg);
        if (ret) {
                dev_err(priv->adapter->dev, "scan failed: %d\n", ret);
+               priv->scan_request = NULL;
+               kfree(priv->user_scan_cfg);
+               priv->user_scan_cfg = NULL;
                return ret;
        }
 
index 8d465107f52b2c5073acad20d8d0acbe0485be5e..ae9010ed58debd4a8dc5001e03cbe866b2c9a8a2 100644 (file)
@@ -890,9 +890,6 @@ mwifiex_cmd_timeout_func(unsigned long function_context)
                return;
        }
        cmd_node = adapter->curr_cmd;
-       if (cmd_node->wait_q_enabled)
-               adapter->cmd_wait_q.status = -ETIMEDOUT;
-
        if (cmd_node) {
                adapter->dbg.timeout_cmd_id =
                        adapter->dbg.last_cmd_id[adapter->dbg.last_cmd_index];
@@ -938,6 +935,14 @@ mwifiex_cmd_timeout_func(unsigned long function_context)
 
                dev_err(adapter->dev, "ps_mode=%d ps_state=%d\n",
                        adapter->ps_mode, adapter->ps_state);
+
+               if (cmd_node->wait_q_enabled) {
+                       adapter->cmd_wait_q.status = -ETIMEDOUT;
+                       wake_up_interruptible(&adapter->cmd_wait_q.wait);
+                       mwifiex_cancel_pending_ioctl(adapter);
+                       /* reset cmd_sent flag to unblock new commands */
+                       adapter->cmd_sent = false;
+               }
        }
        if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING)
                mwifiex_init_fw_complete(adapter);
index 00b658d3b6ecfae72792b055a717aab9c41a0401..9171aaedbccdb28bf3371efcd5c7c89cecb3ab93 100644 (file)
@@ -1843,21 +1843,18 @@ static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv,
                                      struct cfg80211_ssid *req_ssid)
 {
        struct mwifiex_adapter *adapter = priv->adapter;
-       int ret = 0;
+       int ret;
        struct mwifiex_user_scan_cfg *scan_cfg;
 
-       if (!req_ssid)
-               return -1;
-
        if (adapter->scan_processing) {
-               dev_dbg(adapter->dev, "cmd: Scan already in process...\n");
-               return ret;
+               dev_err(adapter->dev, "cmd: Scan already in process...\n");
+               return -EBUSY;
        }
 
        if (priv->scan_block) {
-               dev_dbg(adapter->dev,
+               dev_err(adapter->dev,
                        "cmd: Scan is blocked during association...\n");
-               return ret;
+               return -EBUSY;
        }
 
        scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg), GFP_KERNEL);
index fc8a9bfa1248305fababa37b59ca90110a57afaa..82cf0fa2d9f683a391bb2215f94447d53d09ef40 100644 (file)
@@ -161,7 +161,6 @@ static int mwifiex_sdio_suspend(struct device *dev)
        struct sdio_mmc_card *card;
        struct mwifiex_adapter *adapter;
        mmc_pm_flag_t pm_flag = 0;
-       int hs_actived = 0;
        int i;
        int ret = 0;
 
@@ -188,12 +187,14 @@ static int mwifiex_sdio_suspend(struct device *dev)
        adapter = card->adapter;
 
        /* Enable the Host Sleep */
-       hs_actived = mwifiex_enable_hs(adapter);
-       if (hs_actived) {
-               pr_debug("cmd: suspend with MMC_PM_KEEP_POWER\n");
-               ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
+       if (!mwifiex_enable_hs(adapter)) {
+               dev_err(adapter->dev, "cmd: failed to suspend\n");
+               return -EFAULT;
        }
 
+       dev_dbg(adapter->dev, "cmd: suspend with MMC_PM_KEEP_POWER\n");
+       ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
+
        /* Indicate device suspended */
        adapter->is_suspended = true;
 
index a12e84f892be1d9b13d1762a0369a7841af32645..6b2e1e431dd2fc579d1a2710b2b68ecfd47f043e 100644 (file)
@@ -1988,6 +1988,7 @@ static struct usb_driver rt2500usb_driver = {
        .disconnect     = rt2x00usb_disconnect,
        .suspend        = rt2x00usb_suspend,
        .resume         = rt2x00usb_resume,
+       .reset_resume   = rt2x00usb_resume,
        .disable_hub_initiated_lpm = 1,
 };
 
index 01dc8891070c3729c37b08cce18506ab583c4761..59474ae0aec0d14e7dfc2639c19cf65b82b3b7ea 100644 (file)
@@ -2449,7 +2449,7 @@ static int rt2800_get_gain_calibration_delta(struct rt2x00_dev *rt2x00dev)
        /*
         * Check if temperature compensation is supported.
         */
-       if (tssi_bounds[4] == 0xff)
+       if (tssi_bounds[4] == 0xff || step == 0xff)
                return 0;
 
        /*
index c9e9370eb789c04ec91fd97a2a85d8d21977a144..3b8fb5a603f25244241a3219bff169962cf54733 100644 (file)
@@ -1282,6 +1282,7 @@ static struct usb_driver rt2800usb_driver = {
        .disconnect     = rt2x00usb_disconnect,
        .suspend        = rt2x00usb_suspend,
        .resume         = rt2x00usb_resume,
+       .reset_resume   = rt2x00usb_resume,
        .disable_hub_initiated_lpm = 1,
 };
 
index e5eb43b3eee74f94db85349436f0ba1e15925059..24eec66e9fd2049ae14aa709e7e2ecab0294751c 100644 (file)
@@ -2535,6 +2535,7 @@ static struct usb_driver rt73usb_driver = {
        .disconnect     = rt2x00usb_disconnect,
        .suspend        = rt2x00usb_suspend,
        .resume         = rt2x00usb_resume,
+       .reset_resume   = rt2x00usb_resume,
        .disable_hub_initiated_lpm = 1,
 };
 
index 9970c2b1b19979dc3577472c7c21e27703a38a76..b7e6607e6b6d038bd604657bb4fdcc883b171d7a 100644 (file)
@@ -297,6 +297,7 @@ static struct usb_device_id rtl8192c_usb_ids[] = {
        /*=== Customer ID ===*/
        /****** 8188CU ********/
        {RTL_USB_DEVICE(0x050d, 0x1102, rtl92cu_hal_cfg)}, /*Belkin - Edimax*/
+       {RTL_USB_DEVICE(0x050d, 0x11f2, rtl92cu_hal_cfg)}, /*Belkin - ISY*/
        {RTL_USB_DEVICE(0x06f8, 0xe033, rtl92cu_hal_cfg)}, /*Hercules - Edimax*/
        {RTL_USB_DEVICE(0x07b8, 0x8188, rtl92cu_hal_cfg)}, /*Abocom - Abocom*/
        {RTL_USB_DEVICE(0x07b8, 0x8189, rtl92cu_hal_cfg)}, /*Funai - Abocom*/
index 030beb45d8b0b2b30669e945eb1ccc2e2cbd5fd7..e3ea4b346889430dfb07d604f052adb6522f18bb 100644 (file)
@@ -673,7 +673,7 @@ static int rtl_usb_start(struct ieee80211_hw *hw)
                set_hal_start(rtlhal);
 
                /* Start bulk IN */
-               _rtl_usb_receive(hw);
+               err = _rtl_usb_receive(hw);
        }
 
        return err;
index caa011008cd0c9fe11b38507e7f550552bd93170..fc24eb9b3948666b0819156539138958dd6888f1 100644 (file)
@@ -452,29 +452,85 @@ static void xennet_make_frags(struct sk_buff *skb, struct net_device *dev,
        /* Grant backend access to each skb fragment page. */
        for (i = 0; i < frags; i++) {
                skb_frag_t *frag = skb_shinfo(skb)->frags + i;
+               struct page *page = skb_frag_page(frag);
 
-               tx->flags |= XEN_NETTXF_more_data;
+               len = skb_frag_size(frag);
+               offset = frag->page_offset;
 
-               id = get_id_from_freelist(&np->tx_skb_freelist, np->tx_skbs);
-               np->tx_skbs[id].skb = skb_get(skb);
-               tx = RING_GET_REQUEST(&np->tx, prod++);
-               tx->id = id;
-               ref = gnttab_claim_grant_reference(&np->gref_tx_head);
-               BUG_ON((signed short)ref < 0);
+               /* Data must not cross a page boundary. */
+               BUG_ON(len + offset > PAGE_SIZE<<compound_order(page));
 
-               mfn = pfn_to_mfn(page_to_pfn(skb_frag_page(frag)));
-               gnttab_grant_foreign_access_ref(ref, np->xbdev->otherend_id,
-                                               mfn, GNTMAP_readonly);
+               /* Skip unused frames from start of page */
+               page += offset >> PAGE_SHIFT;
+               offset &= ~PAGE_MASK;
 
-               tx->gref = np->grant_tx_ref[id] = ref;
-               tx->offset = frag->page_offset;
-               tx->size = skb_frag_size(frag);
-               tx->flags = 0;
+               while (len > 0) {
+                       unsigned long bytes;
+
+                       BUG_ON(offset >= PAGE_SIZE);
+
+                       bytes = PAGE_SIZE - offset;
+                       if (bytes > len)
+                               bytes = len;
+
+                       tx->flags |= XEN_NETTXF_more_data;
+
+                       id = get_id_from_freelist(&np->tx_skb_freelist,
+                                                 np->tx_skbs);
+                       np->tx_skbs[id].skb = skb_get(skb);
+                       tx = RING_GET_REQUEST(&np->tx, prod++);
+                       tx->id = id;
+                       ref = gnttab_claim_grant_reference(&np->gref_tx_head);
+                       BUG_ON((signed short)ref < 0);
+
+                       mfn = pfn_to_mfn(page_to_pfn(page));
+                       gnttab_grant_foreign_access_ref(ref,
+                                                       np->xbdev->otherend_id,
+                                                       mfn, GNTMAP_readonly);
+
+                       tx->gref = np->grant_tx_ref[id] = ref;
+                       tx->offset = offset;
+                       tx->size = bytes;
+                       tx->flags = 0;
+
+                       offset += bytes;
+                       len -= bytes;
+
+                       /* Next frame */
+                       if (offset == PAGE_SIZE && len) {
+                               BUG_ON(!PageCompound(page));
+                               page++;
+                               offset = 0;
+                       }
+               }
        }
 
        np->tx.req_prod_pvt = prod;
 }
 
+/*
+ * Count how many ring slots are required to send the frags of this
+ * skb. Each frag might be a compound page.
+ */
+static int xennet_count_skb_frag_slots(struct sk_buff *skb)
+{
+       int i, frags = skb_shinfo(skb)->nr_frags;
+       int pages = 0;
+
+       for (i = 0; i < frags; i++) {
+               skb_frag_t *frag = skb_shinfo(skb)->frags + i;
+               unsigned long size = skb_frag_size(frag);
+               unsigned long offset = frag->page_offset;
+
+               /* Skip unused frames from start of page */
+               offset &= ~PAGE_MASK;
+
+               pages += PFN_UP(offset + size);
+       }
+
+       return pages;
+}
+
 static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        unsigned short id;
@@ -487,23 +543,23 @@ static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)
        grant_ref_t ref;
        unsigned long mfn;
        int notify;
-       int frags = skb_shinfo(skb)->nr_frags;
+       int slots;
        unsigned int offset = offset_in_page(data);
        unsigned int len = skb_headlen(skb);
        unsigned long flags;
 
-       frags += DIV_ROUND_UP(offset + len, PAGE_SIZE);
-       if (unlikely(frags > MAX_SKB_FRAGS + 1)) {
-               printk(KERN_ALERT "xennet: skb rides the rocket: %d frags\n",
-                      frags);
-               dump_stack();
+       slots = DIV_ROUND_UP(offset + len, PAGE_SIZE) +
+               xennet_count_skb_frag_slots(skb);
+       if (unlikely(slots > MAX_SKB_FRAGS + 1)) {
+               net_alert_ratelimited(
+                       "xennet: skb rides the rocket: %d slots\n", slots);
                goto drop;
        }
 
        spin_lock_irqsave(&np->tx_lock, flags);
 
        if (unlikely(!netif_carrier_ok(dev) ||
-                    (frags > 1 && !xennet_can_sg(dev)) ||
+                    (slots > 1 && !xennet_can_sg(dev)) ||
                     netif_needs_gso(skb, netif_skb_features(skb)))) {
                spin_unlock_irqrestore(&np->tx_lock, flags);
                goto drop;
index 97c440a8cd615798a1e61250628e0030ede37694..30ae18a03a9ccc650a195547086866a66646cd98 100644 (file)
@@ -698,13 +698,14 @@ static void pn533_wq_cmd(struct work_struct *work)
 
        cmd = list_first_entry(&dev->cmd_queue, struct pn533_cmd, queue);
 
+       list_del(&cmd->queue);
+
        mutex_unlock(&dev->cmd_lock);
 
        __pn533_send_cmd_frame_async(dev, cmd->out_frame, cmd->in_frame,
                                     cmd->in_frame_len, cmd->cmd_complete,
                                     cmd->arg, cmd->flags);
 
-       list_del(&cmd->queue);
        kfree(cmd);
 }
 
@@ -1678,11 +1679,14 @@ static void pn533_deactivate_target(struct nfc_dev *nfc_dev,
 static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg,
                                                u8 *params, int params_len)
 {
-       struct pn533_cmd_jump_dep *cmd;
        struct pn533_cmd_jump_dep_response *resp;
        struct nfc_target nfc_target;
        u8 target_gt_len;
        int rc;
+       struct pn533_cmd_jump_dep *cmd = (struct pn533_cmd_jump_dep *)arg;
+       u8 active = cmd->active;
+
+       kfree(arg);
 
        if (params_len == -ENOENT) {
                nfc_dev_dbg(&dev->interface->dev, "");
@@ -1704,7 +1708,6 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg,
        }
 
        resp = (struct pn533_cmd_jump_dep_response *) params;
-       cmd = (struct pn533_cmd_jump_dep *) arg;
        rc = resp->status & PN533_CMD_RET_MASK;
        if (rc != PN533_CMD_RET_SUCCESS) {
                nfc_dev_err(&dev->interface->dev,
@@ -1734,7 +1737,7 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg,
        if (rc == 0)
                rc = nfc_dep_link_is_up(dev->nfc_dev,
                                                dev->nfc_dev->targets[0].idx,
-                                               !cmd->active, NFC_RF_INITIATOR);
+                                               !active, NFC_RF_INITIATOR);
 
        return 0;
 }
@@ -1819,12 +1822,8 @@ static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target,
        rc = pn533_send_cmd_frame_async(dev, dev->out_frame, dev->in_frame,
                                dev->in_maxlen, pn533_in_dep_link_up_complete,
                                cmd, GFP_KERNEL);
-       if (rc)
-               goto out;
-
-
-out:
-       kfree(cmd);
+       if (rc < 0)
+               kfree(cmd);
 
        return rc;
 }
@@ -2078,8 +2077,12 @@ error:
 static int pn533_tm_send_complete(struct pn533 *dev, void *arg,
                                  u8 *params, int params_len)
 {
+       struct sk_buff *skb_out = arg;
+
        nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
 
+       dev_kfree_skb(skb_out);
+
        if (params_len < 0) {
                nfc_dev_err(&dev->interface->dev,
                            "Error %d when sending data",
@@ -2117,7 +2120,7 @@ static int pn533_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb)
 
        rc = pn533_send_cmd_frame_async(dev, out_frame, dev->in_frame,
                                        dev->in_maxlen, pn533_tm_send_complete,
-                                       NULL, GFP_KERNEL);
+                                       skb, GFP_KERNEL);
        if (rc) {
                nfc_dev_err(&dev->interface->dev,
                            "Error %d when trying to send data", rc);
index 6241fd05bd4108cde7ff14366eb169a00cb80138..a543746fb354d99913cac3323b99b6f5aa71dbc9 100644 (file)
@@ -320,10 +320,7 @@ void pci_walk_bus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *),
                } else
                        next = dev->bus_list.next;
 
-               /* Run device routines with the device locked */
-               device_lock(&dev->dev);
                retval = cb(dev, userdata);
-               device_unlock(&dev->dev);
                if (retval)
                        break;
        }
index 94c6e2aa03d658defb5d30b0f2fbb1f8383cf9d0..6c94fc9489e709b2ad5f42817d8f29ef21c9a9b6 100644 (file)
@@ -398,6 +398,8 @@ static void pci_device_shutdown(struct device *dev)
        struct pci_dev *pci_dev = to_pci_dev(dev);
        struct pci_driver *drv = pci_dev->driver;
 
+       pm_runtime_resume(dev);
+
        if (drv && drv->shutdown)
                drv->shutdown(pci_dev);
        pci_msi_shutdown(pci_dev);
@@ -408,16 +410,6 @@ static void pci_device_shutdown(struct device *dev)
         * continue to do DMA
         */
        pci_disable_device(pci_dev);
-
-       /*
-        * Devices may be enabled to wake up by runtime PM, but they need not
-        * be supposed to wake up the system from its "power off" state (e.g.
-        * ACPI S5).  Therefore disable wakeup for all devices that aren't
-        * supposed to wake up the system at this point.  The state argument
-        * will be ignored by pci_enable_wake().
-        */
-       if (!device_may_wakeup(dev))
-               pci_enable_wake(pci_dev, PCI_UNKNOWN, false);
 }
 
 #ifdef CONFIG_PM
index 02d107b152818e948cc3e561d276bf24126ac997..f39378d9da1500056a90f4816f742e9e5ee9626f 100644 (file)
@@ -458,40 +458,6 @@ boot_vga_show(struct device *dev, struct device_attribute *attr, char *buf)
 }
 struct device_attribute vga_attr = __ATTR_RO(boot_vga);
 
-static void
-pci_config_pm_runtime_get(struct pci_dev *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct device *parent = dev->parent;
-
-       if (parent)
-               pm_runtime_get_sync(parent);
-       pm_runtime_get_noresume(dev);
-       /*
-        * pdev->current_state is set to PCI_D3cold during suspending,
-        * so wait until suspending completes
-        */
-       pm_runtime_barrier(dev);
-       /*
-        * Only need to resume devices in D3cold, because config
-        * registers are still accessible for devices suspended but
-        * not in D3cold.
-        */
-       if (pdev->current_state == PCI_D3cold)
-               pm_runtime_resume(dev);
-}
-
-static void
-pci_config_pm_runtime_put(struct pci_dev *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct device *parent = dev->parent;
-
-       pm_runtime_put(dev);
-       if (parent)
-               pm_runtime_put_sync(parent);
-}
-
 static ssize_t
 pci_read_config(struct file *filp, struct kobject *kobj,
                struct bin_attribute *bin_attr,
index 54858838f09867f142886edcac6b4dab9c049531..aabf64798bda7d2ebdca2697f23c7e29bfbae620 100644 (file)
@@ -1858,6 +1858,38 @@ bool pci_dev_run_wake(struct pci_dev *dev)
 }
 EXPORT_SYMBOL_GPL(pci_dev_run_wake);
 
+void pci_config_pm_runtime_get(struct pci_dev *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct device *parent = dev->parent;
+
+       if (parent)
+               pm_runtime_get_sync(parent);
+       pm_runtime_get_noresume(dev);
+       /*
+        * pdev->current_state is set to PCI_D3cold during suspending,
+        * so wait until suspending completes
+        */
+       pm_runtime_barrier(dev);
+       /*
+        * Only need to resume devices in D3cold, because config
+        * registers are still accessible for devices suspended but
+        * not in D3cold.
+        */
+       if (pdev->current_state == PCI_D3cold)
+               pm_runtime_resume(dev);
+}
+
+void pci_config_pm_runtime_put(struct pci_dev *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct device *parent = dev->parent;
+
+       pm_runtime_put(dev);
+       if (parent)
+               pm_runtime_put_sync(parent);
+}
+
 /**
  * pci_pm_init - Initialize PM functions of given PCI device
  * @dev: PCI device to handle.
index bacbcba69cf386dd2971b8b94e6ddd383888b471..fd92aab9904b92a694dadf685291220121661905 100644 (file)
@@ -72,6 +72,8 @@ extern void pci_disable_enabled_device(struct pci_dev *dev);
 extern int pci_finish_runtime_suspend(struct pci_dev *dev);
 extern int __pci_pme_wakeup(struct pci_dev *dev, void *ign);
 extern void pci_wakeup_bus(struct pci_bus *bus);
+extern void pci_config_pm_runtime_get(struct pci_dev *dev);
+extern void pci_config_pm_runtime_put(struct pci_dev *dev);
 extern void pci_pm_init(struct pci_dev *dev);
 extern void platform_pci_wakeup_init(struct pci_dev *dev);
 extern void pci_allocate_cap_save_buffers(struct pci_dev *dev);
index 06bad96af415b052b4eb9a90d83f7c04c70b108a..af4e31cd3a3b6b1f895a36afaf4bb874b3e1fb66 100644 (file)
@@ -213,6 +213,7 @@ static int report_error_detected(struct pci_dev *dev, void *data)
        struct aer_broadcast_data *result_data;
        result_data = (struct aer_broadcast_data *) data;
 
+       device_lock(&dev->dev);
        dev->error_state = result_data->state;
 
        if (!dev->driver ||
@@ -231,12 +232,14 @@ static int report_error_detected(struct pci_dev *dev, void *data)
                                   dev->driver ?
                                   "no AER-aware driver" : "no driver");
                }
-               return 0;
+               goto out;
        }
 
        err_handler = dev->driver->err_handler;
        vote = err_handler->error_detected(dev, result_data->state);
        result_data->result = merge_result(result_data->result, vote);
+out:
+       device_unlock(&dev->dev);
        return 0;
 }
 
@@ -247,14 +250,17 @@ static int report_mmio_enabled(struct pci_dev *dev, void *data)
        struct aer_broadcast_data *result_data;
        result_data = (struct aer_broadcast_data *) data;
 
+       device_lock(&dev->dev);
        if (!dev->driver ||
                !dev->driver->err_handler ||
                !dev->driver->err_handler->mmio_enabled)
-               return 0;
+               goto out;
 
        err_handler = dev->driver->err_handler;
        vote = err_handler->mmio_enabled(dev);
        result_data->result = merge_result(result_data->result, vote);
+out:
+       device_unlock(&dev->dev);
        return 0;
 }
 
@@ -265,14 +271,17 @@ static int report_slot_reset(struct pci_dev *dev, void *data)
        struct aer_broadcast_data *result_data;
        result_data = (struct aer_broadcast_data *) data;
 
+       device_lock(&dev->dev);
        if (!dev->driver ||
                !dev->driver->err_handler ||
                !dev->driver->err_handler->slot_reset)
-               return 0;
+               goto out;
 
        err_handler = dev->driver->err_handler;
        vote = err_handler->slot_reset(dev);
        result_data->result = merge_result(result_data->result, vote);
+out:
+       device_unlock(&dev->dev);
        return 0;
 }
 
@@ -280,15 +289,18 @@ static int report_resume(struct pci_dev *dev, void *data)
 {
        const struct pci_error_handlers *err_handler;
 
+       device_lock(&dev->dev);
        dev->error_state = pci_channel_io_normal;
 
        if (!dev->driver ||
                !dev->driver->err_handler ||
                !dev->driver->err_handler->resume)
-               return 0;
+               goto out;
 
        err_handler = dev->driver->err_handler;
        err_handler->resume(dev);
+out:
+       device_unlock(&dev->dev);
        return 0;
 }
 
index d03a7a39b2d85e14baef54a8255e787094528229..ed129b4146246144de63db421ff04d28d5d7de27 100644 (file)
@@ -272,7 +272,8 @@ static int get_port_device_capability(struct pci_dev *dev)
        }
 
        /* Hot-Plug Capable */
-       if (cap_mask & PCIE_PORT_SERVICE_HP) {
+       if ((cap_mask & PCIE_PORT_SERVICE_HP) &&
+           dev->pcie_flags_reg & PCI_EXP_FLAGS_SLOT) {
                pcie_capability_read_dword(dev, PCI_EXP_SLTCAP, &reg32);
                if (reg32 & PCI_EXP_SLTCAP_HPC) {
                        services |= PCIE_PORT_SERVICE_HP;
index eb907a8faf2a9b6e325033005127b0b40904930a..9b8505ccc56d5ef87a09105f5847d19a441ec704 100644 (file)
@@ -76,6 +76,8 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp
        if (!access_ok(VERIFY_WRITE, buf, cnt))
                return -EINVAL;
 
+       pci_config_pm_runtime_get(dev);
+
        if ((pos & 1) && cnt) {
                unsigned char val;
                pci_user_read_config_byte(dev, pos, &val);
@@ -121,6 +123,8 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp
                cnt--;
        }
 
+       pci_config_pm_runtime_put(dev);
+
        *ppos = pos;
        return nbytes;
 }
@@ -146,6 +150,8 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof
        if (!access_ok(VERIFY_READ, buf, cnt))
                return -EINVAL;
 
+       pci_config_pm_runtime_get(dev);
+
        if ((pos & 1) && cnt) {
                unsigned char val;
                __get_user(val, buf);
@@ -191,6 +197,8 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof
                cnt--;
        }
 
+       pci_config_pm_runtime_put(dev);
+
        *ppos = pos;
        i_size_write(ino, dp->size);
        return nbytes;
index 7bf914df6e91a6129d23f5d12828b8228a8c2775..aeecf0f72cad50c633953e4ffd9617709239095b 100644 (file)
@@ -178,12 +178,14 @@ config PINCTRL_COH901
          ports of 8 GPIO pins each.
 
 config PINCTRL_SAMSUNG
-       bool "Samsung pinctrl driver"
+       bool
+       depends on OF && GPIOLIB
        select PINMUX
        select PINCONF
 
 config PINCTRL_EXYNOS4
        bool "Pinctrl driver data for Exynos4 SoC"
+       depends on OF && GPIOLIB
        select PINCTRL_SAMSUNG
 
 config PINCTRL_MVEBU
index 0f1ec9e8ff14b02448877cb4f4872f45baeeccd3..2e39c04fc16bb4be31dba8800477aafed2e64441 100644 (file)
@@ -1061,8 +1061,10 @@ static int pinctrl_groups_show(struct seq_file *s, void *what)
                        seq_printf(s, "group: %s\n", gname);
                        for (i = 0; i < num_pins; i++) {
                                pname = pin_get_name(pctldev, pins[i]);
-                               if (WARN_ON(!pname))
+                               if (WARN_ON(!pname)) {
+                                       mutex_unlock(&pinctrl_mutex);
                                        return -EINVAL;
+                               }
                                seq_printf(s, "pin %d (%s)\n", pins[i], pname);
                        }
                        seq_puts(s, "\n");
index 43f474cdc11082717c881b757c6bcaf104bcbb97..baee2cc46a17a7c5c328f98c7eaa25f8f10d8fba 100644 (file)
@@ -537,8 +537,6 @@ static int pinconf_groups_show(struct seq_file *s, void *what)
        seq_puts(s, "Pin config settings per pin group\n");
        seq_puts(s, "Format: group (name): configs\n");
 
-       mutex_lock(&pinctrl_mutex);
-
        while (selector < ngroups) {
                const char *gname = pctlops->get_group_name(pctldev, selector);
 
@@ -549,8 +547,6 @@ static int pinconf_groups_show(struct seq_file *s, void *what)
                selector++;
        }
 
-       mutex_unlock(&pinctrl_mutex);
-
        return 0;
 }
 
index 01aea1c3b5fa3188a50cfe4e41ea13e48c50f56d..cf82d9ce4deeccc8c19c6104103fee84854c945a 100644 (file)
@@ -1056,7 +1056,7 @@ static int nmk_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
        struct nmk_gpio_chip *nmk_chip =
                container_of(chip, struct nmk_gpio_chip, chip);
 
-       return irq_find_mapping(nmk_chip->domain, offset);
+       return irq_create_mapping(nmk_chip->domain, offset);
 }
 
 #ifdef CONFIG_DEBUG_FS
@@ -1281,7 +1281,7 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev)
        struct clk *clk;
        int secondary_irq;
        void __iomem *base;
-       int irq_start = -1;
+       int irq_start = 0;
        int irq;
        int ret;
 
@@ -1387,7 +1387,7 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev)
 
        if (!np)
                irq_start = NOMADIK_GPIO_TO_IRQ(pdata->first_gpio);
-       nmk_chip->domain = irq_domain_add_simple(NULL,
+       nmk_chip->domain = irq_domain_add_simple(np,
                                NMK_GPIO_PER_CHIP, irq_start,
                                &nmk_gpio_irq_simple_ops, nmk_chip);
        if (!nmk_chip->domain) {
index 729b686c3ad2338e2d4878ed0e1623674ba87f3f..7da0b371fd652a04ac7d55ecf89c55c915d19f8b 100644 (file)
@@ -464,7 +464,7 @@ static int tegra_pinconf_reg(struct tegra_pmx *pmx,
                *bank = g->drv_bank;
                *reg = g->drv_reg;
                *bit = g->lpmd_bit;
-               *width = 1;
+               *width = 2;
                break;
        case TEGRA_PINCONF_PARAM_DRIVE_DOWN_STRENGTH:
                *bank = g->drv_bank;
index 0386fdf0da16441ecc874b1710e55a929d44325a..7894f14c70590058726a6c07da4286e1640058db 100644 (file)
@@ -3345,10 +3345,10 @@ static const struct tegra_function tegra30_functions[] = {
        FUNCTION(vi_alt3),
 };
 
-#define MUXCTL_REG_A   0x3000
-#define PINGROUP_REG_A 0x868
+#define DRV_PINGROUP_REG_A     0x868   /* bank 0 */
+#define PINGROUP_REG_A         0x3000  /* bank 1 */
 
-#define PINGROUP_REG_Y(r) ((r) - MUXCTL_REG_A)
+#define PINGROUP_REG_Y(r) ((r) - PINGROUP_REG_A)
 #define PINGROUP_REG_N(r) -1
 
 #define PINGROUP(pg_name, f0, f1, f2, f3, f_safe, r, od, ior)  \
@@ -3364,25 +3364,25 @@ static const struct tegra_function tegra30_functions[] = {
                },                                              \
                .func_safe = TEGRA_MUX_ ## f_safe,              \
                .mux_reg = PINGROUP_REG_Y(r),                   \
-               .mux_bank = 0,                                  \
+               .mux_bank = 1,                                  \
                .mux_bit = 0,                                   \
                .pupd_reg = PINGROUP_REG_Y(r),                  \
-               .pupd_bank = 0,                                 \
+               .pupd_bank = 1,                                 \
                .pupd_bit = 2,                                  \
                .tri_reg = PINGROUP_REG_Y(r),                   \
-               .tri_bank = 0,                                  \
+               .tri_bank = 1,                                  \
                .tri_bit = 4,                                   \
                .einput_reg = PINGROUP_REG_Y(r),                \
-               .einput_bank = 0,                               \
+               .einput_bank = 1,                               \
                .einput_bit = 5,                                \
                .odrain_reg = PINGROUP_REG_##od(r),             \
-               .odrain_bank = 0,                               \
+               .odrain_bank = 1,                               \
                .odrain_bit = 6,                                \
                .lock_reg = PINGROUP_REG_Y(r),                  \
-               .lock_bank = 0,                                 \
+               .lock_bank = 1,                                 \
                .lock_bit = 7,                                  \
                .ioreset_reg = PINGROUP_REG_##ior(r),           \
-               .ioreset_bank = 0,                              \
+               .ioreset_bank = 1,                              \
                .ioreset_bit = 8,                               \
                .drv_reg = -1,                                  \
        }
@@ -3401,8 +3401,8 @@ static const struct tegra_function tegra30_functions[] = {
                .odrain_reg = -1,                               \
                .lock_reg = -1,                                 \
                .ioreset_reg = -1,                              \
-               .drv_reg = ((r) - PINGROUP_REG_A),              \
-               .drv_bank = 1,                                  \
+               .drv_reg = ((r) - DRV_PINGROUP_REG_A),          \
+               .drv_bank = 0,                                  \
                .hsm_bit = hsm_b,                               \
                .schmitt_bit = schmitt_b,                       \
                .lpmd_bit = lpmd_b,                             \
index 5d4f44f462f0962b26b955d877f3a0ceb0285c7a..b1fd6ee33c6ceed614e3a5ccf1cb096049069710 100644 (file)
@@ -244,7 +244,7 @@ static int spear_pinctrl_endisable(struct pinctrl_dev *pctldev,
                        else
                                temp = ~muxreg->val;
 
-                       val |= temp;
+                       val |= muxreg->mask & temp;
                        pmx_writel(pmx, val, muxreg->reg);
                }
        }
index d6cca8c81b92cf9cd9cb63f9d972965e46670249..0436fc7895d6226a8c0cd4943fad2201b03ad4b5 100644 (file)
@@ -25,8 +25,8 @@ static const struct pinctrl_pin_desc spear1310_pins[] = {
 };
 
 /* registers */
-#define PERIP_CFG                                      0x32C
-       #define MCIF_SEL_SHIFT                          3
+#define PERIP_CFG                                      0x3B0
+       #define MCIF_SEL_SHIFT                          5
        #define MCIF_SEL_SD                             (0x1 << MCIF_SEL_SHIFT)
        #define MCIF_SEL_CF                             (0x2 << MCIF_SEL_SHIFT)
        #define MCIF_SEL_XD                             (0x3 << MCIF_SEL_SHIFT)
@@ -164,6 +164,10 @@ static const struct pinctrl_pin_desc spear1310_pins[] = {
        #define PMX_SSP0_CS0_MASK                       (1 << 29)
        #define PMX_SSP0_CS1_2_MASK                     (1 << 30)
 
+#define PAD_DIRECTION_SEL_0                            0x65C
+#define PAD_DIRECTION_SEL_1                            0x660
+#define PAD_DIRECTION_SEL_2                            0x664
+
 /* combined macros */
 #define PMX_GMII_MASK          (PMX_GMIICLK_MASK |                     \
                                PMX_GMIICOL_CRS_XFERER_MIITXCLK_MASK |  \
@@ -237,6 +241,10 @@ static struct spear_muxreg i2c0_muxreg[] = {
                .reg = PAD_FUNCTION_EN_0,
                .mask = PMX_I2C0_MASK,
                .val = PMX_I2C0_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_I2C0_MASK,
+               .val = PMX_I2C0_MASK,
        },
 };
 
@@ -269,6 +277,10 @@ static struct spear_muxreg ssp0_muxreg[] = {
                .reg = PAD_FUNCTION_EN_0,
                .mask = PMX_SSP0_MASK,
                .val = PMX_SSP0_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_SSP0_MASK,
+               .val = PMX_SSP0_MASK,
        },
 };
 
@@ -294,6 +306,10 @@ static struct spear_muxreg ssp0_cs0_muxreg[] = {
                .reg = PAD_FUNCTION_EN_2,
                .mask = PMX_SSP0_CS0_MASK,
                .val = PMX_SSP0_CS0_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_2,
+               .mask = PMX_SSP0_CS0_MASK,
+               .val = PMX_SSP0_CS0_MASK,
        },
 };
 
@@ -319,6 +335,10 @@ static struct spear_muxreg ssp0_cs1_2_muxreg[] = {
                .reg = PAD_FUNCTION_EN_2,
                .mask = PMX_SSP0_CS1_2_MASK,
                .val = PMX_SSP0_CS1_2_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_2,
+               .mask = PMX_SSP0_CS1_2_MASK,
+               .val = PMX_SSP0_CS1_2_MASK,
        },
 };
 
@@ -352,6 +372,10 @@ static struct spear_muxreg i2s0_muxreg[] = {
                .reg = PAD_FUNCTION_EN_0,
                .mask = PMX_I2S0_MASK,
                .val = PMX_I2S0_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_I2S0_MASK,
+               .val = PMX_I2S0_MASK,
        },
 };
 
@@ -384,6 +408,10 @@ static struct spear_muxreg i2s1_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_I2S1_MASK,
                .val = PMX_I2S1_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_I2S1_MASK,
+               .val = PMX_I2S1_MASK,
        },
 };
 
@@ -418,6 +446,10 @@ static struct spear_muxreg clcd_muxreg[] = {
                .reg = PAD_FUNCTION_EN_0,
                .mask = PMX_CLCD1_MASK,
                .val = PMX_CLCD1_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_CLCD1_MASK,
+               .val = PMX_CLCD1_MASK,
        },
 };
 
@@ -443,6 +475,10 @@ static struct spear_muxreg clcd_high_res_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_CLCD2_MASK,
                .val = PMX_CLCD2_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_CLCD2_MASK,
+               .val = PMX_CLCD2_MASK,
        },
 };
 
@@ -461,7 +497,7 @@ static struct spear_pingroup clcd_high_res_pingroup = {
        .nmodemuxs = ARRAY_SIZE(clcd_high_res_modemux),
 };
 
-static const char *const clcd_grps[] = { "clcd_grp", "clcd_high_res" };
+static const char *const clcd_grps[] = { "clcd_grp", "clcd_high_res_grp" };
 static struct spear_function clcd_function = {
        .name = "clcd",
        .groups = clcd_grps,
@@ -479,6 +515,14 @@ static struct spear_muxreg arm_gpio_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_EGPIO_1_GRP_MASK,
                .val = PMX_EGPIO_1_GRP_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_EGPIO_0_GRP_MASK,
+               .val = PMX_EGPIO_0_GRP_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_EGPIO_1_GRP_MASK,
+               .val = PMX_EGPIO_1_GRP_MASK,
        },
 };
 
@@ -511,6 +555,10 @@ static struct spear_muxreg smi_2_chips_muxreg[] = {
                .reg = PAD_FUNCTION_EN_0,
                .mask = PMX_SMI_MASK,
                .val = PMX_SMI_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_SMI_MASK,
+               .val = PMX_SMI_MASK,
        },
 };
 
@@ -539,6 +587,14 @@ static struct spear_muxreg smi_4_chips_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_SMINCS2_MASK | PMX_SMINCS3_MASK,
                .val = PMX_SMINCS2_MASK | PMX_SMINCS3_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_SMI_MASK,
+               .val = PMX_SMI_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_SMINCS2_MASK | PMX_SMINCS3_MASK,
+               .val = PMX_SMINCS2_MASK | PMX_SMINCS3_MASK,
        },
 };
 
@@ -573,6 +629,10 @@ static struct spear_muxreg gmii_muxreg[] = {
                .reg = PAD_FUNCTION_EN_0,
                .mask = PMX_GMII_MASK,
                .val = PMX_GMII_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_GMII_MASK,
+               .val = PMX_GMII_MASK,
        },
 };
 
@@ -615,6 +675,18 @@ static struct spear_muxreg rgmii_muxreg[] = {
                .reg = PAD_FUNCTION_EN_2,
                .mask = PMX_RGMII_REG2_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_RGMII_REG0_MASK,
+               .val = PMX_RGMII_REG0_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_RGMII_REG1_MASK,
+               .val = PMX_RGMII_REG1_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_2,
+               .mask = PMX_RGMII_REG2_MASK,
+               .val = PMX_RGMII_REG2_MASK,
        },
 };
 
@@ -649,6 +721,10 @@ static struct spear_muxreg smii_0_1_2_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_SMII_0_1_2_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_SMII_0_1_2_MASK,
+               .val = PMX_SMII_0_1_2_MASK,
        },
 };
 
@@ -681,6 +757,10 @@ static struct spear_muxreg ras_mii_txclk_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_NFCE2_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_NFCE2_MASK,
+               .val = PMX_NFCE2_MASK,
        },
 };
 
@@ -721,6 +801,14 @@ static struct spear_muxreg nand_8bit_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_NAND8BIT_1_MASK,
                .val = PMX_NAND8BIT_1_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_NAND8BIT_0_MASK,
+               .val = PMX_NAND8BIT_0_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_NAND8BIT_1_MASK,
+               .val = PMX_NAND8BIT_1_MASK,
        },
 };
 
@@ -747,6 +835,10 @@ static struct spear_muxreg nand_16bit_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_NAND16BIT_1_MASK,
                .val = PMX_NAND16BIT_1_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_NAND16BIT_1_MASK,
+               .val = PMX_NAND16BIT_1_MASK,
        },
 };
 
@@ -772,6 +864,10 @@ static struct spear_muxreg nand_4_chips_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_NAND_4CHIPS_MASK,
                .val = PMX_NAND_4CHIPS_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_NAND_4CHIPS_MASK,
+               .val = PMX_NAND_4CHIPS_MASK,
        },
 };
 
@@ -833,6 +929,10 @@ static struct spear_muxreg keyboard_rowcol6_8_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_KBD_ROWCOL68_MASK,
                .val = PMX_KBD_ROWCOL68_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_KBD_ROWCOL68_MASK,
+               .val = PMX_KBD_ROWCOL68_MASK,
        },
 };
 
@@ -866,6 +966,10 @@ static struct spear_muxreg uart0_muxreg[] = {
                .reg = PAD_FUNCTION_EN_0,
                .mask = PMX_UART0_MASK,
                .val = PMX_UART0_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_UART0_MASK,
+               .val = PMX_UART0_MASK,
        },
 };
 
@@ -891,6 +995,10 @@ static struct spear_muxreg uart0_modem_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_UART0_MODEM_MASK,
                .val = PMX_UART0_MODEM_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_UART0_MODEM_MASK,
+               .val = PMX_UART0_MODEM_MASK,
        },
 };
 
@@ -923,6 +1031,10 @@ static struct spear_muxreg gpt0_tmr0_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_GPT0_TMR0_MASK,
                .val = PMX_GPT0_TMR0_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_GPT0_TMR0_MASK,
+               .val = PMX_GPT0_TMR0_MASK,
        },
 };
 
@@ -948,6 +1060,10 @@ static struct spear_muxreg gpt0_tmr1_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_GPT0_TMR1_MASK,
                .val = PMX_GPT0_TMR1_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_GPT0_TMR1_MASK,
+               .val = PMX_GPT0_TMR1_MASK,
        },
 };
 
@@ -980,6 +1096,10 @@ static struct spear_muxreg gpt1_tmr0_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_GPT1_TMR0_MASK,
                .val = PMX_GPT1_TMR0_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_GPT1_TMR0_MASK,
+               .val = PMX_GPT1_TMR0_MASK,
        },
 };
 
@@ -1005,6 +1125,10 @@ static struct spear_muxreg gpt1_tmr1_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_GPT1_TMR1_MASK,
                .val = PMX_GPT1_TMR1_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_GPT1_TMR1_MASK,
+               .val = PMX_GPT1_TMR1_MASK,
        },
 };
 
@@ -1049,6 +1173,20 @@ static const unsigned mcif_pins[] = { 86, 87, 88, 89, 90, 91, 92, 93, 213, 214,
                .reg = PAD_FUNCTION_EN_2,                       \
                .mask = PMX_MCIFALL_2_MASK,                     \
                .val = PMX_MCIFALL_2_MASK,                      \
+       }, {                                                    \
+               .reg = PAD_DIRECTION_SEL_0,                     \
+               .mask = PMX_MCI_DATA8_15_MASK,                  \
+               .val = PMX_MCI_DATA8_15_MASK,                   \
+       }, {                                                    \
+               .reg = PAD_DIRECTION_SEL_1,                     \
+               .mask = PMX_MCIFALL_1_MASK | PMX_NFWPRT1_MASK | \
+                       PMX_NFWPRT2_MASK,                       \
+               .val = PMX_MCIFALL_1_MASK | PMX_NFWPRT1_MASK |  \
+                       PMX_NFWPRT2_MASK,                       \
+       }, {                                                    \
+               .reg = PAD_DIRECTION_SEL_2,                     \
+               .mask = PMX_MCIFALL_2_MASK,                     \
+               .val = PMX_MCIFALL_2_MASK,                      \
        }
 
 /* sdhci device */
@@ -1154,6 +1292,10 @@ static struct spear_muxreg touch_xy_muxreg[] = {
                .reg = PAD_FUNCTION_EN_2,
                .mask = PMX_TOUCH_XY_MASK,
                .val = PMX_TOUCH_XY_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_2,
+               .mask = PMX_TOUCH_XY_MASK,
+               .val = PMX_TOUCH_XY_MASK,
        },
 };
 
@@ -1187,6 +1329,10 @@ static struct spear_muxreg uart1_dis_i2c_muxreg[] = {
                .reg = PAD_FUNCTION_EN_0,
                .mask = PMX_I2C0_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_I2C0_MASK,
+               .val = PMX_I2C0_MASK,
        },
 };
 
@@ -1213,6 +1359,12 @@ static struct spear_muxreg uart1_dis_sd_muxreg[] = {
                .mask = PMX_MCIDATA1_MASK |
                        PMX_MCIDATA2_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_MCIDATA1_MASK |
+                       PMX_MCIDATA2_MASK,
+               .val = PMX_MCIDATA1_MASK |
+                       PMX_MCIDATA2_MASK,
        },
 };
 
@@ -1246,6 +1398,10 @@ static struct spear_muxreg uart2_3_muxreg[] = {
                .reg = PAD_FUNCTION_EN_0,
                .mask = PMX_I2S0_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_I2S0_MASK,
+               .val = PMX_I2S0_MASK,
        },
 };
 
@@ -1278,6 +1434,10 @@ static struct spear_muxreg uart4_muxreg[] = {
                .reg = PAD_FUNCTION_EN_0,
                .mask = PMX_I2S0_MASK | PMX_CLCD1_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_I2S0_MASK | PMX_CLCD1_MASK,
+               .val = PMX_I2S0_MASK | PMX_CLCD1_MASK,
        },
 };
 
@@ -1310,6 +1470,10 @@ static struct spear_muxreg uart5_muxreg[] = {
                .reg = PAD_FUNCTION_EN_0,
                .mask = PMX_CLCD1_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_CLCD1_MASK,
+               .val = PMX_CLCD1_MASK,
        },
 };
 
@@ -1344,6 +1508,10 @@ static struct spear_muxreg rs485_0_1_tdm_0_1_muxreg[] = {
                .reg = PAD_FUNCTION_EN_0,
                .mask = PMX_CLCD1_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_CLCD1_MASK,
+               .val = PMX_CLCD1_MASK,
        },
 };
 
@@ -1376,6 +1544,10 @@ static struct spear_muxreg i2c_1_2_muxreg[] = {
                .reg = PAD_FUNCTION_EN_0,
                .mask = PMX_CLCD1_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_CLCD1_MASK,
+               .val = PMX_CLCD1_MASK,
        },
 };
 
@@ -1409,6 +1581,10 @@ static struct spear_muxreg i2c3_dis_smi_clcd_muxreg[] = {
                .reg = PAD_FUNCTION_EN_0,
                .mask = PMX_CLCD1_MASK | PMX_SMI_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_CLCD1_MASK | PMX_SMI_MASK,
+               .val = PMX_CLCD1_MASK | PMX_SMI_MASK,
        },
 };
 
@@ -1435,6 +1611,10 @@ static struct spear_muxreg i2c3_dis_sd_i2s0_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_I2S1_MASK | PMX_MCIDATA3_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_I2S1_MASK | PMX_MCIDATA3_MASK,
+               .val = PMX_I2S1_MASK | PMX_MCIDATA3_MASK,
        },
 };
 
@@ -1469,6 +1649,10 @@ static struct spear_muxreg i2c_4_5_dis_smi_muxreg[] = {
                .reg = PAD_FUNCTION_EN_0,
                .mask = PMX_SMI_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_SMI_MASK,
+               .val = PMX_SMI_MASK,
        },
 };
 
@@ -1499,6 +1683,14 @@ static struct spear_muxreg i2c4_dis_sd_muxreg[] = {
                .reg = PAD_FUNCTION_EN_2,
                .mask = PMX_MCIDATA5_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_MCIDATA4_MASK,
+               .val = PMX_MCIDATA4_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_2,
+               .mask = PMX_MCIDATA5_MASK,
+               .val = PMX_MCIDATA5_MASK,
        },
 };
 
@@ -1526,6 +1718,12 @@ static struct spear_muxreg i2c5_dis_sd_muxreg[] = {
                .mask = PMX_MCIDATA6_MASK |
                        PMX_MCIDATA7_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_2,
+               .mask = PMX_MCIDATA6_MASK |
+                       PMX_MCIDATA7_MASK,
+               .val = PMX_MCIDATA6_MASK |
+                       PMX_MCIDATA7_MASK,
        },
 };
 
@@ -1560,6 +1758,10 @@ static struct spear_muxreg i2c_6_7_dis_kbd_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_KBD_ROWCOL25_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_KBD_ROWCOL25_MASK,
+               .val = PMX_KBD_ROWCOL25_MASK,
        },
 };
 
@@ -1587,6 +1789,12 @@ static struct spear_muxreg i2c6_dis_sd_muxreg[] = {
                .mask = PMX_MCIIORDRE_MASK |
                        PMX_MCIIOWRWE_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_2,
+               .mask = PMX_MCIIORDRE_MASK |
+                       PMX_MCIIOWRWE_MASK,
+               .val = PMX_MCIIORDRE_MASK |
+                       PMX_MCIIOWRWE_MASK,
        },
 };
 
@@ -1613,6 +1821,12 @@ static struct spear_muxreg i2c7_dis_sd_muxreg[] = {
                .mask = PMX_MCIRESETCF_MASK |
                        PMX_MCICS0CE_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_2,
+               .mask = PMX_MCIRESETCF_MASK |
+                       PMX_MCICS0CE_MASK,
+               .val = PMX_MCIRESETCF_MASK |
+                       PMX_MCICS0CE_MASK,
        },
 };
 
@@ -1651,6 +1865,14 @@ static struct spear_muxreg can0_dis_nor_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_NFRSTPWDWN3_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_NFRSTPWDWN2_MASK,
+               .val = PMX_NFRSTPWDWN2_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_NFRSTPWDWN3_MASK,
+               .val = PMX_NFRSTPWDWN3_MASK,
        },
 };
 
@@ -1677,6 +1899,10 @@ static struct spear_muxreg can0_dis_sd_muxreg[] = {
                .reg = PAD_FUNCTION_EN_2,
                .mask = PMX_MCICFINTR_MASK | PMX_MCIIORDY_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_2,
+               .mask = PMX_MCICFINTR_MASK | PMX_MCIIORDY_MASK,
+               .val = PMX_MCICFINTR_MASK | PMX_MCIIORDY_MASK,
        },
 };
 
@@ -1711,6 +1937,10 @@ static struct spear_muxreg can1_dis_sd_muxreg[] = {
                .reg = PAD_FUNCTION_EN_2,
                .mask = PMX_MCICS1_MASK | PMX_MCIDMAACK_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_2,
+               .mask = PMX_MCICS1_MASK | PMX_MCIDMAACK_MASK,
+               .val = PMX_MCICS1_MASK | PMX_MCIDMAACK_MASK,
        },
 };
 
@@ -1737,6 +1967,10 @@ static struct spear_muxreg can1_dis_kbd_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_KBD_ROWCOL25_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_KBD_ROWCOL25_MASK,
+               .val = PMX_KBD_ROWCOL25_MASK,
        },
 };
 
@@ -1763,29 +1997,64 @@ static struct spear_function can1_function = {
        .ngroups = ARRAY_SIZE(can1_grps),
 };
 
-/* Pad multiplexing for pci device */
-static const unsigned pci_sata_pins[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 18,
+/* Pad multiplexing for (ras-ip) pci device */
+static const unsigned pci_pins[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 18,
        19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
        37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
        55, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99 };
-#define PCI_SATA_MUXREG                                \
-       {                                       \
-               .reg = PAD_FUNCTION_EN_0,       \
-               .mask = PMX_MCI_DATA8_15_MASK,  \
-               .val = 0,                       \
-       }, {                                    \
-               .reg = PAD_FUNCTION_EN_1,       \
-               .mask = PMX_PCI_REG1_MASK,      \
-               .val = 0,                       \
-       }, {                                    \
-               .reg = PAD_FUNCTION_EN_2,       \
-               .mask = PMX_PCI_REG2_MASK,      \
-               .val = 0,                       \
-       }
 
-/* pad multiplexing for pcie0 device */
+static struct spear_muxreg pci_muxreg[] = {
+       {
+               .reg = PAD_FUNCTION_EN_0,
+               .mask = PMX_MCI_DATA8_15_MASK,
+               .val = 0,
+       }, {
+               .reg = PAD_FUNCTION_EN_1,
+               .mask = PMX_PCI_REG1_MASK,
+               .val = 0,
+       }, {
+               .reg = PAD_FUNCTION_EN_2,
+               .mask = PMX_PCI_REG2_MASK,
+               .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_MCI_DATA8_15_MASK,
+               .val = PMX_MCI_DATA8_15_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_PCI_REG1_MASK,
+               .val = PMX_PCI_REG1_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_2,
+               .mask = PMX_PCI_REG2_MASK,
+               .val = PMX_PCI_REG2_MASK,
+       },
+};
+
+static struct spear_modemux pci_modemux[] = {
+       {
+               .muxregs = pci_muxreg,
+               .nmuxregs = ARRAY_SIZE(pci_muxreg),
+       },
+};
+
+static struct spear_pingroup pci_pingroup = {
+       .name = "pci_grp",
+       .pins = pci_pins,
+       .npins = ARRAY_SIZE(pci_pins),
+       .modemuxs = pci_modemux,
+       .nmodemuxs = ARRAY_SIZE(pci_modemux),
+};
+
+static const char *const pci_grps[] = { "pci_grp" };
+static struct spear_function pci_function = {
+       .name = "pci",
+       .groups = pci_grps,
+       .ngroups = ARRAY_SIZE(pci_grps),
+};
+
+/* pad multiplexing for (fix-part) pcie0 device */
 static struct spear_muxreg pcie0_muxreg[] = {
-       PCI_SATA_MUXREG,
        {
                .reg = PCIE_SATA_CFG,
                .mask = PCIE_CFG_VAL(0),
@@ -1802,15 +2071,12 @@ static struct spear_modemux pcie0_modemux[] = {
 
 static struct spear_pingroup pcie0_pingroup = {
        .name = "pcie0_grp",
-       .pins = pci_sata_pins,
-       .npins = ARRAY_SIZE(pci_sata_pins),
        .modemuxs = pcie0_modemux,
        .nmodemuxs = ARRAY_SIZE(pcie0_modemux),
 };
 
-/* pad multiplexing for pcie1 device */
+/* pad multiplexing for (fix-part) pcie1 device */
 static struct spear_muxreg pcie1_muxreg[] = {
-       PCI_SATA_MUXREG,
        {
                .reg = PCIE_SATA_CFG,
                .mask = PCIE_CFG_VAL(1),
@@ -1827,15 +2093,12 @@ static struct spear_modemux pcie1_modemux[] = {
 
 static struct spear_pingroup pcie1_pingroup = {
        .name = "pcie1_grp",
-       .pins = pci_sata_pins,
-       .npins = ARRAY_SIZE(pci_sata_pins),
        .modemuxs = pcie1_modemux,
        .nmodemuxs = ARRAY_SIZE(pcie1_modemux),
 };
 
-/* pad multiplexing for pcie2 device */
+/* pad multiplexing for (fix-part) pcie2 device */
 static struct spear_muxreg pcie2_muxreg[] = {
-       PCI_SATA_MUXREG,
        {
                .reg = PCIE_SATA_CFG,
                .mask = PCIE_CFG_VAL(2),
@@ -1852,22 +2115,20 @@ static struct spear_modemux pcie2_modemux[] = {
 
 static struct spear_pingroup pcie2_pingroup = {
        .name = "pcie2_grp",
-       .pins = pci_sata_pins,
-       .npins = ARRAY_SIZE(pci_sata_pins),
        .modemuxs = pcie2_modemux,
        .nmodemuxs = ARRAY_SIZE(pcie2_modemux),
 };
 
-static const char *const pci_grps[] = { "pcie0_grp", "pcie1_grp", "pcie2_grp" };
-static struct spear_function pci_function = {
-       .name = "pci",
-       .groups = pci_grps,
-       .ngroups = ARRAY_SIZE(pci_grps),
+static const char *const pcie_grps[] = { "pcie0_grp", "pcie1_grp", "pcie2_grp"
+};
+static struct spear_function pcie_function = {
+       .name = "pci_express",
+       .groups = pcie_grps,
+       .ngroups = ARRAY_SIZE(pcie_grps),
 };
 
 /* pad multiplexing for sata0 device */
 static struct spear_muxreg sata0_muxreg[] = {
-       PCI_SATA_MUXREG,
        {
                .reg = PCIE_SATA_CFG,
                .mask = SATA_CFG_VAL(0),
@@ -1884,15 +2145,12 @@ static struct spear_modemux sata0_modemux[] = {
 
 static struct spear_pingroup sata0_pingroup = {
        .name = "sata0_grp",
-       .pins = pci_sata_pins,
-       .npins = ARRAY_SIZE(pci_sata_pins),
        .modemuxs = sata0_modemux,
        .nmodemuxs = ARRAY_SIZE(sata0_modemux),
 };
 
 /* pad multiplexing for sata1 device */
 static struct spear_muxreg sata1_muxreg[] = {
-       PCI_SATA_MUXREG,
        {
                .reg = PCIE_SATA_CFG,
                .mask = SATA_CFG_VAL(1),
@@ -1909,15 +2167,12 @@ static struct spear_modemux sata1_modemux[] = {
 
 static struct spear_pingroup sata1_pingroup = {
        .name = "sata1_grp",
-       .pins = pci_sata_pins,
-       .npins = ARRAY_SIZE(pci_sata_pins),
        .modemuxs = sata1_modemux,
        .nmodemuxs = ARRAY_SIZE(sata1_modemux),
 };
 
 /* pad multiplexing for sata2 device */
 static struct spear_muxreg sata2_muxreg[] = {
-       PCI_SATA_MUXREG,
        {
                .reg = PCIE_SATA_CFG,
                .mask = SATA_CFG_VAL(2),
@@ -1934,8 +2189,6 @@ static struct spear_modemux sata2_modemux[] = {
 
 static struct spear_pingroup sata2_pingroup = {
        .name = "sata2_grp",
-       .pins = pci_sata_pins,
-       .npins = ARRAY_SIZE(pci_sata_pins),
        .modemuxs = sata2_modemux,
        .nmodemuxs = ARRAY_SIZE(sata2_modemux),
 };
@@ -1957,6 +2210,14 @@ static struct spear_muxreg ssp1_dis_kbd_muxreg[] = {
                        PMX_KBD_COL0_MASK | PMX_NFIO8_15_MASK | PMX_NFCE1_MASK |
                        PMX_NFCE2_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_KBD_ROWCOL25_MASK | PMX_KBD_COL1_MASK |
+                       PMX_KBD_COL0_MASK | PMX_NFIO8_15_MASK | PMX_NFCE1_MASK |
+                       PMX_NFCE2_MASK,
+               .val = PMX_KBD_ROWCOL25_MASK | PMX_KBD_COL1_MASK |
+                       PMX_KBD_COL0_MASK | PMX_NFIO8_15_MASK | PMX_NFCE1_MASK |
+                       PMX_NFCE2_MASK,
        },
 };
 
@@ -1983,6 +2244,12 @@ static struct spear_muxreg ssp1_dis_sd_muxreg[] = {
                .mask = PMX_MCIADDR0ALE_MASK | PMX_MCIADDR2_MASK |
                        PMX_MCICECF_MASK | PMX_MCICEXD_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_2,
+               .mask = PMX_MCIADDR0ALE_MASK | PMX_MCIADDR2_MASK |
+                       PMX_MCICECF_MASK | PMX_MCICEXD_MASK,
+               .val = PMX_MCIADDR0ALE_MASK | PMX_MCIADDR2_MASK |
+                       PMX_MCICECF_MASK | PMX_MCICEXD_MASK,
        },
 };
 
@@ -2017,6 +2284,12 @@ static struct spear_muxreg gpt64_muxreg[] = {
                .mask = PMX_MCICDCF1_MASK | PMX_MCICDCF2_MASK | PMX_MCICDXD_MASK
                        | PMX_MCILEDS_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_2,
+               .mask = PMX_MCICDCF1_MASK | PMX_MCICDCF2_MASK | PMX_MCICDXD_MASK
+                       | PMX_MCILEDS_MASK,
+               .val = PMX_MCICDCF1_MASK | PMX_MCICDCF2_MASK | PMX_MCICDXD_MASK
+                       | PMX_MCILEDS_MASK,
        },
 };
 
@@ -2093,6 +2366,7 @@ static struct spear_pingroup *spear1310_pingroups[] = {
        &can0_dis_sd_pingroup,
        &can1_dis_sd_pingroup,
        &can1_dis_kbd_pingroup,
+       &pci_pingroup,
        &pcie0_pingroup,
        &pcie1_pingroup,
        &pcie2_pingroup,
@@ -2138,6 +2412,7 @@ static struct spear_function *spear1310_functions[] = {
        &can0_function,
        &can1_function,
        &pci_function,
+       &pcie_function,
        &sata_function,
        &ssp1_function,
        &gpt64_function,
index a0eb057e55bd3f91e390364a9187ee1f4e0768ab..0606b8cf3f2c10923014917d190d3f5ef73cd0aa 100644 (file)
@@ -213,7 +213,7 @@ static const struct pinctrl_pin_desc spear1340_pins[] = {
  * Pad multiplexing for making all pads as gpio's. This is done to override the
  * values passed from bootloader and start from scratch.
  */
-static const unsigned pads_as_gpio_pins[] = { 251 };
+static const unsigned pads_as_gpio_pins[] = { 12, 88, 89, 251 };
 static struct spear_muxreg pads_as_gpio_muxreg[] = {
        {
                .reg = PAD_FUNCTION_EN_1,
@@ -1692,7 +1692,43 @@ static struct spear_pingroup clcd_pingroup = {
        .nmodemuxs = ARRAY_SIZE(clcd_modemux),
 };
 
-static const char *const clcd_grps[] = { "clcd_grp" };
+/* Disable cld runtime to save panel damage */
+static struct spear_muxreg clcd_sleep_muxreg[] = {
+       {
+               .reg = PAD_SHARED_IP_EN_1,
+               .mask = ARM_TRACE_MASK | MIPHY_DBG_MASK,
+               .val = 0,
+       }, {
+               .reg = PAD_FUNCTION_EN_5,
+               .mask = CLCD_REG4_MASK | CLCD_AND_ARM_TRACE_REG4_MASK,
+               .val = 0x0,
+       }, {
+               .reg = PAD_FUNCTION_EN_6,
+               .mask = CLCD_AND_ARM_TRACE_REG5_MASK,
+               .val = 0x0,
+       }, {
+               .reg = PAD_FUNCTION_EN_7,
+               .mask = CLCD_AND_ARM_TRACE_REG6_MASK,
+               .val = 0x0,
+       },
+};
+
+static struct spear_modemux clcd_sleep_modemux[] = {
+       {
+               .muxregs = clcd_sleep_muxreg,
+               .nmuxregs = ARRAY_SIZE(clcd_sleep_muxreg),
+       },
+};
+
+static struct spear_pingroup clcd_sleep_pingroup = {
+       .name = "clcd_sleep_grp",
+       .pins = clcd_pins,
+       .npins = ARRAY_SIZE(clcd_pins),
+       .modemuxs = clcd_sleep_modemux,
+       .nmodemuxs = ARRAY_SIZE(clcd_sleep_modemux),
+};
+
+static const char *const clcd_grps[] = { "clcd_grp", "clcd_sleep_grp" };
 static struct spear_function clcd_function = {
        .name = "clcd",
        .groups = clcd_grps,
@@ -1893,6 +1929,7 @@ static struct spear_pingroup *spear1340_pingroups[] = {
        &sdhci_pingroup,
        &cf_pingroup,
        &xd_pingroup,
+       &clcd_sleep_pingroup,
        &clcd_pingroup,
        &arm_trace_pingroup,
        &miphy_dbg_pingroup,
index 020b1e0bdb3ee77c0e4fd254e91467c3436604e9..ca47b0e50780c52b884c7155349ad107fd098a93 100644 (file)
@@ -2239,6 +2239,10 @@ static struct spear_muxreg pwm2_pin_34_muxreg[] = {
                .reg = PMX_CONFIG_REG,
                .mask = PMX_SSP_CS_MASK,
                .val = 0,
+       }, {
+               .reg = MODE_CONFIG_REG,
+               .mask = PMX_PWM_MASK,
+               .val = PMX_PWM_MASK,
        }, {
                .reg = IP_SEL_PAD_30_39_REG,
                .mask = PMX_PL_34_MASK,
@@ -2956,9 +2960,9 @@ static struct spear_function mii2_function = {
 };
 
 /* Pad multiplexing for cadence mii 1_2 as smii or rmii device */
-static const unsigned smii0_1_pins[] = { 10, 11, 13, 14, 15, 16, 17, 18, 19, 20,
+static const unsigned rmii0_1_pins[] = { 10, 11, 13, 14, 15, 16, 17, 18, 19, 20,
        21, 22, 23, 24, 25, 26, 27 };
-static const unsigned rmii0_1_pins[] = { 10, 11, 21, 22, 23, 24, 25, 26, 27 };
+static const unsigned smii0_1_pins[] = { 10, 11, 21, 22, 23, 24, 25, 26, 27 };
 static struct spear_muxreg mii0_1_muxreg[] = {
        {
                .reg = PMX_CONFIG_REG,
index 31f44347f17ccfd32e3ca0f0913d85b2998aaa05..7860b36053c4523f69a5861f9fd832afae0983e8 100644 (file)
@@ -15,6 +15,7 @@
 #include "pinctrl-spear.h"
 
 /* pad mux declarations */
+#define PMX_PWM_MASK           (1 << 16)
 #define PMX_FIRDA_MASK         (1 << 14)
 #define PMX_I2C_MASK           (1 << 13)
 #define PMX_SSP_CS_MASK                (1 << 12)
index c17ae22567e0494c381bf023c13e48dfc729aa8b..0c6fcb461faf7bb10df865bd3e49a5bd905313df 100644 (file)
@@ -401,7 +401,7 @@ EXPORT_SYMBOL_GPL(rio_release_inb_pwrite);
 /**
  * rio_map_inb_region -- Map inbound memory region.
  * @mport: Master port.
- * @lstart: physical address of memory region to be mapped
+ * @local: physical address of memory region to be mapped
  * @rbase: RIO base address assigned to this window
  * @size: Size of the memory region
  * @rflags: Flags for mapping.
index 5c4829cba6a62de6168c6bb3c4913812e5e8b4e1..e872c8be080ed427a2e546efffee50c12acdd9fe 100644 (file)
@@ -1381,22 +1381,14 @@ struct regulator *regulator_get_exclusive(struct device *dev, const char *id)
 }
 EXPORT_SYMBOL_GPL(regulator_get_exclusive);
 
-/**
- * regulator_put - "free" the regulator source
- * @regulator: regulator source
- *
- * Note: drivers must ensure that all regulator_enable calls made on this
- * regulator source are balanced by regulator_disable calls prior to calling
- * this function.
- */
-void regulator_put(struct regulator *regulator)
+/* Locks held by regulator_put() */
+static void _regulator_put(struct regulator *regulator)
 {
        struct regulator_dev *rdev;
 
        if (regulator == NULL || IS_ERR(regulator))
                return;
 
-       mutex_lock(&regulator_list_mutex);
        rdev = regulator->rdev;
 
        debugfs_remove_recursive(regulator->debugfs);
@@ -1412,6 +1404,20 @@ void regulator_put(struct regulator *regulator)
        rdev->exclusive = 0;
 
        module_put(rdev->owner);
+}
+
+/**
+ * regulator_put - "free" the regulator source
+ * @regulator: regulator source
+ *
+ * Note: drivers must ensure that all regulator_enable calls made on this
+ * regulator source are balanced by regulator_disable calls prior to calling
+ * this function.
+ */
+void regulator_put(struct regulator *regulator)
+{
+       mutex_lock(&regulator_list_mutex);
+       _regulator_put(regulator);
        mutex_unlock(&regulator_list_mutex);
 }
 EXPORT_SYMBOL_GPL(regulator_put);
@@ -1974,7 +1980,7 @@ int regulator_is_supported_voltage(struct regulator *regulator,
        if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) {
                ret = regulator_get_voltage(regulator);
                if (ret >= 0)
-                       return (min_uV >= ret && ret <= max_uV);
+                       return (min_uV <= ret && ret <= max_uV);
                else
                        return ret;
        }
@@ -3365,7 +3371,7 @@ regulator_register(const struct regulator_desc *regulator_desc,
                if (ret != 0) {
                        rdev_err(rdev, "Failed to request enable GPIO%d: %d\n",
                                 config->ena_gpio, ret);
-                       goto clean;
+                       goto wash;
                }
 
                rdev->ena_gpio = config->ena_gpio;
@@ -3445,10 +3451,11 @@ unset_supplies:
 
 scrub:
        if (rdev->supply)
-               regulator_put(rdev->supply);
+               _regulator_put(rdev->supply);
        if (rdev->ena_gpio)
                gpio_free(rdev->ena_gpio);
        kfree(rdev->constraints);
+wash:
        device_unregister(&rdev->dev);
        /* device core frees rdev */
        rdev = ERR_PTR(ret);
index 891cd6c61d0ae76112ccc0f6b6da3876d21569ad..4eed51044c5dd331f576fc1b1b71655e5f932366 100644 (file)
@@ -392,6 +392,8 @@ static int dryice_rtc_probe(struct platform_device *pdev)
        if (imxdi->ioaddr == NULL)
                return -ENOMEM;
 
+       spin_lock_init(&imxdi->irq_lock);
+
        imxdi->irq = platform_get_irq(pdev, 0);
        if (imxdi->irq < 0)
                return imxdi->irq;
index 9ffb6d5f17aa0523473215db57edeccda1391a70..4ed343e4eb4155718cc31084eb6902a2ee84f570 100644 (file)
@@ -44,7 +44,6 @@
 #define RAW3215_NR_CCWS            3
 #define RAW3215_TIMEOUT            HZ/10     /* time for delayed output */
 
-#define RAW3215_FIXED      1         /* 3215 console device is not be freed */
 #define RAW3215_WORKING            4         /* set if a request is being worked on */
 #define RAW3215_THROTTLED   8        /* set if reading is disabled */
 #define RAW3215_STOPPED            16        /* set if writing is disabled */
@@ -339,8 +338,10 @@ static void raw3215_wakeup(unsigned long data)
        struct tty_struct *tty;
 
        tty = tty_port_tty_get(&raw->port);
-       tty_wakeup(tty);
-       tty_kref_put(tty);
+       if (tty) {
+               tty_wakeup(tty);
+               tty_kref_put(tty);
+       }
 }
 
 /*
@@ -629,8 +630,7 @@ static void raw3215_shutdown(struct raw3215_info *raw)
        DECLARE_WAITQUEUE(wait, current);
        unsigned long flags;
 
-       if (!(raw->port.flags & ASYNC_INITIALIZED) ||
-                       (raw->flags & RAW3215_FIXED))
+       if (!(raw->port.flags & ASYNC_INITIALIZED))
                return;
        /* Wait for outstanding requests, then free irq */
        spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
@@ -926,8 +926,6 @@ static int __init con3215_init(void)
        dev_set_drvdata(&cdev->dev, raw);
        cdev->handler = raw3215_irq;
 
-       raw->flags |= RAW3215_FIXED;
-
        /* Request the console irq */
        if (raw3215_startup(raw) != 0) {
                raw3215_free_info(raw);
index b4d572f65f079d93650cebd8ff5f7bb39bcb75d2..fd00afd8b850da2abaa916ba485dccd748939319 100644 (file)
@@ -377,7 +377,11 @@ static int css_evaluate_new_subchannel(struct subchannel_id schid, int slow)
                /* Will be done on the slow path. */
                return -EAGAIN;
        }
-       if (stsch_err(schid, &schib) || !css_sch_is_valid(&schib)) {
+       if (stsch_err(schid, &schib)) {
+               /* Subchannel is not provided. */
+               return -ENXIO;
+       }
+       if (!css_sch_is_valid(&schib)) {
                /* Unusable - ignore. */
                return 0;
        }
@@ -536,6 +540,7 @@ static int slow_eval_unknown_fn(struct subchannel_id schid, void *data)
                case -ENOMEM:
                case -EIO:
                        /* These should abort looping */
+                       idset_sch_del_subseq(slow_subchannel_set, schid);
                        break;
                default:
                        rc = 0;
index 33bb4d891e161174d01b8f6e0d6433883d5fb495..4af3dfe70ef53d075bb7cc96ea1064801ac777c6 100644 (file)
@@ -112,9 +112,6 @@ extern int for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *);
 extern void css_reiterate_subchannels(void);
 void css_update_ssd_info(struct subchannel *sch);
 
-#define __MAX_SUBCHANNEL 65535
-#define __MAX_SSID 3
-
 struct channel_subsystem {
        u8 cssid;
        int valid;
index fc916f5d731412c7146465d3ff29277979b69189..fd3143c291c6a630933d608c6c6e455b2be04a0d 100644 (file)
@@ -1424,7 +1424,7 @@ static enum io_sch_action sch_get_action(struct subchannel *sch)
        }
        if (device_is_disconnected(cdev))
                return IO_SCH_REPROBE;
-       if (cdev->online)
+       if (cdev->online && !cdev->private->flags.resuming)
                return IO_SCH_VERIFY;
        if (cdev->private->state == DEV_STATE_NOT_OPER)
                return IO_SCH_UNREG_ATTACH;
@@ -1469,12 +1469,6 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process)
                rc = 0;
                goto out_unlock;
        case IO_SCH_VERIFY:
-               if (cdev->private->flags.resuming == 1) {
-                       if (cio_enable_subchannel(sch, (u32)(addr_t)sch)) {
-                               ccw_device_set_notoper(cdev);
-                               break;
-                       }
-               }
                /* Trigger path verification. */
                io_subchannel_verify(sch);
                rc = 0;
index e6d5f8c49524d05f78f6548a2937b1747bd7ffe6..65d13e38803f9dddc11079b9a00176e7b94116d2 100644 (file)
@@ -1,9 +1,10 @@
 /*
- *    Copyright IBM Corp. 2007
+ *    Copyright IBM Corp. 2007, 2012
  *    Author(s): Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
  */
 
 #include <linux/vmalloc.h>
+#include <linux/bitmap.h>
 #include <linux/bitops.h>
 #include "idset.h"
 #include "css.h"
@@ -89,6 +90,14 @@ void idset_sch_del(struct idset *set, struct subchannel_id schid)
        idset_del(set, schid.ssid, schid.sch_no);
 }
 
+/* Clear ids starting from @schid up to end of subchannel set. */
+void idset_sch_del_subseq(struct idset *set, struct subchannel_id schid)
+{
+       int pos = schid.ssid * set->num_id + schid.sch_no;
+
+       bitmap_clear(set->bitmap, pos, set->num_id - schid.sch_no);
+}
+
 int idset_sch_contains(struct idset *set, struct subchannel_id schid)
 {
        return idset_contains(set, schid.ssid, schid.sch_no);
@@ -111,20 +120,12 @@ int idset_sch_get_first(struct idset *set, struct subchannel_id *schid)
 
 int idset_is_empty(struct idset *set)
 {
-       int bitnum;
-
-       bitnum = find_first_bit(set->bitmap, set->num_ssid * set->num_id);
-       if (bitnum >= set->num_ssid * set->num_id)
-               return 1;
-       return 0;
+       return bitmap_empty(set->bitmap, set->num_ssid * set->num_id);
 }
 
 void idset_add_set(struct idset *to, struct idset *from)
 {
-       unsigned long i, len;
+       int len = min(to->num_ssid * to->num_id, from->num_ssid * from->num_id);
 
-       len = min(__BITOPS_WORDS(to->num_ssid * to->num_id),
-                 __BITOPS_WORDS(from->num_ssid * from->num_id));
-       for (i = 0; i < len ; i++)
-               to->bitmap[i] |= from->bitmap[i];
+       bitmap_or(to->bitmap, to->bitmap, from->bitmap, len);
 }
index 3d943f03591e1b2180cc6fdd9c92e54c99a0d0e4..06d3bc01bb0934a52198349da2657e8787c46c13 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *    Copyright IBM Corp. 2007
+ *    Copyright IBM Corp. 2007, 2012
  *    Author(s): Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
  */
 
@@ -17,6 +17,7 @@ void idset_fill(struct idset *set);
 struct idset *idset_sch_new(void);
 void idset_sch_add(struct idset *set, struct subchannel_id id);
 void idset_sch_del(struct idset *set, struct subchannel_id id);
+void idset_sch_del_subseq(struct idset *set, struct subchannel_id schid);
 int idset_sch_contains(struct idset *set, struct subchannel_id id);
 int idset_sch_get_first(struct idset *set, struct subchannel_id *id);
 int idset_is_empty(struct idset *set);
index 3e25d31504560a79b75b782a45153190a7694ffa..4d6ba00d00472055f56afe7ad2b4f651d7f6fe26 100644 (file)
@@ -2942,13 +2942,33 @@ static int qeth_query_ipassists_cb(struct qeth_card *card,
        QETH_DBF_TEXT(SETUP, 2, "qipasscb");
 
        cmd = (struct qeth_ipa_cmd *) data;
+
+       switch (cmd->hdr.return_code) {
+       case IPA_RC_NOTSUPP:
+       case IPA_RC_L2_UNSUPPORTED_CMD:
+               QETH_DBF_TEXT(SETUP, 2, "ipaunsup");
+               card->options.ipa4.supported_funcs |= IPA_SETADAPTERPARMS;
+               card->options.ipa6.supported_funcs |= IPA_SETADAPTERPARMS;
+               return -0;
+       default:
+               if (cmd->hdr.return_code) {
+                       QETH_DBF_MESSAGE(1, "%s IPA_CMD_QIPASSIST: Unhandled "
+                                               "rc=%d\n",
+                                               dev_name(&card->gdev->dev),
+                                               cmd->hdr.return_code);
+                       return 0;
+               }
+       }
+
        if (cmd->hdr.prot_version == QETH_PROT_IPV4) {
                card->options.ipa4.supported_funcs = cmd->hdr.ipa_supported;
                card->options.ipa4.enabled_funcs = cmd->hdr.ipa_enabled;
-       } else {
+       } else if (cmd->hdr.prot_version == QETH_PROT_IPV6) {
                card->options.ipa6.supported_funcs = cmd->hdr.ipa_supported;
                card->options.ipa6.enabled_funcs = cmd->hdr.ipa_enabled;
-       }
+       } else
+               QETH_DBF_MESSAGE(1, "%s IPA_CMD_QIPASSIST: Flawed LIC detected"
+                                       "\n", dev_name(&card->gdev->dev));
        QETH_DBF_TEXT(SETUP, 2, "suppenbl");
        QETH_DBF_TEXT_(SETUP, 2, "%08x", (__u32)cmd->hdr.ipa_supported);
        QETH_DBF_TEXT_(SETUP, 2, "%08x", (__u32)cmd->hdr.ipa_enabled);
index e67e0258aec582a8d441e3eff5591c1eec2058ec..fddb62654b6a6cabeaf4e168951a305cddce1abd 100644 (file)
@@ -626,10 +626,13 @@ static int qeth_l2_request_initial_mac(struct qeth_card *card)
        QETH_DBF_TEXT(SETUP, 2, "doL2init");
        QETH_DBF_TEXT_(SETUP, 2, "doL2%s", CARD_BUS_ID(card));
 
-       rc = qeth_query_setadapterparms(card);
-       if (rc) {
-               QETH_DBF_MESSAGE(2, "could not query adapter parameters on "
-                       "device %s: x%x\n", CARD_BUS_ID(card), rc);
+       if (qeth_is_supported(card, IPA_SETADAPTERPARMS)) {
+               rc = qeth_query_setadapterparms(card);
+               if (rc) {
+                       QETH_DBF_MESSAGE(2, "could not query adapter "
+                               "parameters on device %s: x%x\n",
+                               CARD_BUS_ID(card), rc);
+               }
        }
 
        if (card->info.type == QETH_CARD_TYPE_IQD ||
@@ -676,7 +679,7 @@ static int qeth_l2_set_mac_address(struct net_device *dev, void *p)
                return -ERESTARTSYS;
        }
        rc = qeth_l2_send_delmac(card, &card->dev->dev_addr[0]);
-       if (!rc)
+       if (!rc || (rc == IPA_RC_L2_MAC_NOT_FOUND))
                rc = qeth_l2_send_setmac(card, addr->sa_data);
        return rc ? -EINVAL : 0;
 }
index c1bafc3f3fb19bad3a1587c85345ef2c4fa9545f..9594ab62702b1786d51d7ac80f7e10b365b6ce61 100644 (file)
@@ -1972,7 +1972,7 @@ sci_io_request_frame_handler(struct isci_request *ireq,
                                                                      frame_index,
                                                                      (void **)&frame_buffer);
 
-                       sci_controller_copy_sata_response(&ireq->stp.req,
+                       sci_controller_copy_sata_response(&ireq->stp.rsp,
                                                               frame_header,
                                                               frame_buffer);
 
index bd4708a422cd78b09fd8594ded593af775343398..20fd974f903afd5d4ae15c95db2549d49db52849 100644 (file)
@@ -149,6 +149,7 @@ qla2x00_mark_vp_devices_dead(scsi_qla_host_t *vha)
 int
 qla24xx_disable_vp(scsi_qla_host_t *vha)
 {
+       unsigned long flags;
        int ret;
 
        ret = qla24xx_control_vp(vha, VCE_COMMAND_DISABLE_VPS_LOGO_ALL);
@@ -156,7 +157,9 @@ qla24xx_disable_vp(scsi_qla_host_t *vha)
        atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
 
        /* Remove port id from vp target map */
+       spin_lock_irqsave(&vha->hw->vport_slock, flags);
        qlt_update_vp_map(vha, RESET_AL_PA);
+       spin_unlock_irqrestore(&vha->hw->vport_slock, flags);
 
        qla2x00_mark_vp_devices_dead(vha);
        atomic_set(&vha->vp_state, VP_FAILED);
index 0e09d8f433d1683e61ba61074d7c67b71919d970..62aa5584f64478d286e373414dd8b119315a5204 100644 (file)
@@ -557,6 +557,7 @@ static bool qlt_check_fcport_exist(struct scsi_qla_host *vha,
        int pmap_len;
        fc_port_t *fcport;
        int global_resets;
+       unsigned long flags;
 
 retry:
        global_resets = atomic_read(&ha->tgt.qla_tgt->tgt_global_resets_count);
@@ -625,10 +626,10 @@ retry:
            sess->s_id.b.area, sess->loop_id, fcport->d_id.b.domain,
            fcport->d_id.b.al_pa, fcport->d_id.b.area, fcport->loop_id);
 
-       sess->s_id = fcport->d_id;
-       sess->loop_id = fcport->loop_id;
-       sess->conf_compl_supported = !!(fcport->flags &
-           FCF_CONF_COMP_SUPPORTED);
+       spin_lock_irqsave(&ha->hardware_lock, flags);
+       ha->tgt.tgt_ops->update_sess(sess, fcport->d_id, fcport->loop_id,
+                               (fcport->flags & FCF_CONF_COMP_SUPPORTED));
+       spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
        res = true;
 
@@ -740,10 +741,9 @@ static struct qla_tgt_sess *qlt_create_sess(
                                qlt_undelete_sess(sess);
 
                        kref_get(&sess->se_sess->sess_kref);
-                       sess->s_id = fcport->d_id;
-                       sess->loop_id = fcport->loop_id;
-                       sess->conf_compl_supported = !!(fcport->flags &
-                           FCF_CONF_COMP_SUPPORTED);
+                       ha->tgt.tgt_ops->update_sess(sess, fcport->d_id, fcport->loop_id,
+                                               (fcport->flags & FCF_CONF_COMP_SUPPORTED));
+
                        if (sess->local && !local)
                                sess->local = 0;
                        spin_unlock_irqrestore(&ha->hardware_lock, flags);
@@ -796,8 +796,7 @@ static struct qla_tgt_sess *qlt_create_sess(
         */
        kref_get(&sess->se_sess->sess_kref);
 
-       sess->conf_compl_supported = !!(fcport->flags &
-           FCF_CONF_COMP_SUPPORTED);
+       sess->conf_compl_supported = (fcport->flags & FCF_CONF_COMP_SUPPORTED);
        BUILD_BUG_ON(sizeof(sess->port_name) != sizeof(fcport->port_name));
        memcpy(sess->port_name, fcport->port_name, sizeof(sess->port_name));
 
@@ -869,10 +868,8 @@ void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport)
                        ql_dbg(ql_dbg_tgt_mgt, vha, 0xf007,
                            "Reappeared sess %p\n", sess);
                }
-               sess->s_id = fcport->d_id;
-               sess->loop_id = fcport->loop_id;
-               sess->conf_compl_supported = !!(fcport->flags &
-                   FCF_CONF_COMP_SUPPORTED);
+               ha->tgt.tgt_ops->update_sess(sess, fcport->d_id, fcport->loop_id,
+                                       (fcport->flags & FCF_CONF_COMP_SUPPORTED));
        }
 
        if (sess && sess->local) {
index 170af1571214095fe82db73fa52f520c16a8197b..bad749561ec2ae4fe57e3ea28763ec627f0b18f1 100644 (file)
@@ -648,6 +648,7 @@ struct qla_tgt_func_tmpl {
 
        int (*check_initiator_node_acl)(struct scsi_qla_host *, unsigned char *,
                                        void *, uint8_t *, uint16_t);
+       void (*update_sess)(struct qla_tgt_sess *, port_id_t, uint16_t, bool);
        struct qla_tgt_sess *(*find_sess_by_loop_id)(struct scsi_qla_host *,
                                                const uint16_t);
        struct qla_tgt_sess *(*find_sess_by_s_id)(struct scsi_qla_host *,
index 2358c16c4c8ea8a0cdb85c33c2c97a5b4e65c400..3d74f2f39ae18954ac825f4599b689d770f494cf 100644 (file)
@@ -237,7 +237,7 @@ static char *tcm_qla2xxx_get_fabric_wwn(struct se_portal_group *se_tpg)
                                struct tcm_qla2xxx_tpg, se_tpg);
        struct tcm_qla2xxx_lport *lport = tpg->lport;
 
-       return &lport->lport_name[0];
+       return lport->lport_naa_name;
 }
 
 static char *tcm_qla2xxx_npiv_get_fabric_wwn(struct se_portal_group *se_tpg)
@@ -1457,6 +1457,78 @@ static int tcm_qla2xxx_check_initiator_node_acl(
        return 0;
 }
 
+static void tcm_qla2xxx_update_sess(struct qla_tgt_sess *sess, port_id_t s_id,
+                                   uint16_t loop_id, bool conf_compl_supported)
+{
+       struct qla_tgt *tgt = sess->tgt;
+       struct qla_hw_data *ha = tgt->ha;
+       struct tcm_qla2xxx_lport *lport = ha->tgt.target_lport_ptr;
+       struct se_node_acl *se_nacl = sess->se_sess->se_node_acl;
+       struct tcm_qla2xxx_nacl *nacl = container_of(se_nacl,
+                       struct tcm_qla2xxx_nacl, se_node_acl);
+       u32 key;
+
+
+       if (sess->loop_id != loop_id || sess->s_id.b24 != s_id.b24)
+               pr_info("Updating session %p from port %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x loop_id %d -> %d s_id %x:%x:%x -> %x:%x:%x\n",
+                       sess,
+                       sess->port_name[0], sess->port_name[1],
+                       sess->port_name[2], sess->port_name[3],
+                       sess->port_name[4], sess->port_name[5],
+                       sess->port_name[6], sess->port_name[7],
+                       sess->loop_id, loop_id,
+                       sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa,
+                       s_id.b.domain, s_id.b.area, s_id.b.al_pa);
+
+       if (sess->loop_id != loop_id) {
+               /*
+                * Because we can shuffle loop IDs around and we
+                * update different sessions non-atomically, we might
+                * have overwritten this session's old loop ID
+                * already, and we might end up overwriting some other
+                * session that will be updated later.  So we have to
+                * be extra careful and we can't warn about those things...
+                */
+               if (lport->lport_loopid_map[sess->loop_id].se_nacl == se_nacl)
+                       lport->lport_loopid_map[sess->loop_id].se_nacl = NULL;
+
+               lport->lport_loopid_map[loop_id].se_nacl = se_nacl;
+
+               sess->loop_id = loop_id;
+       }
+
+       if (sess->s_id.b24 != s_id.b24) {
+               key = (((u32) sess->s_id.b.domain << 16) |
+                      ((u32) sess->s_id.b.area   <<  8) |
+                      ((u32) sess->s_id.b.al_pa));
+
+               if (btree_lookup32(&lport->lport_fcport_map, key))
+                       WARN(btree_remove32(&lport->lport_fcport_map, key) != se_nacl,
+                            "Found wrong se_nacl when updating s_id %x:%x:%x\n",
+                            sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa);
+               else
+                       WARN(1, "No lport_fcport_map entry for s_id %x:%x:%x\n",
+                            sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa);
+
+               key = (((u32) s_id.b.domain << 16) |
+                      ((u32) s_id.b.area   <<  8) |
+                      ((u32) s_id.b.al_pa));
+
+               if (btree_lookup32(&lport->lport_fcport_map, key)) {
+                       WARN(1, "Already have lport_fcport_map entry for s_id %x:%x:%x\n",
+                            s_id.b.domain, s_id.b.area, s_id.b.al_pa);
+                       btree_update32(&lport->lport_fcport_map, key, se_nacl);
+               } else {
+                       btree_insert32(&lport->lport_fcport_map, key, se_nacl, GFP_ATOMIC);
+               }
+
+               sess->s_id = s_id;
+               nacl->nport_id = key;
+       }
+
+       sess->conf_compl_supported = conf_compl_supported;
+}
+
 /*
  * Calls into tcm_qla2xxx used by qla2xxx LLD I/O path.
  */
@@ -1467,6 +1539,7 @@ static struct qla_tgt_func_tmpl tcm_qla2xxx_template = {
        .free_cmd               = tcm_qla2xxx_free_cmd,
        .free_mcmd              = tcm_qla2xxx_free_mcmd,
        .free_session           = tcm_qla2xxx_free_session,
+       .update_sess            = tcm_qla2xxx_update_sess,
        .check_initiator_node_acl = tcm_qla2xxx_check_initiator_node_acl,
        .find_sess_by_s_id      = tcm_qla2xxx_find_sess_by_s_id,
        .find_sess_by_loop_id   = tcm_qla2xxx_find_sess_by_loop_id,
@@ -1534,6 +1607,7 @@ static struct se_wwn *tcm_qla2xxx_make_lport(
        lport->lport_wwpn = wwpn;
        tcm_qla2xxx_format_wwn(&lport->lport_name[0], TCM_QLA2XXX_NAMELEN,
                                wwpn);
+       sprintf(lport->lport_naa_name, "naa.%016llx", (unsigned long long) wwpn);
 
        ret = tcm_qla2xxx_init_lport(lport);
        if (ret != 0)
@@ -1601,6 +1675,7 @@ static struct se_wwn *tcm_qla2xxx_npiv_make_lport(
        lport->lport_npiv_wwnn = npiv_wwnn;
        tcm_qla2xxx_npiv_format_wwn(&lport->lport_npiv_name[0],
                        TCM_QLA2XXX_NAMELEN, npiv_wwpn, npiv_wwnn);
+       sprintf(lport->lport_naa_name, "naa.%016llx", (unsigned long long) npiv_wwpn);
 
 /* FIXME: tcm_qla2xxx_npiv_make_lport */
        ret = -ENOSYS;
index 8254981033524466bc372ac4bbd067aa5d19cc5b..9ba075fe9781f0148dca9aa73b6525e554a91154 100644 (file)
@@ -61,6 +61,8 @@ struct tcm_qla2xxx_lport {
        u64 lport_npiv_wwnn;
        /* ASCII formatted WWPN for FC Target Lport */
        char lport_name[TCM_QLA2XXX_NAMELEN];
+       /* ASCII formatted naa WWPN for VPD page 83 etc */
+       char lport_naa_name[TCM_QLA2XXX_NAMELEN];
        /* ASCII formatted WWPN+WWNN for NPIV FC Target Lport */
        char lport_npiv_name[TCM_QLA2XXX_NPIV_NAMELEN];
        /* map for fc_port pointers in 24-bit FC Port ID space */
index b191dd549207db3ac2c25fd16e3b6a87559cb047..71fddbc60f181feb15bbd30994f16dc5b35d4831 100644 (file)
@@ -1294,26 +1294,19 @@ static struct scsi_host_template qpti_template = {
 static const struct of_device_id qpti_match[];
 static int __devinit qpti_sbus_probe(struct platform_device *op)
 {
-       const struct of_device_id *match;
-       struct scsi_host_template *tpnt;
        struct device_node *dp = op->dev.of_node;
        struct Scsi_Host *host;
        struct qlogicpti *qpti;
        static int nqptis;
        const char *fcode;
 
-       match = of_match_device(qpti_match, &op->dev);
-       if (!match)
-               return -EINVAL;
-       tpnt = match->data;
-
        /* Sometimes Antares cards come up not completely
         * setup, and we get a report of a zero IRQ.
         */
        if (op->archdata.irqs[0] == 0)
                return -ENODEV;
 
-       host = scsi_host_alloc(tpnt, sizeof(struct qlogicpti));
+       host = scsi_host_alloc(&qpti_template, sizeof(struct qlogicpti));
        if (!host)
                return -ENOMEM;
 
@@ -1445,19 +1438,15 @@ static int __devexit qpti_sbus_remove(struct platform_device *op)
 static const struct of_device_id qpti_match[] = {
        {
                .name = "ptisp",
-               .data = &qpti_template,
        },
        {
                .name = "PTI,ptisp",
-               .data = &qpti_template,
        },
        {
                .name = "QLGC,isp",
-               .data = &qpti_template,
        },
        {
                .name = "SUNW,isp",
-               .data = &qpti_template,
        },
        {},
 };
index 2936b447cae93bc544fc054c862ecd6d1abb92c6..2c0d0ec8150b62d62d8ca3ca9ecc777a950a7c0a 100644 (file)
@@ -55,6 +55,7 @@
 #include <linux/cpu.h>
 #include <linux/mutex.h>
 #include <linux/async.h>
+#include <asm/unaligned.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
@@ -1061,6 +1062,50 @@ int scsi_get_vpd_page(struct scsi_device *sdev, u8 page, unsigned char *buf,
 }
 EXPORT_SYMBOL_GPL(scsi_get_vpd_page);
 
+/**
+ * scsi_report_opcode - Find out if a given command opcode is supported
+ * @sdev:      scsi device to query
+ * @buffer:    scratch buffer (must be at least 20 bytes long)
+ * @len:       length of buffer
+ * @opcode:    opcode for command to look up
+ *
+ * Uses the REPORT SUPPORTED OPERATION CODES to look up the given
+ * opcode. Returns 0 if RSOC fails or if the command opcode is
+ * unsupported. Returns 1 if the device claims to support the command.
+ */
+int scsi_report_opcode(struct scsi_device *sdev, unsigned char *buffer,
+                      unsigned int len, unsigned char opcode)
+{
+       unsigned char cmd[16];
+       struct scsi_sense_hdr sshdr;
+       int result;
+
+       if (sdev->no_report_opcodes || sdev->scsi_level < SCSI_SPC_3)
+               return 0;
+
+       memset(cmd, 0, 16);
+       cmd[0] = MAINTENANCE_IN;
+       cmd[1] = MI_REPORT_SUPPORTED_OPERATION_CODES;
+       cmd[2] = 1;             /* One command format */
+       cmd[3] = opcode;
+       put_unaligned_be32(len, &cmd[6]);
+       memset(buffer, 0, len);
+
+       result = scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buffer, len,
+                                 &sshdr, 30 * HZ, 3, NULL);
+
+       if (result && scsi_sense_valid(&sshdr) &&
+           sshdr.sense_key == ILLEGAL_REQUEST &&
+           (sshdr.asc == 0x20 || sshdr.asc == 0x24) && sshdr.ascq == 0x00)
+               return 0;
+
+       if ((buffer[1] & 3) == 3) /* Command supported */
+               return 1;
+
+       return 0;
+}
+EXPORT_SYMBOL(scsi_report_opcode);
+
 /**
  * scsi_device_get  -  get an additional reference to a scsi_device
  * @sdev:      device to get a reference to
index da36a3a81a9ee2206f753a04d4fbbe91b883e00a..9032e910bca3044055ed23310b38c126318736bb 100644 (file)
@@ -900,11 +900,23 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
                                action = ACTION_FAIL;
                                error = -EILSEQ;
                        /* INVALID COMMAND OPCODE or INVALID FIELD IN CDB */
-                       } else if ((sshdr.asc == 0x20 || sshdr.asc == 0x24) &&
-                                  (cmd->cmnd[0] == UNMAP ||
-                                   cmd->cmnd[0] == WRITE_SAME_16 ||
-                                   cmd->cmnd[0] == WRITE_SAME)) {
-                               description = "Discard failure";
+                       } else if (sshdr.asc == 0x20 || sshdr.asc == 0x24) {
+                               switch (cmd->cmnd[0]) {
+                               case UNMAP:
+                                       description = "Discard failure";
+                                       break;
+                               case WRITE_SAME:
+                               case WRITE_SAME_16:
+                                       if (cmd->cmnd[1] & 0x8)
+                                               description = "Discard failure";
+                                       else
+                                               description =
+                                                       "Write same failure";
+                                       break;
+                               default:
+                                       description = "Invalid command failure";
+                                       break;
+                               }
                                action = ACTION_FAIL;
                                error = -EREMOTEIO;
                        } else
index 12f6fdfc11474a9363ae6c641959832d2c1d6440..352bc77b7c886fb80c057019c3edc2d5b95b7d7e 100644 (file)
@@ -99,6 +99,7 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_RBC);
 #endif
 
 static void sd_config_discard(struct scsi_disk *, unsigned int);
+static void sd_config_write_same(struct scsi_disk *);
 static int  sd_revalidate_disk(struct gendisk *);
 static void sd_unlock_native_capacity(struct gendisk *disk);
 static int  sd_probe(struct device *);
@@ -395,6 +396,45 @@ sd_store_max_medium_access_timeouts(struct device *dev,
        return err ? err : count;
 }
 
+static ssize_t
+sd_show_write_same_blocks(struct device *dev, struct device_attribute *attr,
+                         char *buf)
+{
+       struct scsi_disk *sdkp = to_scsi_disk(dev);
+
+       return snprintf(buf, 20, "%u\n", sdkp->max_ws_blocks);
+}
+
+static ssize_t
+sd_store_write_same_blocks(struct device *dev, struct device_attribute *attr,
+                          const char *buf, size_t count)
+{
+       struct scsi_disk *sdkp = to_scsi_disk(dev);
+       struct scsi_device *sdp = sdkp->device;
+       unsigned long max;
+       int err;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EACCES;
+
+       if (sdp->type != TYPE_DISK)
+               return -EINVAL;
+
+       err = kstrtoul(buf, 10, &max);
+
+       if (err)
+               return err;
+
+       if (max == 0)
+               sdp->no_write_same = 1;
+       else if (max <= SD_MAX_WS16_BLOCKS)
+               sdkp->max_ws_blocks = max;
+
+       sd_config_write_same(sdkp);
+
+       return count;
+}
+
 static struct device_attribute sd_disk_attrs[] = {
        __ATTR(cache_type, S_IRUGO|S_IWUSR, sd_show_cache_type,
               sd_store_cache_type),
@@ -410,6 +450,8 @@ static struct device_attribute sd_disk_attrs[] = {
        __ATTR(thin_provisioning, S_IRUGO, sd_show_thin_provisioning, NULL),
        __ATTR(provisioning_mode, S_IRUGO|S_IWUSR, sd_show_provisioning_mode,
               sd_store_provisioning_mode),
+       __ATTR(max_write_same_blocks, S_IRUGO|S_IWUSR,
+              sd_show_write_same_blocks, sd_store_write_same_blocks),
        __ATTR(max_medium_access_timeouts, S_IRUGO|S_IWUSR,
               sd_show_max_medium_access_timeouts,
               sd_store_max_medium_access_timeouts),
@@ -561,19 +603,23 @@ static void sd_config_discard(struct scsi_disk *sdkp, unsigned int mode)
                return;
 
        case SD_LBP_UNMAP:
-               max_blocks = min_not_zero(sdkp->max_unmap_blocks, 0xffffffff);
+               max_blocks = min_not_zero(sdkp->max_unmap_blocks,
+                                         (u32)SD_MAX_WS16_BLOCKS);
                break;
 
        case SD_LBP_WS16:
-               max_blocks = min_not_zero(sdkp->max_ws_blocks, 0xffffffff);
+               max_blocks = min_not_zero(sdkp->max_ws_blocks,
+                                         (u32)SD_MAX_WS16_BLOCKS);
                break;
 
        case SD_LBP_WS10:
-               max_blocks = min_not_zero(sdkp->max_ws_blocks, (u32)0xffff);
+               max_blocks = min_not_zero(sdkp->max_ws_blocks,
+                                         (u32)SD_MAX_WS10_BLOCKS);
                break;
 
        case SD_LBP_ZERO:
-               max_blocks = min_not_zero(sdkp->max_ws_blocks, (u32)0xffff);
+               max_blocks = min_not_zero(sdkp->max_ws_blocks,
+                                         (u32)SD_MAX_WS10_BLOCKS);
                q->limits.discard_zeroes_data = 1;
                break;
        }
@@ -583,29 +629,26 @@ static void sd_config_discard(struct scsi_disk *sdkp, unsigned int mode)
 }
 
 /**
- * scsi_setup_discard_cmnd - unmap blocks on thinly provisioned device
+ * sd_setup_discard_cmnd - unmap blocks on thinly provisioned device
  * @sdp: scsi device to operate one
  * @rq: Request to prepare
  *
  * Will issue either UNMAP or WRITE SAME(16) depending on preference
  * indicated by target device.
  **/
-static int scsi_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq)
+static int sd_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq)
 {
        struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
-       struct bio *bio = rq->bio;
-       sector_t sector = bio->bi_sector;
-       unsigned int nr_sectors = bio_sectors(bio);
+       sector_t sector = blk_rq_pos(rq);
+       unsigned int nr_sectors = blk_rq_sectors(rq);
+       unsigned int nr_bytes = blk_rq_bytes(rq);
        unsigned int len;
        int ret;
        char *buf;
        struct page *page;
 
-       if (sdkp->device->sector_size == 4096) {
-               sector >>= 3;
-               nr_sectors >>= 3;
-       }
-
+       sector >>= ilog2(sdp->sector_size) - 9;
+       nr_sectors >>= ilog2(sdp->sector_size) - 9;
        rq->timeout = SD_TIMEOUT;
 
        memset(rq->cmd, 0, rq->cmd_len);
@@ -660,6 +703,7 @@ static int scsi_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq)
        blk_add_request_payload(rq, page, len);
        ret = scsi_setup_blk_pc_cmnd(sdp, rq);
        rq->buffer = page_address(page);
+       rq->__data_len = nr_bytes;
 
 out:
        if (ret != BLKPREP_OK) {
@@ -669,6 +713,83 @@ out:
        return ret;
 }
 
+static void sd_config_write_same(struct scsi_disk *sdkp)
+{
+       struct request_queue *q = sdkp->disk->queue;
+       unsigned int logical_block_size = sdkp->device->sector_size;
+       unsigned int blocks = 0;
+
+       if (sdkp->device->no_write_same) {
+               sdkp->max_ws_blocks = 0;
+               goto out;
+       }
+
+       /* Some devices can not handle block counts above 0xffff despite
+        * supporting WRITE SAME(16). Consequently we default to 64k
+        * blocks per I/O unless the device explicitly advertises a
+        * bigger limit.
+        */
+       if (sdkp->max_ws_blocks == 0)
+               sdkp->max_ws_blocks = SD_MAX_WS10_BLOCKS;
+
+       if (sdkp->ws16 || sdkp->max_ws_blocks > SD_MAX_WS10_BLOCKS)
+               blocks = min_not_zero(sdkp->max_ws_blocks,
+                                     (u32)SD_MAX_WS16_BLOCKS);
+       else
+               blocks = min_not_zero(sdkp->max_ws_blocks,
+                                     (u32)SD_MAX_WS10_BLOCKS);
+
+out:
+       blk_queue_max_write_same_sectors(q, blocks * (logical_block_size >> 9));
+}
+
+/**
+ * sd_setup_write_same_cmnd - write the same data to multiple blocks
+ * @sdp: scsi device to operate one
+ * @rq: Request to prepare
+ *
+ * Will issue either WRITE SAME(10) or WRITE SAME(16) depending on
+ * preference indicated by target device.
+ **/
+static int sd_setup_write_same_cmnd(struct scsi_device *sdp, struct request *rq)
+{
+       struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
+       struct bio *bio = rq->bio;
+       sector_t sector = blk_rq_pos(rq);
+       unsigned int nr_sectors = blk_rq_sectors(rq);
+       unsigned int nr_bytes = blk_rq_bytes(rq);
+       int ret;
+
+       if (sdkp->device->no_write_same)
+               return BLKPREP_KILL;
+
+       BUG_ON(bio_offset(bio) || bio_iovec(bio)->bv_len != sdp->sector_size);
+
+       sector >>= ilog2(sdp->sector_size) - 9;
+       nr_sectors >>= ilog2(sdp->sector_size) - 9;
+
+       rq->__data_len = sdp->sector_size;
+       rq->timeout = SD_WRITE_SAME_TIMEOUT;
+       memset(rq->cmd, 0, rq->cmd_len);
+
+       if (sdkp->ws16 || sector > 0xffffffff || nr_sectors > 0xffff) {
+               rq->cmd_len = 16;
+               rq->cmd[0] = WRITE_SAME_16;
+               put_unaligned_be64(sector, &rq->cmd[2]);
+               put_unaligned_be32(nr_sectors, &rq->cmd[10]);
+       } else {
+               rq->cmd_len = 10;
+               rq->cmd[0] = WRITE_SAME;
+               put_unaligned_be32(sector, &rq->cmd[2]);
+               put_unaligned_be16(nr_sectors, &rq->cmd[7]);
+       }
+
+       ret = scsi_setup_blk_pc_cmnd(sdp, rq);
+       rq->__data_len = nr_bytes;
+
+       return ret;
+}
+
 static int scsi_setup_flush_cmnd(struct scsi_device *sdp, struct request *rq)
 {
        rq->timeout = SD_FLUSH_TIMEOUT;
@@ -712,7 +833,10 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq)
         * block PC requests to make life easier.
         */
        if (rq->cmd_flags & REQ_DISCARD) {
-               ret = scsi_setup_discard_cmnd(sdp, rq);
+               ret = sd_setup_discard_cmnd(sdp, rq);
+               goto out;
+       } else if (rq->cmd_flags & REQ_WRITE_SAME) {
+               ret = sd_setup_write_same_cmnd(sdp, rq);
                goto out;
        } else if (rq->cmd_flags & REQ_FLUSH) {
                ret = scsi_setup_flush_cmnd(sdp, rq);
@@ -1482,12 +1606,21 @@ static int sd_done(struct scsi_cmnd *SCpnt)
        unsigned int good_bytes = result ? 0 : scsi_bufflen(SCpnt);
        struct scsi_sense_hdr sshdr;
        struct scsi_disk *sdkp = scsi_disk(SCpnt->request->rq_disk);
+       struct request *req = SCpnt->request;
        int sense_valid = 0;
        int sense_deferred = 0;
        unsigned char op = SCpnt->cmnd[0];
+       unsigned char unmap = SCpnt->cmnd[1] & 8;
 
-       if ((SCpnt->request->cmd_flags & REQ_DISCARD) && !result)
-               scsi_set_resid(SCpnt, 0);
+       if (req->cmd_flags & REQ_DISCARD || req->cmd_flags & REQ_WRITE_SAME) {
+               if (!result) {
+                       good_bytes = blk_rq_bytes(req);
+                       scsi_set_resid(SCpnt, 0);
+               } else {
+                       good_bytes = 0;
+                       scsi_set_resid(SCpnt, blk_rq_bytes(req));
+               }
+       }
 
        if (result) {
                sense_valid = scsi_command_normalize_sense(SCpnt, &sshdr);
@@ -1536,9 +1669,25 @@ static int sd_done(struct scsi_cmnd *SCpnt)
                if (sshdr.asc == 0x10)  /* DIX: Host detected corruption */
                        good_bytes = sd_completed_bytes(SCpnt);
                /* INVALID COMMAND OPCODE or INVALID FIELD IN CDB */
-               if ((sshdr.asc == 0x20 || sshdr.asc == 0x24) &&
-                   (op == UNMAP || op == WRITE_SAME_16 || op == WRITE_SAME))
-                       sd_config_discard(sdkp, SD_LBP_DISABLE);
+               if (sshdr.asc == 0x20 || sshdr.asc == 0x24) {
+                       switch (op) {
+                       case UNMAP:
+                               sd_config_discard(sdkp, SD_LBP_DISABLE);
+                               break;
+                       case WRITE_SAME_16:
+                       case WRITE_SAME:
+                               if (unmap)
+                                       sd_config_discard(sdkp, SD_LBP_DISABLE);
+                               else {
+                                       sdkp->device->no_write_same = 1;
+                                       sd_config_write_same(sdkp);
+
+                                       good_bytes = 0;
+                                       req->__data_len = blk_rq_bytes(req);
+                                       req->cmd_flags |= REQ_QUIET;
+                               }
+                       }
+               }
                break;
        default:
                break;
@@ -2374,9 +2523,7 @@ static void sd_read_block_limits(struct scsi_disk *sdkp)
        if (buffer[3] == 0x3c) {
                unsigned int lba_count, desc_count;
 
-               sdkp->max_ws_blocks =
-                       (u32) min_not_zero(get_unaligned_be64(&buffer[36]),
-                                          (u64)0xffffffff);
+               sdkp->max_ws_blocks = (u32)get_unaligned_be64(&buffer[36]);
 
                if (!sdkp->lbpme)
                        goto out;
@@ -2469,6 +2616,13 @@ static void sd_read_block_provisioning(struct scsi_disk *sdkp)
        kfree(buffer);
 }
 
+static void sd_read_write_same(struct scsi_disk *sdkp, unsigned char *buffer)
+{
+       if (scsi_report_opcode(sdkp->device, buffer, SD_BUF_SIZE,
+                              WRITE_SAME_16))
+               sdkp->ws16 = 1;
+}
+
 static int sd_try_extended_inquiry(struct scsi_device *sdp)
 {
        /*
@@ -2528,6 +2682,7 @@ static int sd_revalidate_disk(struct gendisk *disk)
                sd_read_write_protect_flag(sdkp, buffer);
                sd_read_cache_type(sdkp, buffer);
                sd_read_app_tag_own(sdkp, buffer);
+               sd_read_write_same(sdkp, buffer);
        }
 
        sdkp->first_scan = 0;
@@ -2545,6 +2700,7 @@ static int sd_revalidate_disk(struct gendisk *disk)
        blk_queue_flush(sdkp->disk->queue, flush);
 
        set_capacity(disk, sdkp->capacity);
+       sd_config_write_same(sdkp);
        kfree(buffer);
 
  out:
index 47c52a6d733c0f757b4ef42236e89fba172b857c..74a1e4ca5401f9a58e6e705bb2fc8a99fcd04a0f 100644 (file)
@@ -14,6 +14,7 @@
 #define SD_TIMEOUT             (30 * HZ)
 #define SD_MOD_TIMEOUT         (75 * HZ)
 #define SD_FLUSH_TIMEOUT       (60 * HZ)
+#define SD_WRITE_SAME_TIMEOUT  (120 * HZ)
 
 /*
  * Number of allowed retries
@@ -38,6 +39,11 @@ enum {
        SD_MEMPOOL_SIZE = 2,    /* CDB pool size */
 };
 
+enum {
+       SD_MAX_WS10_BLOCKS = 0xffff,
+       SD_MAX_WS16_BLOCKS = 0x7fffff,
+};
+
 enum {
        SD_LBP_FULL = 0,        /* Full logical block provisioning */
        SD_LBP_UNMAP,           /* Use UNMAP command */
@@ -77,6 +83,7 @@ struct scsi_disk {
        unsigned        lbpws : 1;
        unsigned        lbpws10 : 1;
        unsigned        lbpvpd : 1;
+       unsigned        ws16 : 1;
 };
 #define to_scsi_disk(obj) container_of(obj,struct scsi_disk,dev)
 
index edf1360ab09e5be8311b7338a28d75ce8bbb46a3..86dd04d6bc873dfa30f0bab1148bd863aac818fc 100644 (file)
@@ -323,6 +323,7 @@ static int mxs_spi_txrx_dma(struct mxs_spi *spi, int cs,
        if (!ret) {
                dev_err(ssp->dev, "DMA transfer timeout\n");
                ret = -ETIMEDOUT;
+               dmaengine_terminate_all(ssp->dmach);
                goto err_vmalloc;
        }
 
@@ -480,7 +481,7 @@ static int mxs_spi_transfer_one(struct spi_master *master,
                first = last = 0;
        }
 
-       m->status = 0;
+       m->status = status;
        spi_finalize_current_message(master);
 
        return status;
index 919464102d33afb2d493ace07c81c80403d1d51d..a1db91a99b89a670cb7979c5fd758c90796aa2a9 100644 (file)
@@ -2186,8 +2186,6 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
        printk(KERN_INFO "pl022: mapped registers from 0x%08x to %p\n",
               adev->res.start, pl022->virtbase);
 
-       pm_runtime_resume(dev);
-
        pl022->clk = devm_clk_get(&adev->dev, NULL);
        if (IS_ERR(pl022->clk)) {
                status = PTR_ERR(pl022->clk);
@@ -2292,7 +2290,6 @@ pl022_remove(struct amba_device *adev)
 
        clk_disable(pl022->clk);
        clk_unprepare(pl022->clk);
-       pm_runtime_disable(&adev->dev);
        amba_release_regions(adev);
        tasklet_disable(&pl022->pump_transfers);
        spi_unregister_master(pl022->master);
index 4894bde4bbffea3f65d7ff30db4277c92ab79587..30faf6d4ab9135c84ecd8f359626ddd75e896b60 100644 (file)
@@ -147,8 +147,6 @@ struct rspi_data {
        unsigned char spsr;
 
        /* for dmaengine */
-       struct sh_dmae_slave dma_tx;
-       struct sh_dmae_slave dma_rx;
        struct dma_chan *chan_tx;
        struct dma_chan *chan_rx;
        int irq;
@@ -663,20 +661,16 @@ static irqreturn_t rspi_irq(int irq, void *_sr)
        return ret;
 }
 
-static bool rspi_filter(struct dma_chan *chan, void *filter_param)
-{
-       chan->private = filter_param;
-       return true;
-}
-
-static void __devinit rspi_request_dma(struct rspi_data *rspi,
-                                      struct platform_device *pdev)
+static int __devinit rspi_request_dma(struct rspi_data *rspi,
+                                     struct platform_device *pdev)
 {
        struct rspi_plat_data *rspi_pd = pdev->dev.platform_data;
        dma_cap_mask_t mask;
+       struct dma_slave_config cfg;
+       int ret;
 
        if (!rspi_pd)
-               return;
+               return 0;       /* The driver assumes no error. */
 
        rspi->dma_width_16bit = rspi_pd->dma_width_16bit;
 
@@ -684,21 +678,35 @@ static void __devinit rspi_request_dma(struct rspi_data *rspi,
        if (rspi_pd->dma_rx_id && rspi_pd->dma_tx_id) {
                dma_cap_zero(mask);
                dma_cap_set(DMA_SLAVE, mask);
-               rspi->dma_rx.slave_id = rspi_pd->dma_rx_id;
-               rspi->chan_rx = dma_request_channel(mask, rspi_filter,
-                                                   &rspi->dma_rx);
-               if (rspi->chan_rx)
-                       dev_info(&pdev->dev, "Use DMA when rx.\n");
+               rspi->chan_rx = dma_request_channel(mask, shdma_chan_filter,
+                                                   (void *)rspi_pd->dma_rx_id);
+               if (rspi->chan_rx) {
+                       cfg.slave_id = rspi_pd->dma_rx_id;
+                       cfg.direction = DMA_DEV_TO_MEM;
+                       ret = dmaengine_slave_config(rspi->chan_rx, &cfg);
+                       if (!ret)
+                               dev_info(&pdev->dev, "Use DMA when rx.\n");
+                       else
+                               return ret;
+               }
        }
        if (rspi_pd->dma_tx_id) {
                dma_cap_zero(mask);
                dma_cap_set(DMA_SLAVE, mask);
-               rspi->dma_tx.slave_id = rspi_pd->dma_tx_id;
-               rspi->chan_tx = dma_request_channel(mask, rspi_filter,
-                                                   &rspi->dma_tx);
-               if (rspi->chan_tx)
-                       dev_info(&pdev->dev, "Use DMA when tx\n");
+               rspi->chan_tx = dma_request_channel(mask, shdma_chan_filter,
+                                                   (void *)rspi_pd->dma_tx_id);
+               if (rspi->chan_tx) {
+                       cfg.slave_id = rspi_pd->dma_tx_id;
+                       cfg.direction = DMA_MEM_TO_DEV;
+                       ret = dmaengine_slave_config(rspi->chan_tx, &cfg);
+                       if (!ret)
+                               dev_info(&pdev->dev, "Use DMA when tx\n");
+                       else
+                               return ret;
+               }
        }
+
+       return 0;
 }
 
 static void __devexit rspi_release_dma(struct rspi_data *rspi)
@@ -788,7 +796,11 @@ static int __devinit rspi_probe(struct platform_device *pdev)
        }
 
        rspi->irq = irq;
-       rspi_request_dma(rspi, pdev);
+       ret = rspi_request_dma(rspi, pdev);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "rspi_request_dma failed.\n");
+               goto error4;
+       }
 
        ret = spi_register_master(master);
        if (ret < 0) {
index f2ffd963f1c348e3986f761b1d2d2b7b75b361e2..d0cafd6371996c75e3ee094b2be3168ad14d38b7 100644 (file)
@@ -51,12 +51,10 @@ enum android_alarm_return_flags {
 #define ANDROID_ALARM_WAIT                  _IO('a', 1)
 
 #define ALARM_IOW(c, type, size)            _IOW('a', (c) | ((type) << 4), size)
-#define ALARM_IOR(c, type, size)            _IOR('a', (c) | ((type) << 4), size)
-
 /* Set alarm */
 #define ANDROID_ALARM_SET(type)             ALARM_IOW(2, type, struct timespec)
 #define ANDROID_ALARM_SET_AND_WAIT(type)    ALARM_IOW(3, type, struct timespec)
-#define ANDROID_ALARM_GET_TIME(type)        ALARM_IOR(4, type, struct timespec)
+#define ANDROID_ALARM_GET_TIME(type)        ALARM_IOW(4, type, struct timespec)
 #define ANDROID_ALARM_SET_RTC               _IOW('a', 5, struct timespec)
 #define ANDROID_ALARM_BASE_CMD(cmd)         (cmd & ~(_IOC(0, 0, 0xf0, 0)))
 #define ANDROID_ALARM_IOCTL_TO_TYPE(cmd)    (_IOC_NR(cmd) >> 4)
index 7b0ba92e7e46730d1d5c72137c9f1b2b9ddc3201..5d4610babd8a6a48e4d5ac161a04db7322ad2892 100644 (file)
@@ -567,7 +567,7 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate,
                page = &proc->pages[(page_addr - proc->buffer) / PAGE_SIZE];
 
                BUG_ON(*page);
-               *page = alloc_page(GFP_KERNEL | __GFP_ZERO);
+               *page = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO);
                if (*page == NULL) {
                        pr_err("binder: %d: binder_alloc_buf failed "
                               "for page at %p\n", proc->pid, page_addr);
@@ -2419,14 +2419,38 @@ static void binder_release_work(struct list_head *list)
                        struct binder_transaction *t;
 
                        t = container_of(w, struct binder_transaction, work);
-                       if (t->buffer->target_node && !(t->flags & TF_ONE_WAY))
+                       if (t->buffer->target_node &&
+                           !(t->flags & TF_ONE_WAY)) {
                                binder_send_failed_reply(t, BR_DEAD_REPLY);
+                       } else {
+                               binder_debug(BINDER_DEBUG_DEAD_TRANSACTION,
+                                       "binder: undelivered transaction %d\n",
+                                       t->debug_id);
+                               t->buffer->transaction = NULL;
+                               kfree(t);
+                               binder_stats_deleted(BINDER_STAT_TRANSACTION);
+                       }
                } break;
                case BINDER_WORK_TRANSACTION_COMPLETE: {
+                       binder_debug(BINDER_DEBUG_DEAD_TRANSACTION,
+                               "binder: undelivered TRANSACTION_COMPLETE\n");
                        kfree(w);
                        binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
                } break;
+               case BINDER_WORK_DEAD_BINDER_AND_CLEAR:
+               case BINDER_WORK_CLEAR_DEATH_NOTIFICATION: {
+                       struct binder_ref_death *death;
+
+                       death = container_of(w, struct binder_ref_death, work);
+                       binder_debug(BINDER_DEBUG_DEAD_TRANSACTION,
+                               "binder: undelivered death notification, %p\n",
+                               death->cookie);
+                       kfree(death);
+                       binder_stats_deleted(BINDER_STAT_DEATH);
+               } break;
                default:
+                       pr_err("binder: unexpected work type, %d, not freed\n",
+                              w->type);
                        break;
                }
        }
@@ -2899,6 +2923,7 @@ static void binder_deferred_release(struct binder_proc *proc)
                nodes++;
                rb_erase(&node->rb_node, &proc->nodes);
                list_del_init(&node->work.entry);
+               binder_release_work(&node->async_todo);
                if (hlist_empty(&node->refs)) {
                        kfree(node);
                        binder_stats_deleted(BINDER_STAT_NODE);
@@ -2937,6 +2962,7 @@ static void binder_deferred_release(struct binder_proc *proc)
                binder_delete_ref(ref);
        }
        binder_release_work(&proc->todo);
+       binder_release_work(&proc->delivered_death);
        buffers = 0;
 
        while ((n = rb_first(&proc->allocated_buffers))) {
index 7dff3c01dc29ef3286d5559065a1c2c9e52819d5..d00aff6671df961c475f41bb3bb3141b41d5f83f 100644 (file)
@@ -289,6 +289,8 @@ static void pci_8255_detach(struct comedi_device *dev)
        struct comedi_subdevice *s;
        int i;
 
+       if (!board || !devpriv)
+               return;
        if (dev->subdevices) {
                for (i = 0; i < board->n_8255; i++) {
                        s = &dev->subdevices[i];
index 08f305210a695d57e1ef2c8181ec3d47b2f62c53..29eb52d11d2f7b3ef6b2a7f1372e3b99f95862fc 100644 (file)
@@ -1410,6 +1410,8 @@ static void dio200_detach(struct comedi_device *dev)
        const struct dio200_layout_struct *layout;
        unsigned n;
 
+       if (!thisboard)
+               return;
        if (dev->irq)
                free_irq(dev->irq, dev);
        if (dev->subdevices) {
index eacb5e4735d7df0a3ccf7e794bb0744ab936f71a..4e4f3c15df87e9db99528806b15ba48c54a558c2 100644 (file)
@@ -573,9 +573,10 @@ static int __devinit pc236_attach_pci(struct comedi_device *dev,
 static void pc236_detach(struct comedi_device *dev)
 {
        const struct pc236_board *thisboard = comedi_board(dev);
-       struct pc236_private *devpriv = dev->private;
 
-       if (devpriv)
+       if (!thisboard)
+               return;
+       if (dev->iobase)
                pc236_intr_disable(dev);
        if (dev->irq)
                free_irq(dev->irq, dev);
index 60830ccfb903f48fc9720490040d59bc113f0c5c..d0a4c441228b405d4459f70cb264b13717c26161 100644 (file)
@@ -323,6 +323,8 @@ static void pc263_detach(struct comedi_device *dev)
 {
        const struct pc263_board *thisboard = comedi_board(dev);
 
+       if (!thisboard)
+               return;
        if (is_isa_board(thisboard)) {
                if (dev->iobase)
                        release_region(dev->iobase, PC263_IO_SIZE);
index 5fd21fa6c1c76d25f910c41ca26ecec86b8894e8..c304528cfb1341293255f097620c1d1f8877c7fe 100644 (file)
@@ -846,6 +846,8 @@ static void __maybe_unused das08_detach(struct comedi_device *dev)
 {
        const struct das08_board_struct *thisboard = comedi_board(dev);
 
+       if (!thisboard)
+               return;
        das08_common_detach(dev);
        if (is_isa_board(thisboard)) {
                if (dev->iobase)
index 2ba0ade45c6484b940b1ed9559a4bd85f96e5a84..68d7c6a5db7dac901fd2f208f923106930c3553f 100644 (file)
@@ -95,7 +95,7 @@ static int daq700_dio_insn_bits(struct comedi_device *dev,
        }
 
        data[1] = s->state & 0xff;
-       data[1] |= inb(dev->iobase + DIO_R);
+       data[1] |= inb(dev->iobase + DIO_R) << 8;
 
        return insn->n;
 }
index 28b91a6c378908ba2f30b01b88a11d819b3dd9f7..b5a19a0863fbb8ba3e7fe2842f66b0611992b054 100644 (file)
@@ -772,6 +772,8 @@ void labpc_common_detach(struct comedi_device *dev)
 {
        struct comedi_subdevice *s;
 
+       if (!thisboard)
+               return;
        if (dev->subdevices) {
                s = &dev->subdevices[2];
                subdev_8255_cleanup(dev, s);
index 8e37d6e04277663d7b7d135a5dd653f050a16785..b12ca68cd9e4f286191349ba148aabcf3b9d6e56 100644 (file)
@@ -310,30 +310,32 @@ static int adis16201_read_raw(struct iio_dev *indio_dev,
        case IIO_CHAN_INFO_SCALE:
                switch (chan->type) {
                case IIO_VOLTAGE:
-                       *val = 0;
-                       if (chan->channel == 0)
-                               *val2 = 1220;
-                       else
-                               *val2 = 610;
+                       if (chan->channel == 0) {
+                               *val = 1;
+                               *val2 = 220000; /* 1.22 mV */
+                       } else {
+                               *val = 0;
+                               *val2 = 610000; /* 0.610 mV */
+                       }
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_TEMP:
-                       *val = 0;
-                       *val2 = -470000;
+                       *val = -470; /* 0.47 C */
+                       *val2 = 0;
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_ACCEL:
                        *val = 0;
-                       *val2 = 462500;
-                       return IIO_VAL_INT_PLUS_MICRO;
+                       *val2 = IIO_G_TO_M_S_2(462400); /* 0.4624 mg */
+                       return IIO_VAL_INT_PLUS_NANO;
                case IIO_INCLI:
                        *val = 0;
-                       *val2 = 100000;
+                       *val2 = 100000; /* 0.1 degree */
                        return IIO_VAL_INT_PLUS_MICRO;
                default:
                        return -EINVAL;
                }
                break;
        case IIO_CHAN_INFO_OFFSET:
-               *val = 25;
+               *val = 25000 / -470 - 1278; /* 25 C = 1278 */
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_CALIBBIAS:
                switch (chan->type) {
index 002fa9dfc3756ee5052c9039dd7bb2af48473168..e7b3441115aee59861571a40ebecaaf45a4160e7 100644 (file)
@@ -316,25 +316,27 @@ static int adis16203_read_raw(struct iio_dev *indio_dev,
        case IIO_CHAN_INFO_SCALE:
                switch (chan->type) {
                case IIO_VOLTAGE:
-                       *val = 0;
-                       if (chan->channel == 0)
-                               *val2 = 1220;
-                       else
-                               *val2 = 610;
+                       if (chan->channel == 0) {
+                               *val = 1;
+                               *val2 = 220000; /* 1.22 mV */
+                       } else {
+                               *val = 0;
+                               *val2 = 610000; /* 0.61 mV */
+                       }
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_TEMP:
-                       *val = 0;
-                       *val2 = -470000;
+                       *val = -470; /* -0.47 C */
+                       *val2 = 0;
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_INCLI:
                        *val = 0;
-                       *val2 = 25000;
+                       *val2 = 25000; /* 0.025 degree */
                        return IIO_VAL_INT_PLUS_MICRO;
                default:
                        return -EINVAL;
                }
        case IIO_CHAN_INFO_OFFSET:
-               *val = 25;
+               *val = 25000 / -470 - 1278; /* 25 C = 1278 */
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_CALIBBIAS:
                bits = 14;
index 05bdb7c2c8e3f100953c8b0fde872ae367f26c45..c6234c2f46aabdac362921e903fcdfa955f4a8a8 100644 (file)
@@ -317,26 +317,28 @@ static int adis16204_read_raw(struct iio_dev *indio_dev,
        case IIO_CHAN_INFO_SCALE:
                switch (chan->type) {
                case IIO_VOLTAGE:
-                       *val = 0;
-                       if (chan->channel == 0)
-                               *val2 = 1220;
-                       else
-                               *val2 = 610;
+                       if (chan->channel == 0) {
+                               *val = 1;
+                               *val2 = 220000; /* 1.22 mV */
+                       } else {
+                               *val = 0;
+                               *val2 = 610000; /* 0.61 mV */
+                       }
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_TEMP:
-                       *val = 0;
-                       *val2 = -470000;
+                       *val = -470; /* 0.47 C */
+                       *val2 = 0;
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_ACCEL:
                        *val = 0;
                        switch (chan->channel2) {
                        case IIO_MOD_X:
                        case IIO_MOD_ROOT_SUM_SQUARED_X_Y:
-                               *val2 = 17125;
+                               *val2 = IIO_G_TO_M_S_2(17125); /* 17.125 mg */
                                break;
                        case IIO_MOD_Y:
                        case IIO_MOD_Z:
-                               *val2 = 8407;
+                               *val2 = IIO_G_TO_M_S_2(8407); /* 8.407 mg */
                                break;
                        }
                        return IIO_VAL_INT_PLUS_MICRO;
@@ -345,7 +347,7 @@ static int adis16204_read_raw(struct iio_dev *indio_dev,
                }
                break;
        case IIO_CHAN_INFO_OFFSET:
-               *val = 25;
+               *val = 25000 / -470 - 1278; /* 25 C = 1278 */
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_CALIBBIAS:
        case IIO_CHAN_INFO_PEAK:
index b7333bfe0b2f1312a51548a731e73f2f41bd36ba..7ee974b45d7d3a3eb354ef073a1094c9183f26c3 100644 (file)
@@ -343,28 +343,29 @@ static int adis16209_read_raw(struct iio_dev *indio_dev,
                case IIO_VOLTAGE:
                        *val = 0;
                        if (chan->channel == 0)
-                               *val2 = 305180;
+                               *val2 = 305180; /* 0.30518 mV */
                        else
-                               *val2 = 610500;
+                               *val2 = 610500; /* 0.6105 mV */
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_TEMP:
-                       *val = 0;
-                       *val2 = -470000;
+                       *val = -470; /* -0.47 C */
+                       *val2 = 0;
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_ACCEL:
                        *val = 0;
-                       *val2 = 2394;
-                       return IIO_VAL_INT_PLUS_MICRO;
+                       *val2 = IIO_G_TO_M_S_2(244140); /* 0.244140 mg */
+                       return IIO_VAL_INT_PLUS_NANO;
                case IIO_INCLI:
+               case IIO_ROT:
                        *val = 0;
-                       *val2 = 436;
+                       *val2 = 25000; /* 0.025 degree */
                        return IIO_VAL_INT_PLUS_MICRO;
                default:
                        return -EINVAL;
                }
                break;
        case IIO_CHAN_INFO_OFFSET:
-               *val = 25;
+               *val = 25000 / -470 - 0x4FE; /* 25 C = 0x4FE */
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_CALIBBIAS:
                switch (chan->type) {
@@ -491,6 +492,7 @@ static const struct iio_chan_spec adis16209_channels[] = {
                .modified = 1,
                .channel2 = IIO_MOD_X,
                .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
+               IIO_CHAN_INFO_SCALE_SHARED_BIT,
                .address = rot,
                .scan_index = ADIS16209_SCAN_ROT,
                .scan_type = {
index c755089c711715802ce6e90818a35bae41941acb..eaadd9df3f78360c111b54b05ac3b93a96ba7cb7 100644 (file)
@@ -486,7 +486,7 @@ static int adis16220_read_raw(struct iio_dev *indio_dev,
                break;
        case IIO_CHAN_INFO_OFFSET:
                if (chan->type == IIO_TEMP) {
-                       *val = 25;
+                       *val = 25000 / -470 - 1278; /* 25 C = 1278 */
                        return IIO_VAL_INT;
                }
                addrind = 1;
@@ -495,19 +495,22 @@ static int adis16220_read_raw(struct iio_dev *indio_dev,
                addrind = 2;
                break;
        case IIO_CHAN_INFO_SCALE:
-               *val = 0;
                switch (chan->type) {
                case IIO_TEMP:
-                       *val2 = -470000;
+                       *val = -470; /* -0.47 C */
+                       *val2 = 0;
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_ACCEL:
-                       *val2 = 1887042;
+                       *val2 = IIO_G_TO_M_S_2(19073); /* 19.073 g */
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_VOLTAGE:
-                       if (chan->channel == 0)
-                               *val2 = 0012221;
-                       else /* Should really be dependent on VDD */
-                               *val2 = 305;
+                       if (chan->channel == 0) {
+                               *val = 1;
+                               *val2 = 220700; /* 1.2207 mV */
+                       } else {
+                               /* Should really be dependent on VDD */
+                               *val2 = 305180; /* 305.18 uV */
+                       }
                        return IIO_VAL_INT_PLUS_MICRO;
                default:
                        return -EINVAL;
index 0fc26a49d681abbb4ece13156771e429db9aee2f..35e093973d5cb9028992682344f3dc9bba23be96 100644 (file)
@@ -373,30 +373,31 @@ static int adis16240_read_raw(struct iio_dev *indio_dev,
        case IIO_CHAN_INFO_SCALE:
                switch (chan->type) {
                case IIO_VOLTAGE:
-                       *val = 0;
-                       if (chan->channel == 0)
-                               *val2 = 4880;
-                       else
+                       if (chan->channel == 0) {
+                               *val = 4;
+                               *val2 = 880000; /* 4.88 mV */
+                               return IIO_VAL_INT_PLUS_MICRO;
+                       } else {
                                return -EINVAL;
-                       return IIO_VAL_INT_PLUS_MICRO;
+                       }
                case IIO_TEMP:
-                       *val = 0;
-                       *val2 = 244000;
+                       *val = 244; /* 0.244 C */
+                       *val2 = 0;
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_ACCEL:
                        *val = 0;
-                       *val2 = 504062;
+                       *val2 = IIO_G_TO_M_S_2(51400); /* 51.4 mg */
                        return IIO_VAL_INT_PLUS_MICRO;
                default:
                        return -EINVAL;
                }
                break;
        case IIO_CHAN_INFO_PEAK_SCALE:
-               *val = 6;
-               *val2 = 629295;
+               *val = 0;
+               *val2 = IIO_G_TO_M_S_2(51400); /* 51.4 mg */
                return IIO_VAL_INT_PLUS_MICRO;
        case IIO_CHAN_INFO_OFFSET:
-               *val = 25;
+               *val = 25000 / 244 - 0x133; /* 25 C = 0x133 */
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_CALIBBIAS:
                bits = 10;
index 9571c03aa4cc976346d17bcb27f41d4dc4319060..aa964a2d829016e25b918ede1418d25152a9a425 100644 (file)
@@ -498,28 +498,33 @@ static int adis16260_read_raw(struct iio_dev *indio_dev,
                switch (chan->type) {
                case IIO_ANGL_VEL:
                        *val = 0;
-                       if (spi_get_device_id(st->us)->driver_data)
-                               *val2 = 320;
-                       else
-                               *val2 = 1278;
+                       if (spi_get_device_id(st->us)->driver_data) {
+                               /* 0.01832 degree / sec */
+                               *val2 = IIO_DEGREE_TO_RAD(18320);
+                       } else {
+                               /* 0.07326 degree / sec */
+                               *val2 = IIO_DEGREE_TO_RAD(73260);
+                       }
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_VOLTAGE:
-                       *val = 0;
-                       if (chan->channel == 0)
-                               *val2 = 18315;
-                       else
-                               *val2 = 610500;
+                       if (chan->channel == 0) {
+                               *val = 1;
+                               *val2 = 831500; /* 1.8315 mV */
+                       } else {
+                               *val = 0;
+                               *val2 = 610500; /* 610.5 uV */
+                       }
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_TEMP:
-                       *val = 0;
-                       *val2 = 145300;
+                       *val = 145;
+                       *val2 = 300000; /* 0.1453 C */
                        return IIO_VAL_INT_PLUS_MICRO;
                default:
                        return -EINVAL;
                }
                break;
        case IIO_CHAN_INFO_OFFSET:
-               *val = 25;
+               *val = 250000 / 1453; /* 25 C = 0x00 */
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_CALIBBIAS:
                switch (chan->type) {
index d59d7ac856a9db8bb3c0bff7ccf1811d97917539..77c601da184603c6391cecc1b10d887cb38ffb70 100644 (file)
@@ -139,6 +139,8 @@ struct adis16400_chip_info {
        const long flags;
        unsigned int gyro_scale_micro;
        unsigned int accel_scale_micro;
+       int temp_scale_nano;
+       int temp_offset;
        unsigned long default_scan_mask;
 };
 
index b302c9ba271260e2f31476e51420af68fbbd28db..3144a7b1e1c4f6cd03f0b55780aa473603afa51e 100644 (file)
@@ -553,10 +553,13 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_VOLTAGE:
                        *val = 0;
-                       if (chan->channel == 0)
-                               *val2 = 2418;
-                       else
-                               *val2 = 806;
+                       if (chan->channel == 0) {
+                               *val = 2;
+                               *val2 = 418000; /* 2.418 mV */
+                       } else {
+                               *val = 0;
+                               *val2 = 805800; /* 805.8 uV */
+                       }
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_ACCEL:
                        *val = 0;
@@ -564,11 +567,11 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_MAGN:
                        *val = 0;
-                       *val2 = 500;
+                       *val2 = 500; /* 0.5 mgauss */
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_TEMP:
-                       *val = 0;
-                       *val2 = 140000;
+                       *val = st->variant->temp_scale_nano / 1000000;
+                       *val2 = (st->variant->temp_scale_nano % 1000000);
                        return IIO_VAL_INT_PLUS_MICRO;
                default:
                        return -EINVAL;
@@ -586,9 +589,8 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_OFFSET:
                /* currently only temperature */
-               *val = 198;
-               *val2 = 160000;
-               return IIO_VAL_INT_PLUS_MICRO;
+               *val = st->variant->temp_offset;
+               return IIO_VAL_INT;
        case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
                mutex_lock(&indio_dev->mlock);
                /* Need both the number of taps and the sampling frequency */
@@ -1035,7 +1037,7 @@ static const struct iio_chan_spec adis16334_channels[] = {
                .indexed = 1,
                .channel = 0,
                .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-               IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+               IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
                IIO_CHAN_INFO_SCALE_SHARED_BIT,
                .address = temp0,
                .scan_index = ADIS16400_SCAN_TEMP,
@@ -1058,8 +1060,10 @@ static struct adis16400_chip_info adis16400_chips[] = {
        [ADIS16300] = {
                .channels = adis16300_channels,
                .num_channels = ARRAY_SIZE(adis16300_channels),
-               .gyro_scale_micro = 873,
+               .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
                .accel_scale_micro = 5884,
+               .temp_scale_nano = 140000000, /* 0.14 C */
+               .temp_offset = 25000000 / 140000, /* 25 C = 0x00 */
                .default_scan_mask = (1 << ADIS16400_SCAN_SUPPLY) |
                (1 << ADIS16400_SCAN_GYRO_X) | (1 << ADIS16400_SCAN_ACC_X) |
                (1 << ADIS16400_SCAN_ACC_Y) | (1 << ADIS16400_SCAN_ACC_Z) |
@@ -1070,8 +1074,10 @@ static struct adis16400_chip_info adis16400_chips[] = {
        [ADIS16334] = {
                .channels = adis16334_channels,
                .num_channels = ARRAY_SIZE(adis16334_channels),
-               .gyro_scale_micro = 873,
-               .accel_scale_micro = 981,
+               .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
+               .accel_scale_micro = IIO_G_TO_M_S_2(1000), /* 1 mg */
+               .temp_scale_nano = 67850000, /* 0.06785 C */
+               .temp_offset = 25000000 / 67850, /* 25 C = 0x00 */
                .default_scan_mask = (1 << ADIS16400_SCAN_GYRO_X) |
                (1 << ADIS16400_SCAN_GYRO_Y) | (1 << ADIS16400_SCAN_GYRO_Z) |
                (1 << ADIS16400_SCAN_ACC_X) | (1 << ADIS16400_SCAN_ACC_Y) |
@@ -1080,8 +1086,10 @@ static struct adis16400_chip_info adis16400_chips[] = {
        [ADIS16350] = {
                .channels = adis16350_channels,
                .num_channels = ARRAY_SIZE(adis16350_channels),
-               .gyro_scale_micro = 872664,
-               .accel_scale_micro = 24732,
+               .gyro_scale_micro = IIO_DEGREE_TO_RAD(73260), /* 0.07326 deg/s */
+               .accel_scale_micro = IIO_G_TO_M_S_2(2522), /* 0.002522 g */
+               .temp_scale_nano = 145300000, /* 0.1453 C */
+               .temp_offset = 25000000 / 145300, /* 25 C = 0x00 */
                .default_scan_mask = 0x7FF,
                .flags = ADIS16400_NO_BURST,
        },
@@ -1090,8 +1098,10 @@ static struct adis16400_chip_info adis16400_chips[] = {
                .num_channels = ARRAY_SIZE(adis16350_channels),
                .flags = ADIS16400_HAS_PROD_ID,
                .product_id = 0x3FE8,
-               .gyro_scale_micro = 1279,
-               .accel_scale_micro = 24732,
+               .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
+               .accel_scale_micro = IIO_G_TO_M_S_2(3333), /* 3.333 mg */
+               .temp_scale_nano = 136000000, /* 0.136 C */
+               .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */
                .default_scan_mask = 0x7FF,
        },
        [ADIS16362] = {
@@ -1099,8 +1109,10 @@ static struct adis16400_chip_info adis16400_chips[] = {
                .num_channels = ARRAY_SIZE(adis16350_channels),
                .flags = ADIS16400_HAS_PROD_ID,
                .product_id = 0x3FEA,
-               .gyro_scale_micro = 1279,
-               .accel_scale_micro = 24732,
+               .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
+               .accel_scale_micro = IIO_G_TO_M_S_2(333), /* 0.333 mg */
+               .temp_scale_nano = 136000000, /* 0.136 C */
+               .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */
                .default_scan_mask = 0x7FF,
        },
        [ADIS16364] = {
@@ -1108,8 +1120,10 @@ static struct adis16400_chip_info adis16400_chips[] = {
                .num_channels = ARRAY_SIZE(adis16350_channels),
                .flags = ADIS16400_HAS_PROD_ID,
                .product_id = 0x3FEC,
-               .gyro_scale_micro = 1279,
-               .accel_scale_micro = 24732,
+               .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
+               .accel_scale_micro = IIO_G_TO_M_S_2(1000), /* 1 mg */
+               .temp_scale_nano = 136000000, /* 0.136 C */
+               .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */
                .default_scan_mask = 0x7FF,
        },
        [ADIS16365] = {
@@ -1117,8 +1131,10 @@ static struct adis16400_chip_info adis16400_chips[] = {
                .num_channels = ARRAY_SIZE(adis16350_channels),
                .flags = ADIS16400_HAS_PROD_ID,
                .product_id = 0x3FED,
-               .gyro_scale_micro = 1279,
-               .accel_scale_micro = 24732,
+               .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
+               .accel_scale_micro = IIO_G_TO_M_S_2(1000), /* 1 mg */
+               .temp_scale_nano = 136000000, /* 0.136 C */
+               .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */
                .default_scan_mask = 0x7FF,
        },
        [ADIS16400] = {
@@ -1126,9 +1142,11 @@ static struct adis16400_chip_info adis16400_chips[] = {
                .num_channels = ARRAY_SIZE(adis16400_channels),
                .flags = ADIS16400_HAS_PROD_ID,
                .product_id = 0x4015,
-               .gyro_scale_micro = 873,
-               .accel_scale_micro = 32656,
+               .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
+               .accel_scale_micro = IIO_G_TO_M_S_2(3333), /* 3.333 mg */
                .default_scan_mask = 0xFFF,
+               .temp_scale_nano = 140000000, /* 0.14 C */
+               .temp_offset = 25000000 / 140000, /* 25 C = 0x00 */
        }
 };
 
index bb8aa70281cd9da9aa55edf89850b08f1b848a2c..46d6657280b8490799f818123166827771d22615 100644 (file)
@@ -12,6 +12,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/slab.h>
 #include "tpci200.h"
 
 static u16 tpci200_status_timeout[] = {
index 3434e6ec01426677ff576de960ffbf65440af8d6..66e2c2f8a239964c22f3fe18dbd8d6a644b95013 100644 (file)
@@ -246,7 +246,7 @@ static int omap_gem_attach_pages(struct drm_gem_object *obj)
         * DSS, GPU, etc. are not cache coherent:
         */
        if (omap_obj->flags & (OMAP_BO_WC|OMAP_BO_UNCACHED)) {
-               addrs = kmalloc(npages * sizeof(addrs), GFP_KERNEL);
+               addrs = kmalloc(npages * sizeof(*addrs), GFP_KERNEL);
                if (!addrs) {
                        ret = -ENOMEM;
                        goto free_pages;
@@ -257,7 +257,7 @@ static int omap_gem_attach_pages(struct drm_gem_object *obj)
                                        0, PAGE_SIZE, DMA_BIDIRECTIONAL);
                }
        } else {
-               addrs = kzalloc(npages * sizeof(addrs), GFP_KERNEL);
+               addrs = kzalloc(npages * sizeof(*addrs), GFP_KERNEL);
                if (!addrs) {
                        ret = -ENOMEM;
                        goto free_pages;
index 843c54101438fa1aa30aafe564016d45aa3ba10d..3abf6619dace58319beee2be2fba640d02f059d2 100644 (file)
@@ -18,6 +18,7 @@ config ZCACHE2
 config RAMSTER
        bool "Cross-machine RAM capacity sharing, aka peer-to-peer tmem"
        depends on CONFIGFS_FS=y && SYSFS=y && !HIGHMEM && ZCACHE2=y
+       depends on NET
        # must ensure struct page is 8-byte aligned
        select HAVE_ALIGNED_STRUCT_PAGE if !64_BIT
        default n
index 066a3ceec65e92fccb725401e41e410e52d7ee1a..f619fb3c56d298334a615eb1b34203ccd1e5f5d3 100644 (file)
@@ -126,7 +126,8 @@ static int mem_map_vmalloc(struct bridge_dev_context *dev_context,
                                  u32 ul_num_bytes,
                                  struct hw_mmu_map_attrs_t *hw_attrs);
 
-bool wait_for_start(struct bridge_dev_context *dev_context, u32 dw_sync_addr);
+bool wait_for_start(struct bridge_dev_context *dev_context,
+                       void __iomem *sync_addr);
 
 /*  ----------------------------------- Globals */
 
@@ -363,10 +364,11 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt,
 {
        int status = 0;
        struct bridge_dev_context *dev_context = dev_ctxt;
-       u32 dw_sync_addr = 0;
+       void __iomem *sync_addr;
        u32 ul_shm_base;        /* Gpp Phys SM base addr(byte) */
        u32 ul_shm_base_virt;   /* Dsp Virt SM base addr */
        u32 ul_tlb_base_virt;   /* Base of MMU TLB entry */
+       u32 shm_sync_pa;
        /* Offset of shm_base_virt from tlb_base_virt */
        u32 ul_shm_offset_virt;
        s32 entry_ndx;
@@ -397,15 +399,22 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt,
        /* Kernel logical address */
        ul_shm_base = dev_context->atlb_entry[0].gpp_va + ul_shm_offset_virt;
 
+       /* SHM physical sync address */
+       shm_sync_pa = dev_context->atlb_entry[0].gpp_pa + ul_shm_offset_virt +
+                       SHMSYNCOFFSET;
+
        /* 2nd wd is used as sync field */
-       dw_sync_addr = ul_shm_base + SHMSYNCOFFSET;
+       sync_addr = ioremap(shm_sync_pa, SZ_32);
+       if (!sync_addr)
+               return -ENOMEM;
+
        /* Write a signature into the shm base + offset; this will
         * get cleared when the DSP program starts. */
        if ((ul_shm_base_virt == 0) || (ul_shm_base == 0)) {
                pr_err("%s: Illegal SM base\n", __func__);
                status = -EPERM;
        } else
-               __raw_writel(0xffffffff, dw_sync_addr);
+               __raw_writel(0xffffffff, sync_addr);
 
        if (!status) {
                resources = dev_context->resources;
@@ -419,8 +428,10 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt,
                         * function is made available.
                         */
                        void __iomem *ctrl = ioremap(0x48002000, SZ_4K);
-                       if (!ctrl)
+                       if (!ctrl) {
+                               iounmap(sync_addr);
                                return -ENOMEM;
+                       }
 
                        (*pdata->dsp_prm_rmw_bits)(OMAP3430_RST1_IVA2_MASK,
                                        OMAP3430_RST1_IVA2_MASK, OMAP3430_IVA2_MOD,
@@ -588,15 +599,15 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt,
                (*pdata->dsp_prm_rmw_bits)(OMAP3430_RST1_IVA2_MASK, 0,
                                        OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL);
 
-               dev_dbg(bridge, "Waiting for Sync @ 0x%x\n", dw_sync_addr);
+               dev_dbg(bridge, "Waiting for Sync @ 0x%x\n", *(u32 *)sync_addr);
                dev_dbg(bridge, "DSP c_int00 Address =  0x%x\n", dsp_addr);
                if (dsp_debug)
-                       while (__raw_readw(dw_sync_addr))
+                       while (__raw_readw(sync_addr))
                                ;
 
                /* Wait for DSP to clear word in shared memory */
                /* Read the Location */
-               if (!wait_for_start(dev_context, dw_sync_addr))
+               if (!wait_for_start(dev_context, sync_addr))
                        status = -ETIMEDOUT;
 
                dev_get_symbol(dev_context->dev_obj, "_WDT_enable", &wdt_en);
@@ -612,7 +623,7 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt,
                        /* Write the synchronization bit to indicate the
                         * completion of OPP table update to DSP
                         */
-                       __raw_writel(0XCAFECAFE, dw_sync_addr);
+                       __raw_writel(0XCAFECAFE, sync_addr);
 
                        /* update board state */
                        dev_context->brd_state = BRD_RUNNING;
@@ -621,6 +632,9 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt,
                        dev_context->brd_state = BRD_UNKNOWN;
                }
        }
+
+       iounmap(sync_addr);
+
        return status;
 }
 
@@ -1796,12 +1810,13 @@ static int mem_map_vmalloc(struct bridge_dev_context *dev_context,
  *  ======== wait_for_start ========
  *      Wait for the singal from DSP that it has started, or time out.
  */
-bool wait_for_start(struct bridge_dev_context *dev_context, u32 dw_sync_addr)
+bool wait_for_start(struct bridge_dev_context *dev_context,
+                       void __iomem *sync_addr)
 {
        u16 timeout = TIHELEN_ACKTIMEOUT;
 
        /*  Wait for response from board */
-       while (__raw_readw(dw_sync_addr) && --timeout)
+       while (__raw_readw(sync_addr) && --timeout)
                udelay(10);
 
        /*  If timed out: return false */
index 71cb822936499fb23b82f19053337a5159307c87..50244a474178610b6f0271b88dbb6479e21e03ac 100644 (file)
@@ -47,38 +47,13 @@ enum hw_mmu_page_size_t {
        HW_MMU_SUPERSECTION
 };
 
-/*
- * FUNCTION          : mmu_flush_entry
- *
- * INPUTS:
- *
- *       Identifier      : base_address
- *       Type          : const u32
- *       Description     : Base Address of instance of MMU module
- *
- * RETURNS:
- *
- *       Type          : hw_status
- *       Description     : 0            -- No errors occurred
- *                      RET_BAD_NULL_PARAM     -- A Pointer
- *                                             Parameter was set to NULL
- *
- * PURPOSE:          : Flush the TLB entry pointed by the
- *                     lock counter register
- *                     even if this entry is set protected
- *
- * METHOD:            : Check the Input parameter and Flush a
- *                      single entry in the TLB.
- */
-static hw_status mmu_flush_entry(const void __iomem *base_address);
-
 /*
  * FUNCTION          : mmu_set_cam_entry
  *
  * INPUTS:
  *
  *       Identifier      : base_address
- *       TypE          : const u32
+ *       Type           : void __iomem *
  *       Description     : Base Address of instance of MMU module
  *
  *       Identifier      : page_sz
@@ -112,7 +87,7 @@ static hw_status mmu_flush_entry(const void __iomem *base_address);
  *
  * METHOD:             : Check the Input parameters and set the CAM entry.
  */
-static hw_status mmu_set_cam_entry(const void __iomem *base_address,
+static hw_status mmu_set_cam_entry(void __iomem *base_address,
                                   const u32 page_sz,
                                   const u32 preserved_bit,
                                   const u32 valid_bit,
@@ -124,7 +99,7 @@ static hw_status mmu_set_cam_entry(const void __iomem *base_address,
  * INPUTS:
  *
  *       Identifier      : base_address
- *       Type          : const u32
+ *       Type           : void __iomem *
  *       Description     : Base Address of instance of MMU module
  *
  *       Identifier      : physical_addr
@@ -157,7 +132,7 @@ static hw_status mmu_set_cam_entry(const void __iomem *base_address,
  *
  * METHOD:            : Check the Input parameters and set the RAM entry.
  */
-static hw_status mmu_set_ram_entry(const void __iomem *base_address,
+static hw_status mmu_set_ram_entry(void __iomem *base_address,
                                   const u32 physical_addr,
                                   enum hw_endianism_t endianism,
                                   enum hw_element_size_t element_size,
@@ -165,7 +140,7 @@ static hw_status mmu_set_ram_entry(const void __iomem *base_address,
 
 /* HW FUNCTIONS */
 
-hw_status hw_mmu_enable(const void __iomem *base_address)
+hw_status hw_mmu_enable(void __iomem *base_address)
 {
        hw_status status = 0;
 
@@ -174,7 +149,7 @@ hw_status hw_mmu_enable(const void __iomem *base_address)
        return status;
 }
 
-hw_status hw_mmu_disable(const void __iomem *base_address)
+hw_status hw_mmu_disable(void __iomem *base_address)
 {
        hw_status status = 0;
 
@@ -183,7 +158,7 @@ hw_status hw_mmu_disable(const void __iomem *base_address)
        return status;
 }
 
-hw_status hw_mmu_num_locked_set(const void __iomem *base_address,
+hw_status hw_mmu_num_locked_set(void __iomem *base_address,
                                u32 num_locked_entries)
 {
        hw_status status = 0;
@@ -193,7 +168,7 @@ hw_status hw_mmu_num_locked_set(const void __iomem *base_address,
        return status;
 }
 
-hw_status hw_mmu_victim_num_set(const void __iomem *base_address,
+hw_status hw_mmu_victim_num_set(void __iomem *base_address,
                                u32 victim_entry_num)
 {
        hw_status status = 0;
@@ -203,7 +178,7 @@ hw_status hw_mmu_victim_num_set(const void __iomem *base_address,
        return status;
 }
 
-hw_status hw_mmu_event_ack(const void __iomem *base_address, u32 irq_mask)
+hw_status hw_mmu_event_ack(void __iomem *base_address, u32 irq_mask)
 {
        hw_status status = 0;
 
@@ -212,7 +187,7 @@ hw_status hw_mmu_event_ack(const void __iomem *base_address, u32 irq_mask)
        return status;
 }
 
-hw_status hw_mmu_event_disable(const void __iomem *base_address, u32 irq_mask)
+hw_status hw_mmu_event_disable(void __iomem *base_address, u32 irq_mask)
 {
        hw_status status = 0;
        u32 irq_reg;
@@ -224,7 +199,7 @@ hw_status hw_mmu_event_disable(const void __iomem *base_address, u32 irq_mask)
        return status;
 }
 
-hw_status hw_mmu_event_enable(const void __iomem *base_address, u32 irq_mask)
+hw_status hw_mmu_event_enable(void __iomem *base_address, u32 irq_mask)
 {
        hw_status status = 0;
        u32 irq_reg;
@@ -236,7 +211,7 @@ hw_status hw_mmu_event_enable(const void __iomem *base_address, u32 irq_mask)
        return status;
 }
 
-hw_status hw_mmu_event_status(const void __iomem *base_address, u32 *irq_mask)
+hw_status hw_mmu_event_status(void __iomem *base_address, u32 *irq_mask)
 {
        hw_status status = 0;
 
@@ -245,7 +220,7 @@ hw_status hw_mmu_event_status(const void __iomem *base_address, u32 *irq_mask)
        return status;
 }
 
-hw_status hw_mmu_fault_addr_read(const void __iomem *base_address, u32 *addr)
+hw_status hw_mmu_fault_addr_read(void __iomem *base_address, u32 *addr)
 {
        hw_status status = 0;
 
@@ -255,7 +230,7 @@ hw_status hw_mmu_fault_addr_read(const void __iomem *base_address, u32 *addr)
        return status;
 }
 
-hw_status hw_mmu_ttb_set(const void __iomem *base_address, u32 ttb_phys_addr)
+hw_status hw_mmu_ttb_set(void __iomem *base_address, u32 ttb_phys_addr)
 {
        hw_status status = 0;
        u32 load_ttb;
@@ -267,7 +242,7 @@ hw_status hw_mmu_ttb_set(const void __iomem *base_address, u32 ttb_phys_addr)
        return status;
 }
 
-hw_status hw_mmu_twl_enable(const void __iomem *base_address)
+hw_status hw_mmu_twl_enable(void __iomem *base_address)
 {
        hw_status status = 0;
 
@@ -276,7 +251,7 @@ hw_status hw_mmu_twl_enable(const void __iomem *base_address)
        return status;
 }
 
-hw_status hw_mmu_twl_disable(const void __iomem *base_address)
+hw_status hw_mmu_twl_disable(void __iomem *base_address)
 {
        hw_status status = 0;
 
@@ -285,45 +260,7 @@ hw_status hw_mmu_twl_disable(const void __iomem *base_address)
        return status;
 }
 
-hw_status hw_mmu_tlb_flush(const void __iomem *base_address, u32 virtual_addr,
-                          u32 page_sz)
-{
-       hw_status status = 0;
-       u32 virtual_addr_tag;
-       enum hw_mmu_page_size_t pg_size_bits;
-
-       switch (page_sz) {
-       case HW_PAGE_SIZE4KB:
-               pg_size_bits = HW_MMU_SMALL_PAGE;
-               break;
-
-       case HW_PAGE_SIZE64KB:
-               pg_size_bits = HW_MMU_LARGE_PAGE;
-               break;
-
-       case HW_PAGE_SIZE1MB:
-               pg_size_bits = HW_MMU_SECTION;
-               break;
-
-       case HW_PAGE_SIZE16MB:
-               pg_size_bits = HW_MMU_SUPERSECTION;
-               break;
-
-       default:
-               return -EINVAL;
-       }
-
-       /* Generate the 20-bit tag from virtual address */
-       virtual_addr_tag = ((virtual_addr & MMU_ADDR_MASK) >> 12);
-
-       mmu_set_cam_entry(base_address, pg_size_bits, 0, 0, virtual_addr_tag);
-
-       mmu_flush_entry(base_address);
-
-       return status;
-}
-
-hw_status hw_mmu_tlb_add(const void __iomem *base_address,
+hw_status hw_mmu_tlb_add(void __iomem *base_address,
                         u32 physical_addr,
                         u32 virtual_addr,
                         u32 page_sz,
@@ -503,20 +440,8 @@ hw_status hw_mmu_pte_clear(const u32 pg_tbl_va, u32 virtual_addr, u32 page_size)
        return status;
 }
 
-/* mmu_flush_entry */
-static hw_status mmu_flush_entry(const void __iomem *base_address)
-{
-       hw_status status = 0;
-       u32 flush_entry_data = 0x1;
-
-       /* write values to register */
-       MMUMMU_FLUSH_ENTRY_WRITE_REGISTER32(base_address, flush_entry_data);
-
-       return status;
-}
-
 /* mmu_set_cam_entry */
-static hw_status mmu_set_cam_entry(const void __iomem *base_address,
+static hw_status mmu_set_cam_entry(void __iomem *base_address,
                                   const u32 page_sz,
                                   const u32 preserved_bit,
                                   const u32 valid_bit,
@@ -536,7 +461,7 @@ static hw_status mmu_set_cam_entry(const void __iomem *base_address,
 }
 
 /* mmu_set_ram_entry */
-static hw_status mmu_set_ram_entry(const void __iomem *base_address,
+static hw_status mmu_set_ram_entry(void __iomem *base_address,
                                   const u32 physical_addr,
                                   enum hw_endianism_t endianism,
                                   enum hw_element_size_t element_size,
@@ -556,7 +481,7 @@ static hw_status mmu_set_ram_entry(const void __iomem *base_address,
 
 }
 
-void hw_mmu_tlb_flush_all(const void __iomem *base)
+void hw_mmu_tlb_flush_all(void __iomem *base)
 {
        __raw_writel(1, base + MMU_GFLUSH);
 }
index 1458a2c6027b7e1fc3cac1c160b837e10b29c6b3..1c50bb36edfee4e4ba918b6d86ee5f18cee78624 100644 (file)
@@ -42,44 +42,41 @@ struct hw_mmu_map_attrs_t {
        bool donotlockmpupage;
 };
 
-extern hw_status hw_mmu_enable(const void __iomem *base_address);
+extern hw_status hw_mmu_enable(void __iomem *base_address);
 
-extern hw_status hw_mmu_disable(const void __iomem *base_address);
+extern hw_status hw_mmu_disable(void __iomem *base_address);
 
-extern hw_status hw_mmu_num_locked_set(const void __iomem *base_address,
+extern hw_status hw_mmu_num_locked_set(void __iomem *base_address,
                                       u32 num_locked_entries);
 
-extern hw_status hw_mmu_victim_num_set(const void __iomem *base_address,
+extern hw_status hw_mmu_victim_num_set(void __iomem *base_address,
                                       u32 victim_entry_num);
 
 /* For MMU faults */
-extern hw_status hw_mmu_event_ack(const void __iomem *base_address,
+extern hw_status hw_mmu_event_ack(void __iomem *base_address,
                                  u32 irq_mask);
 
-extern hw_status hw_mmu_event_disable(const void __iomem *base_address,
+extern hw_status hw_mmu_event_disable(void __iomem *base_address,
                                      u32 irq_mask);
 
-extern hw_status hw_mmu_event_enable(const void __iomem *base_address,
+extern hw_status hw_mmu_event_enable(void __iomem *base_address,
                                     u32 irq_mask);
 
-extern hw_status hw_mmu_event_status(const void __iomem *base_address,
+extern hw_status hw_mmu_event_status(void __iomem *base_address,
                                     u32 *irq_mask);
 
-extern hw_status hw_mmu_fault_addr_read(const void __iomem *base_address,
+extern hw_status hw_mmu_fault_addr_read(void __iomem *base_address,
                                        u32 *addr);
 
 /* Set the TT base address */
-extern hw_status hw_mmu_ttb_set(const void __iomem *base_address,
+extern hw_status hw_mmu_ttb_set(void __iomem *base_address,
                                u32 ttb_phys_addr);
 
-extern hw_status hw_mmu_twl_enable(const void __iomem *base_address);
+extern hw_status hw_mmu_twl_enable(void __iomem *base_address);
 
-extern hw_status hw_mmu_twl_disable(const void __iomem *base_address);
+extern hw_status hw_mmu_twl_disable(void __iomem *base_address);
 
-extern hw_status hw_mmu_tlb_flush(const void __iomem *base_address,
-                                 u32 virtual_addr, u32 page_sz);
-
-extern hw_status hw_mmu_tlb_add(const void __iomem *base_address,
+extern hw_status hw_mmu_tlb_add(void __iomem *base_address,
                                u32 physical_addr,
                                u32 virtual_addr,
                                u32 page_sz,
@@ -97,7 +94,7 @@ extern hw_status hw_mmu_pte_set(const u32 pg_tbl_va,
 extern hw_status hw_mmu_pte_clear(const u32 pg_tbl_va,
                                  u32 virtual_addr, u32 page_size);
 
-void hw_mmu_tlb_flush_all(const void __iomem *base);
+void hw_mmu_tlb_flush_all(void __iomem *base);
 
 static inline u32 hw_mmu_pte_addr_l1(u32 l1_base, u32 va)
 {
index 60a278136bdf58f14718fb43913d292a51b01397..b32c75673ab441c5795b456d25d272ffdaf79866 100644 (file)
@@ -53,8 +53,8 @@ struct cfg_hostres {
        u32 chnl_buf_size;
        u32 num_chnls;
        void __iomem *per_base;
-       u32 per_pm_base;
-       u32 core_pm_base;
+       void __iomem *per_pm_base;
+       void __iomem *core_pm_base;
        void __iomem *dmmu_base;
 };
 
index ed00d3da3205a0074333fb0a4dfd778ca6417280..5e2f4d82d925fbf76b628299347c4f83a86321a3 100644 (file)
@@ -47,8 +47,8 @@
 #include <asm/cacheflush.h>
 #include <linux/dma-mapping.h>
 
-/* TODO -- Remove, once BP defines them */
-#define INT_DSP_MMU_IRQ        28
+/* TODO -- Remove, once omap-iommu is used */
+#define INT_DSP_MMU_IRQ        (28 + NR_IRQS)
 
 #define PRCM_VDD1 1
 
index 6795205b01553e07b671c63a1c49519b092c6e7f..db1da28cecba84d4800363df964647e85b8177c9 100644 (file)
@@ -667,10 +667,10 @@ int drv_request_bridge_res_dsp(void **phost_resources)
                                                         OMAP_DSP_MEM3_SIZE);
                host_res->per_base = ioremap(OMAP_PER_CM_BASE,
                                                OMAP_PER_CM_SIZE);
-               host_res->per_pm_base = (u32) ioremap(OMAP_PER_PRM_BASE,
-                                                        OMAP_PER_PRM_SIZE);
-               host_res->core_pm_base = (u32) ioremap(OMAP_CORE_PRM_BASE,
-                                                         OMAP_CORE_PRM_SIZE);
+               host_res->per_pm_base = ioremap(OMAP_PER_PRM_BASE,
+                                               OMAP_PER_PRM_SIZE);
+               host_res->core_pm_base = ioremap(OMAP_CORE_PRM_BASE,
+                                                       OMAP_CORE_PRM_SIZE);
                host_res->dmmu_base = ioremap(OMAP_DMMU_BASE,
                                                 OMAP_DMMU_SIZE);
 
index c2fc6137c7708372ff4cde1d8f9f6375fe3086a8..294e9b40f51666396c2a56c3d92036951e04382d 100644 (file)
@@ -304,8 +304,7 @@ int node_allocate(struct proc_object *hprocessor,
        u32 pul_value;
        u32 dynext_base;
        u32 off_set = 0;
-       u32 ul_stack_seg_addr, ul_stack_seg_val;
-       u32 ul_gpp_mem_base;
+       u32 ul_stack_seg_val;
        struct cfg_hostres *host_res;
        struct bridge_dev_context *pbridge_context;
        u32 mapped_addr = 0;
@@ -581,6 +580,9 @@ func_cont:
                if (strcmp((char *)
                           pnode->dcd_props.obj_data.node_obj.ndb_props.
                           stack_seg_name, STACKSEGLABEL) == 0) {
+                       void __iomem *stack_seg;
+                       u32 stack_seg_pa;
+
                        status =
                            hnode_mgr->nldr_fxns.
                            get_fxn_addr(pnode->nldr_node_obj, "DYNEXT_BEG",
@@ -608,14 +610,21 @@ func_cont:
                                goto func_end;
                        }
 
-                       ul_gpp_mem_base = (u32) host_res->mem_base[1];
                        off_set = pul_value - dynext_base;
-                       ul_stack_seg_addr = ul_gpp_mem_base + off_set;
-                       ul_stack_seg_val = readl(ul_stack_seg_addr);
+                       stack_seg_pa = host_res->mem_phys[1] + off_set;
+                       stack_seg = ioremap(stack_seg_pa, SZ_32);
+                       if (!stack_seg) {
+                               status = -ENOMEM;
+                               goto func_end;
+                       }
+
+                       ul_stack_seg_val = readl(stack_seg);
+
+                       iounmap(stack_seg);
 
                        dev_dbg(bridge, "%s: StackSegVal = 0x%x, StackSegAddr ="
                                " 0x%x\n", __func__, ul_stack_seg_val,
-                               ul_stack_seg_addr);
+                               host_res->mem_base[1] + off_set);
 
                        pnode->create_args.asa.task_arg_obj.stack_seg =
                            ul_stack_seg_val;
index 653b074035f7b165d04d1587d428097ecfac780a..6edefde23722b436641166f5b678291d6648c6b2 100644 (file)
@@ -223,8 +223,13 @@ static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec,
        cmem = zs_map_object(zram->mem_pool, zram->table[index].handle,
                                ZS_MM_RO);
 
-       ret = lzo1x_decompress_safe(cmem, zram->table[index].size,
+       if (zram->table[index].size == PAGE_SIZE) {
+               memcpy(uncmem, cmem, PAGE_SIZE);
+               ret = LZO_E_OK;
+       } else {
+               ret = lzo1x_decompress_safe(cmem, zram->table[index].size,
                                    uncmem, &clen);
+       }
 
        if (is_partial_io(bvec)) {
                memcpy(user_mem + bvec->bv_offset, uncmem + offset,
@@ -342,8 +347,11 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
                goto out;
        }
 
-       if (unlikely(clen > max_zpage_size))
+       if (unlikely(clen > max_zpage_size)) {
                zram_stat_inc(&zram->stats.bad_compress);
+               src = uncmem;
+               clen = PAGE_SIZE;
+       }
 
        handle = zs_malloc(zram->mem_pool, clen);
        if (!handle) {
index d6ce2182e67207d41932fec75914b9d2c7f44479..035c2c762537c63e9bf62210b5476f7aef5c687a 100644 (file)
@@ -3719,7 +3719,9 @@ restart:
                 */
                iscsit_thread_check_cpumask(conn, current, 1);
 
-               schedule_timeout_interruptible(MAX_SCHEDULE_TIMEOUT);
+               wait_event_interruptible(conn->queues_wq,
+                                        !iscsit_conn_all_queues_empty(conn) ||
+                                        ts->status == ISCSI_THREAD_SET_RESET);
 
                if ((ts->status == ISCSI_THREAD_SET_RESET) ||
                     signal_pending(current))
index 2ba9f9b9435c8684e59d0c65b6a18a6586ec5490..21048dbf7d13cc7ac116be38bb13a9ac6300c2a0 100644 (file)
@@ -486,6 +486,7 @@ struct iscsi_tmr_req {
 };
 
 struct iscsi_conn {
+       wait_queue_head_t       queues_wq;
        /* Authentication Successful for this connection */
        u8                      auth_complete;
        /* State connection is currently in */
index cdc8a10939c3d8d00912a6d9b5d735930d4e60ab..f8dbec05d5e56736fdc9238f997fcc8b18209021 100644 (file)
@@ -41,6 +41,7 @@
 
 static int iscsi_login_init_conn(struct iscsi_conn *conn)
 {
+       init_waitqueue_head(&conn->queues_wq);
        INIT_LIST_HEAD(&conn->conn_list);
        INIT_LIST_HEAD(&conn->conn_cmd_list);
        INIT_LIST_HEAD(&conn->immed_queue_list);
index afd98ccd40ae564f8013155bf6a4d99f857f339a..1a91195ab619a9ebbfa503cf7851c3cb8ca02b49 100644 (file)
@@ -488,7 +488,7 @@ void iscsit_add_cmd_to_immediate_queue(
        atomic_set(&conn->check_immediate_queue, 1);
        spin_unlock_bh(&conn->immed_queue_lock);
 
-       wake_up_process(conn->thread_set->tx_thread);
+       wake_up(&conn->queues_wq);
 }
 
 struct iscsi_queue_req *iscsit_get_cmd_from_immediate_queue(struct iscsi_conn *conn)
@@ -562,7 +562,7 @@ void iscsit_add_cmd_to_response_queue(
        atomic_inc(&cmd->response_queue_count);
        spin_unlock_bh(&conn->response_queue_lock);
 
-       wake_up_process(conn->thread_set->tx_thread);
+       wake_up(&conn->queues_wq);
 }
 
 struct iscsi_queue_req *iscsit_get_cmd_from_response_queue(struct iscsi_conn *conn)
@@ -616,6 +616,24 @@ static void iscsit_remove_cmd_from_response_queue(
        }
 }
 
+bool iscsit_conn_all_queues_empty(struct iscsi_conn *conn)
+{
+       bool empty;
+
+       spin_lock_bh(&conn->immed_queue_lock);
+       empty = list_empty(&conn->immed_queue_list);
+       spin_unlock_bh(&conn->immed_queue_lock);
+
+       if (!empty)
+               return empty;
+
+       spin_lock_bh(&conn->response_queue_lock);
+       empty = list_empty(&conn->response_queue_list);
+       spin_unlock_bh(&conn->response_queue_lock);
+
+       return empty;
+}
+
 void iscsit_free_queue_reqs_for_conn(struct iscsi_conn *conn)
 {
        struct iscsi_queue_req *qr, *qr_tmp;
index 44054bd35437af3b21fbdc5422171d7d8032f76c..894d0f8379246f63166666b36259fbe0315d8dd4 100644 (file)
@@ -25,6 +25,7 @@ extern struct iscsi_queue_req *iscsit_get_cmd_from_immediate_queue(struct iscsi_
 extern void iscsit_add_cmd_to_response_queue(struct iscsi_cmd *, struct iscsi_conn *, u8);
 extern struct iscsi_queue_req *iscsit_get_cmd_from_response_queue(struct iscsi_conn *);
 extern void iscsit_remove_cmd_from_tx_queues(struct iscsi_cmd *, struct iscsi_conn *);
+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 *);
index 015f5be27bf6f00dab299b20b295ef71df4af3e2..c123327499a3572f5e950f6483ea20d99096ebab 100644 (file)
@@ -3206,7 +3206,8 @@ static int __init target_core_init_configfs(void)
        if (ret < 0)
                goto out;
 
-       if (core_dev_setup_virtual_lun0() < 0)
+       ret = core_dev_setup_virtual_lun0();
+       if (ret < 0)
                goto out;
 
        return 0;
index 8d774da16320707cb81f525f511188ff202c57ae..9abef9f8eb760a88e7073802ceec77197421bf97 100644 (file)
@@ -850,20 +850,20 @@ int se_dev_check_shutdown(struct se_device *dev)
 
 static u32 se_dev_align_max_sectors(u32 max_sectors, u32 block_size)
 {
-       u32 tmp, aligned_max_sectors;
+       u32 aligned_max_sectors;
+       u32 alignment;
        /*
         * Limit max_sectors to a PAGE_SIZE aligned value for modern
         * transport_allocate_data_tasks() operation.
         */
-       tmp = rounddown((max_sectors * block_size), PAGE_SIZE);
-       aligned_max_sectors = (tmp / block_size);
-       if (max_sectors != aligned_max_sectors) {
-               printk(KERN_INFO "Rounding down aligned max_sectors from %u"
-                               " to %u\n", max_sectors, aligned_max_sectors);
-               return aligned_max_sectors;
-       }
+       alignment = max(1ul, PAGE_SIZE / block_size);
+       aligned_max_sectors = rounddown(max_sectors, alignment);
+
+       if (max_sectors != aligned_max_sectors)
+               pr_info("Rounding down aligned max_sectors from %u to %u\n",
+                       max_sectors, aligned_max_sectors);
 
-       return max_sectors;
+       return aligned_max_sectors;
 }
 
 void se_dev_set_default_attribs(
index 868f8aa04f13d318b1c752d08887703f7a72de21..a6e27d967c7b7b4abc53dd194927252ed2cde897 100644 (file)
@@ -135,6 +135,12 @@ static int sbc_emulate_verify(struct se_cmd *cmd)
        return 0;
 }
 
+static int sbc_emulate_noop(struct se_cmd *cmd)
+{
+       target_complete_cmd(cmd, GOOD);
+       return 0;
+}
+
 static inline u32 sbc_get_size(struct se_cmd *cmd, u32 sectors)
 {
        return cmd->se_dev->se_sub_dev->se_dev_attrib.block_size * sectors;
@@ -531,6 +537,18 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops)
                size = 0;
                cmd->execute_cmd = sbc_emulate_verify;
                break;
+       case REZERO_UNIT:
+       case SEEK_6:
+       case SEEK_10:
+               /*
+                * There are still clients out there which use these old SCSI-2
+                * commands. This mainly happens when running VMs with legacy
+                * guest systems, connected via SCSI command pass-through to
+                * iSCSI targets. Make them happy and return status GOOD.
+                */
+               size = 0;
+               cmd->execute_cmd = sbc_emulate_noop;
+               break;
        default:
                ret = spc_parse_cdb(cmd, &size);
                if (ret)
index 9229bd9ad61b3db7cd4d182ab3d5315f24785a5f..6fd434d3d7e477ab7d49660d20e02b0d638b8e3a 100644 (file)
@@ -605,6 +605,8 @@ static int spc_emulate_inquiry(struct se_cmd *cmd)
        unsigned char buf[SE_INQUIRY_BUF];
        int p, ret;
 
+       memset(buf, 0, SE_INQUIRY_BUF);
+
        if (dev == tpg->tpg_virt_lun0.lun_se_dev)
                buf[0] = 0x3f; /* Not connected */
        else
index 1c59a3c23b2c1b37ee8a3c54d62b8c66ea6f9e87..be75c4331a9222a5ca4d0b015ebdbe5a983c20ae 100644 (file)
@@ -140,15 +140,15 @@ void core_tmr_abort_task(
                printk("ABORT_TASK: Found referenced %s task_tag: %u\n",
                        se_cmd->se_tfo->get_fabric_name(), ref_tag);
 
-               spin_lock_irq(&se_cmd->t_state_lock);
+               spin_lock(&se_cmd->t_state_lock);
                if (se_cmd->transport_state & CMD_T_COMPLETE) {
                        printk("ABORT_TASK: ref_tag: %u already complete, skipping\n", ref_tag);
-                       spin_unlock_irq(&se_cmd->t_state_lock);
+                       spin_unlock(&se_cmd->t_state_lock);
                        spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
                        goto out;
                }
                se_cmd->transport_state |= CMD_T_ABORTED;
-               spin_unlock_irq(&se_cmd->t_state_lock);
+               spin_unlock(&se_cmd->t_state_lock);
 
                list_del_init(&se_cmd->se_cmd_list);
                kref_get(&se_cmd->cmd_kref);
index c33baff86aa699deacd04bd873e3c31fa5569cf5..9097155e9ebe7100c0bc1a4ac13b7c508a84ac8a 100644 (file)
@@ -1616,7 +1616,6 @@ static void target_complete_tmr_failure(struct work_struct *work)
 
        se_cmd->se_tmr_req->response = TMR_LUN_DOES_NOT_EXIST;
        se_cmd->se_tfo->queue_tm_rsp(se_cmd);
-       transport_generic_free_cmd(se_cmd, 0);
 }
 
 /**
index fd03e8581afc2a8e86ed354c03c06e84a1b604cc..6dd29e4ce36b1cd4841b94b6f1c1bd6251040972 100644 (file)
@@ -815,7 +815,7 @@ static struct platform_device_id exynos_tmu_driver_ids[] = {
        },
        { },
 };
-MODULE_DEVICE_TABLE(platform, exynos4_tmu_driver_ids);
+MODULE_DEVICE_TABLE(platform, exynos_tmu_driver_ids);
 
 static inline struct  exynos_tmu_platform_data *exynos_get_driver_data(
                        struct platform_device *pdev)
index d4452716aaab1a7dbec7e3df53ec0abbed43aabd..f7a1b574a304e8808cb0cfda0d7e91ef6272bd50 100644 (file)
@@ -210,7 +210,7 @@ static int rcar_thermal_probe(struct platform_device *pdev)
                goto error_free_priv;
        }
 
-       zone = thermal_zone_device_register("rcar_thermal", 0, priv,
+       zone = thermal_zone_device_register("rcar_thermal", 0, 0, priv,
                                            &rcar_thermal_zone_ops, 0, 0);
        if (IS_ERR(zone)) {
                dev_err(&pdev->dev, "thermal zone device is NULL\n");
index a5dec1ca1b826bad18d9a1bf5c69eae17bfba423..13ee53bd0bf66869c201e901d3bf16ff35039e17 100644 (file)
@@ -424,7 +424,6 @@ static void hvc_hangup(struct tty_struct *tty)
 {
        struct hvc_struct *hp = tty->driver_data;
        unsigned long flags;
-       int temp_open_count;
 
        if (!hp)
                return;
@@ -444,7 +443,6 @@ static void hvc_hangup(struct tty_struct *tty)
                return;
        }
 
-       temp_open_count = hp->port.count;
        hp->port.count = 0;
        spin_unlock_irqrestore(&hp->port.lock, flags);
        tty_port_tty_set(&hp->port, NULL);
@@ -453,11 +451,6 @@ static void hvc_hangup(struct tty_struct *tty)
 
        if (hp->ops->notifier_hangup)
                hp->ops->notifier_hangup(hp, hp->data);
-
-       while(temp_open_count) {
-               --temp_open_count;
-               tty_port_put(&hp->port);
-       }
 }
 
 /*
index 2bc28a59d38514f762718d19a8ebe50851311b49..1ab1d2c66de43ad749772c240f4f4c6944783e22 100644 (file)
@@ -1239,6 +1239,7 @@ static int __devexit max310x_remove(struct spi_device *spi)
 static const struct spi_device_id max310x_id_table[] = {
        { "max3107",    MAX310X_TYPE_MAX3107 },
        { "max3108",    MAX310X_TYPE_MAX3108 },
+       { }
 };
 MODULE_DEVICE_TABLE(spi, max310x_id_table);
 
index 6ede6fd92b4cd00e939dca479e0f3e3a0a0d923e..6d3d26a607b9fd26bc03cff7d50f62ccbf8a589b 100644 (file)
@@ -671,19 +671,19 @@ serial_omap_configure_xonxoff
 
        /*
         * IXON Flag:
-        * Flow control for OMAP.TX
-        * OMAP.RX should listen for XON/XOFF
+        * Enable XON/XOFF flow control on output.
+        * Transmit XON1, XOFF1
         */
        if (termios->c_iflag & IXON)
-               up->efr |= OMAP_UART_SW_RX;
+               up->efr |= OMAP_UART_SW_TX;
 
        /*
         * IXOFF Flag:
-        * Flow control for OMAP.RX
-        * OMAP.TX should send XON/XOFF
+        * Enable XON/XOFF flow control on input.
+        * Receiver compares XON1, XOFF1.
         */
        if (termios->c_iflag & IXOFF)
-               up->efr |= OMAP_UART_SW_TX;
+               up->efr |= OMAP_UART_SW_RX;
 
        serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
        serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
index 1e741bca02652e8f4ed2b027654abc3ac9d16a4f..f034716190ff425c89b007e2e10e4cd98ca6cb61 100644 (file)
@@ -2151,8 +2151,15 @@ EXPORT_SYMBOL_GPL(usb_bus_start_enum);
 irqreturn_t usb_hcd_irq (int irq, void *__hcd)
 {
        struct usb_hcd          *hcd = __hcd;
+       unsigned long           flags;
        irqreturn_t             rc;
 
+       /* IRQF_DISABLED doesn't work correctly with shared IRQs
+        * when the first handler doesn't use it.  So let's just
+        * assume it's never used.
+        */
+       local_irq_save(flags);
+
        if (unlikely(HCD_DEAD(hcd) || !HCD_HW_ACCESSIBLE(hcd)))
                rc = IRQ_NONE;
        else if (hcd->driver->irq(hcd) == IRQ_NONE)
@@ -2160,6 +2167,7 @@ irqreturn_t usb_hcd_irq (int irq, void *__hcd)
        else
                rc = IRQ_HANDLED;
 
+       local_irq_restore(flags);
        return rc;
 }
 EXPORT_SYMBOL_GPL(usb_hcd_irq);
@@ -2347,6 +2355,14 @@ static int usb_hcd_request_irqs(struct usb_hcd *hcd,
        int retval;
 
        if (hcd->driver->irq) {
+
+               /* IRQF_DISABLED doesn't work as advertised when used together
+                * with IRQF_SHARED. As usb_hcd_irq() will always disable
+                * interrupts we can remove it here.
+                */
+               if (irqflags & IRQF_SHARED)
+                       irqflags &= ~IRQF_DISABLED;
+
                snprintf(hcd->irq_descr, sizeof(hcd->irq_descr), "%s:usb%d",
                                hcd->driver->description, hcd->self.busnum);
                retval = request_irq(irqnum, &usb_hcd_irq, irqflags,
index 64854d76f52901f39bf658a17790d4b512853a81..1af04bdeaf0c1884487ed830bcee7dd32ee720b6 100644 (file)
@@ -739,13 +739,16 @@ static void hub_tt_work(struct work_struct *work)
        int                     limit = 100;
 
        spin_lock_irqsave (&hub->tt.lock, flags);
-       while (--limit && !list_empty (&hub->tt.clear_list)) {
+       while (!list_empty(&hub->tt.clear_list)) {
                struct list_head        *next;
                struct usb_tt_clear     *clear;
                struct usb_device       *hdev = hub->hdev;
                const struct hc_driver  *drv;
                int                     status;
 
+               if (!hub->quiescing && --limit < 0)
+                       break;
+
                next = hub->tt.clear_list.next;
                clear = list_entry (next, struct usb_tt_clear, clear_list);
                list_del (&clear->clear_list);
@@ -1210,7 +1213,7 @@ static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type)
        if (hub->has_indicators)
                cancel_delayed_work_sync(&hub->leds);
        if (hub->tt.hub)
-               cancel_work_sync(&hub->tt.clear_work);
+               flush_work(&hub->tt.clear_work);
 }
 
 /* caller has locked the hub device */
index e426ad626d7498bf5e6537ac100c7a508979066a..4bfa78af379cff63e1e74fa57453d7f55c96fb5e 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/usb/ehci_def.h>
 #include <linux/delay.h>
 #include <linux/serial_core.h>
+#include <linux/kconfig.h>
 #include <linux/kgdb.h>
 #include <linux/kthread.h>
 #include <asm/io.h>
@@ -614,12 +615,6 @@ err:
        return -ENODEV;
 }
 
-int dbgp_external_startup(struct usb_hcd *hcd)
-{
-       return xen_dbgp_external_startup(hcd) ?: _dbgp_external_startup();
-}
-EXPORT_SYMBOL_GPL(dbgp_external_startup);
-
 static int ehci_reset_port(int port)
 {
        u32 portsc;
@@ -979,6 +974,7 @@ struct console early_dbgp_console = {
        .index =        -1,
 };
 
+#if IS_ENABLED(CONFIG_USB_EHCI_HCD)
 int dbgp_reset_prep(struct usb_hcd *hcd)
 {
        int ret = xen_dbgp_reset_prep(hcd);
@@ -1007,6 +1003,13 @@ int dbgp_reset_prep(struct usb_hcd *hcd)
 }
 EXPORT_SYMBOL_GPL(dbgp_reset_prep);
 
+int dbgp_external_startup(struct usb_hcd *hcd)
+{
+       return xen_dbgp_external_startup(hcd) ?: _dbgp_external_startup();
+}
+EXPORT_SYMBOL_GPL(dbgp_external_startup);
+#endif /* USB_EHCI_HCD */
+
 #ifdef CONFIG_KGDB
 
 static char kgdbdbgp_buf[DBGP_MAX_PACKET];
index 43ac7482fa9184dbd4748d42d6a6008e21f330ef..c009263a47e3250951fc1b16cab143ba0934eb86 100644 (file)
@@ -2069,8 +2069,10 @@ static irqreturn_t net2272_irq(int irq, void *_dev)
 #if defined(PLX_PCI_RDK2)
        /* see if PCI int for us by checking irqstat */
        intcsr = readl(dev->rdk2.fpga_base_addr + RDK2_IRQSTAT);
-       if (!intcsr & (1 << NET2272_PCI_IRQ))
+       if (!intcsr & (1 << NET2272_PCI_IRQ)) {
+               spin_unlock(&dev->lock);
                return IRQ_NONE;
+       }
        /* check dma interrupts */
 #endif
        /* Platform/devcice interrupt handler */
index 6458764994efe5d2523ca0cfded7af6a0fd91432..4ec3c0d7a18b84bb895262de69bf080886391025 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/ctype.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
+#include <linux/if_vlan.h>
 
 #include "u_ether.h"
 
@@ -295,7 +296,7 @@ static void rx_complete(struct usb_ep *ep, struct usb_request *req)
                while (skb2) {
                        if (status < 0
                                        || ETH_HLEN > skb2->len
-                                       || skb2->len > ETH_FRAME_LEN) {
+                                       || skb2->len > VLAN_ETH_FRAME_LEN) {
                                dev->net->stats.rx_errors++;
                                dev->net->stats.rx_length_errors++;
                                DBG(dev, "rx length %d\n", skb2->len);
index ca759652626bcf5f823a32bf9e6640acda23a02b..aa0f328922dfad88495b919a84d82abd3a494ac9 100644 (file)
@@ -113,7 +113,7 @@ static int ehci_hcd_ls1x_probe(struct platform_device *pdev)
                goto err_put_hcd;
        }
 
-       ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
+       ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
        if (ret)
                goto err_put_hcd;
 
index 84201cd1a472cd5b00bd959b28bcf35af24137e6..41e378f17c66ac453f2aabfd25640c8e77120224 100644 (file)
@@ -56,7 +56,7 @@ static int ohci_xls_probe_internal(const struct hc_driver *driver,
                goto err3;
        }
 
-       retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
+       retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
        if (retval != 0)
                goto err4;
        return retval;
index 966d1484ee79a2db8c5e78e135c5e0760814d183..39f9e4a9a2d3f086470c6cac459ca0ab4a4fec78 100644 (file)
@@ -545,7 +545,14 @@ static const struct dmi_system_id __devinitconst ehci_dmi_nohandoff_table[] = {
                /*  Pegatron Lucid (Ordissimo AIRIS) */
                .matches = {
                        DMI_MATCH(DMI_BOARD_NAME, "M11JB"),
-                       DMI_MATCH(DMI_BIOS_VERSION, "Lucid-GE-133"),
+                       DMI_MATCH(DMI_BIOS_VERSION, "Lucid-"),
+               },
+       },
+       {
+               /*  Pegatron Lucid (Ordissimo) */
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_NAME, "Ordissimo"),
+                       DMI_MATCH(DMI_BIOS_VERSION, "Lucid-"),
                },
        },
        { }
index 4b436f5a41711bc1a7747f3c7b187ff547c7acbd..5f3a7c74aa8d39404212d342f6236fe1ea48d514 100644 (file)
@@ -544,7 +544,6 @@ void xhci_dbg_ctx(struct xhci_hcd *xhci,
        int i;
        /* Fields are 32 bits wide, DMA addresses are in bytes */
        int field_size = 32 / 8;
-       struct xhci_slot_ctx *slot_ctx;
        dma_addr_t dma = ctx->dma;
        int csz = HCC_64BYTE_CONTEXT(xhci->hcc_params);
 
@@ -570,7 +569,6 @@ void xhci_dbg_ctx(struct xhci_hcd *xhci,
                        dbg_rsvd64(xhci, (u64 *)ctrl_ctx, dma);
        }
 
-       slot_ctx = xhci_get_slot_ctx(xhci, ctx);
        xhci_dbg_slot_ctx(xhci, ctx);
        xhci_dbg_ep_ctx(xhci, ctx, last_ep);
 }
index aa90ad4d4fd53b2f70288641dcd13942355ca875..a686cf4905bb80ae3e4c7b206c05d7cd2b960920 100644 (file)
@@ -151,9 +151,8 @@ static void xhci_usb3_hub_descriptor(struct usb_hcd *hcd, struct xhci_hcd *xhci,
                if (portsc & PORT_DEV_REMOVE)
                        port_removable |= 1 << (i + 1);
        }
-       memset(&desc->u.ss.DeviceRemovable,
-                       (__force __u16) cpu_to_le16(port_removable),
-                       sizeof(__u16));
+
+       desc->u.ss.DeviceRemovable = cpu_to_le16(port_removable);
 }
 
 static void xhci_hub_descriptor(struct usb_hcd *hcd, struct xhci_hcd *xhci,
@@ -809,11 +808,13 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                        temp = xhci_readl(xhci, port_array[wIndex]);
                        xhci_dbg(xhci, "set port power, actual port %d status  = 0x%x\n", wIndex, temp);
 
+                       spin_unlock_irqrestore(&xhci->lock, flags);
                        temp = usb_acpi_power_manageable(hcd->self.root_hub,
                                        wIndex);
                        if (temp)
                                usb_acpi_set_power_state(hcd->self.root_hub,
                                                wIndex, true);
+                       spin_lock_irqsave(&xhci->lock, flags);
                        break;
                case USB_PORT_FEAT_RESET:
                        temp = (temp | PORT_RESET);
@@ -917,11 +918,13 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                        xhci_writel(xhci, temp & ~PORT_POWER,
                                port_array[wIndex]);
 
+                       spin_unlock_irqrestore(&xhci->lock, flags);
                        temp = usb_acpi_power_manageable(hcd->self.root_hub,
                                        wIndex);
                        if (temp)
                                usb_acpi_set_power_state(hcd->self.root_hub,
                                                wIndex, false);
+                       spin_lock_irqsave(&xhci->lock, flags);
                        break;
                default:
                        goto error;
index c6ebb176dc4fb33d1307b9068ea7d27728356637..4e1a8946b8d167c1f36be62b3bc63265f7271815 100644 (file)
@@ -1228,6 +1228,17 @@ static void xhci_cmd_to_noop(struct xhci_hcd *xhci, struct xhci_cd *cur_cd)
        cur_seg = find_trb_seg(xhci->cmd_ring->first_seg,
                        xhci->cmd_ring->dequeue, &cycle_state);
 
+       if (!cur_seg) {
+               xhci_warn(xhci, "Command ring mismatch, dequeue = %p %llx (dma)\n",
+                               xhci->cmd_ring->dequeue,
+                               (unsigned long long)
+                               xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg,
+                                       xhci->cmd_ring->dequeue));
+               xhci_debug_ring(xhci, xhci->cmd_ring);
+               xhci_dbg_ring_ptrs(xhci, xhci->cmd_ring);
+               return;
+       }
+
        /* find the command trb matched by cd from command ring */
        for (cmd_trb = xhci->cmd_ring->dequeue;
                        cmd_trb != xhci->cmd_ring->enqueue;
index 7d462bf20092cee0d35adad12d42ea1d2a28e595..c9e419f29b7454225516cb8629ddff80af5187d9 100644 (file)
@@ -1627,7 +1627,6 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
        struct xhci_hcd *xhci;
        struct xhci_container_ctx *in_ctx, *out_ctx;
        unsigned int ep_index;
-       struct xhci_ep_ctx *ep_ctx;
        struct xhci_slot_ctx *slot_ctx;
        struct xhci_input_control_ctx *ctrl_ctx;
        u32 added_ctxs;
@@ -1663,7 +1662,6 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
        out_ctx = virt_dev->out_ctx;
        ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx);
        ep_index = xhci_get_endpoint_index(&ep->desc);
-       ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index);
 
        /* If this endpoint is already in use, and the upper layers are trying
         * to add it again without dropping it, reject the addition.
@@ -1817,6 +1815,8 @@ static int xhci_evaluate_context_result(struct xhci_hcd *xhci,
        case COMP_EBADSLT:
                dev_warn(&udev->dev, "WARN: slot not enabled for"
                                "evaluate context command.\n");
+               ret = -EINVAL;
+               break;
        case COMP_CTX_STATE:
                dev_warn(&udev->dev, "WARN: invalid context state for "
                                "evaluate context command.\n");
@@ -4021,7 +4021,7 @@ int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev)
 static unsigned long long xhci_service_interval_to_ns(
                struct usb_endpoint_descriptor *desc)
 {
-       return (1 << (desc->bInterval - 1)) * 125 * 1000;
+       return (1ULL << (desc->bInterval - 1)) * 125 * 1000;
 }
 
 static u16 xhci_get_timeout_no_hub_lpm(struct usb_device *udev,
@@ -4142,7 +4142,7 @@ static u16 xhci_calculate_intel_u2_timeout(struct usb_device *udev,
                        (xhci_service_interval_to_ns(desc) > timeout_ns))
                timeout_ns = xhci_service_interval_to_ns(desc);
 
-       u2_del_ns = udev->bos->ss_cap->bU2DevExitLat * 1000;
+       u2_del_ns = le16_to_cpu(udev->bos->ss_cap->bU2DevExitLat) * 1000ULL;
        if (u2_del_ns > timeout_ns)
                timeout_ns = u2_del_ns;
 
index 4223d761223d3440a243a87150d4283537e89a4b..6589268a651517da44f99cd7391e2ca35f84f12a 100644 (file)
@@ -158,3 +158,4 @@ int ezusb_fx2_ihex_firmware_download(struct usb_device *dev,
 }
 EXPORT_SYMBOL_GPL(ezusb_fx2_ihex_firmware_download);
 
+MODULE_LICENSE("GPL");
index 444346e1e10d768086b1e10487f6b6428c892897..ff5f112053d28f114e4d90844b7aa2172f3856d4 100644 (file)
@@ -458,11 +458,11 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)
        struct platform_device  *musb;
        struct resource *res;
        struct resource resources[2];
-       char res_name[10];
+       char res_name[11];
        int ret, musbid;
 
        /* get memory resource */
-       sprintf(res_name, "musb%d", id);
+       snprintf(res_name, sizeof(res_name), "musb%d", id);
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, res_name);
        if (!res) {
                dev_err(dev, "%s get mem resource failed\n", res_name);
@@ -473,7 +473,7 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)
        resources[0] = *res;
 
        /* get irq resource */
-       sprintf(res_name, "musb%d-irq", id);
+       snprintf(res_name, sizeof(res_name), "musb%d-irq", id);
        res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, res_name);
        if (!res) {
                dev_err(dev, "%s get irq resource failed\n", res_name);
@@ -530,7 +530,7 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)
 
                of_property_read_u32(np, "num-eps", (u32 *)&config->num_eps);
                of_property_read_u32(np, "ram-bits", (u32 *)&config->ram_bits);
-               sprintf(res_name, "port%d-mode", id);
+               snprintf(res_name, sizeof(res_name), "port%d-mode", id);
                of_property_read_u32(np, res_name, (u32 *)&pdata->mode);
                of_property_read_u32(np, "power", (u32 *)&pdata->power);
                config->multipoint = of_property_read_bool(np, "multipoint");
index d0b87e7b4abfd98b232c135df7661d6dbe0bfe90..b6b84dacc7917070fb20503243ac51098c927631 100644 (file)
@@ -707,11 +707,12 @@ static void rxstate(struct musb *musb, struct musb_request *req)
                fifo_count = musb_readw(epio, MUSB_RXCOUNT);
 
                /*
-                *  use mode 1 only if we expect data of at least ep packet_sz
-                *  and have not yet received a short packet
+                * Enable Mode 1 on RX transfers only when short_not_ok flag
+                * is set. Currently short_not_ok flag is set only from
+                * file_storage and f_mass_storage drivers
                 */
-               if ((request->length - request->actual >= musb_ep->packet_sz) &&
-                       (fifo_count >= musb_ep->packet_sz))
+
+               if (request->short_not_ok && fifo_count == musb_ep->packet_sz)
                        use_mode_1 = 1;
                else
                        use_mode_1 = 0;
@@ -727,6 +728,27 @@ static void rxstate(struct musb *musb, struct musb_request *req)
                                c = musb->dma_controller;
                                channel = musb_ep->dma;
 
+       /* We use DMA Req mode 0 in rx_csr, and DMA controller operates in
+        * mode 0 only. So we do not get endpoint interrupts due to DMA
+        * completion. We only get interrupts from DMA controller.
+        *
+        * We could operate in DMA mode 1 if we knew the size of the tranfer
+        * in advance. For mass storage class, request->length = what the host
+        * sends, so that'd work.  But for pretty much everything else,
+        * request->length is routinely more than what the host sends. For
+        * most these gadgets, end of is signified either by a short packet,
+        * or filling the last byte of the buffer.  (Sending extra data in
+        * that last pckate should trigger an overflow fault.)  But in mode 1,
+        * we don't get DMA completion interrupt for short packets.
+        *
+        * Theoretically, we could enable DMAReq irq (MUSB_RXCSR_DMAMODE = 1),
+        * to get endpoint interrupt on every DMA req, but that didn't seem
+        * to work reliably.
+        *
+        * REVISIT an updated g_file_storage can set req->short_not_ok, which
+        * then becomes usable as a runtime "use mode 1" hint...
+        */
+
                                /* Experimental: Mode1 works with mass storage use cases */
                                if (use_mode_1) {
                                        csr |= MUSB_RXCSR_AUTOCLEAR;
index d62a91fedc221c02774de2c8b9c9e66c3a880ade..0e62f504410eaaf1120edb49ef40381eb7d41d59 100644 (file)
@@ -65,7 +65,7 @@ static int __devinit ux500_probe(struct platform_device *pdev)
        struct platform_device          *musb;
        struct ux500_glue               *glue;
        struct clk                      *clk;
-
+       int                             musbid;
        int                             ret = -ENOMEM;
 
        glue = kzalloc(sizeof(*glue), GFP_KERNEL);
index d8c8a42bff3eb0bb9187849e8136a6ba358a92cf..6223062d5d1b5487534dc29724508d2e5df68793 100644 (file)
@@ -58,7 +58,7 @@ config USB_ULPI_VIEWPORT
 
 config TWL4030_USB
        tristate "TWL4030 USB Transceiver Driver"
-       depends on TWL4030_CORE && REGULATOR_TWL4030
+       depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS
        select USB_OTG_UTILS
        help
          Enable this to support the USB OTG transceiver on TWL4030
@@ -68,7 +68,7 @@ config TWL4030_USB
 
 config TWL6030_USB
        tristate "TWL6030 USB Transceiver Driver"
-       depends on TWL4030_CORE && OMAP_USB2
+       depends on TWL4030_CORE && OMAP_USB2 && USB_MUSB_OMAP2PLUS
        select USB_OTG_UTILS
        help
          Enable this to support the USB OTG transceiver on TWL6030
index 143c4e9e1be45cc24c0a612d38e590a5ad136be9..c021b202c0f3fe05894d3a94075c55bea8dd1a66 100644 (file)
@@ -795,6 +795,7 @@ static void xfer_work(struct work_struct *work)
        dev_dbg(dev, "  %s %d (%d/ %d)\n",
                fifo->name, usbhs_pipe_number(pipe), pkt->length, pkt->zero);
 
+       usbhs_pipe_enable(pipe);
        usbhsf_dma_start(pipe, fifo);
        dma_async_issue_pending(chan);
 }
index 9b69a132329474052486e0483649b6c64a746a4f..069cd765400cbf51f649564d5ed8490d90cd8259 100644 (file)
@@ -334,6 +334,11 @@ static void usbhsh_pipe_detach(struct usbhsh_hpriv *hpriv,
        struct device *dev = usbhs_priv_to_dev(priv);
        unsigned long flags;
 
+       if (unlikely(!uep)) {
+               dev_err(dev, "no uep\n");
+               return;
+       }
+
        /********************  spin lock ********************/
        usbhs_lock(priv, flags);
 
index e9c7046ae355a9da6746c83b669b8605c38fec96..d255f66e708e80ee78d72bc052bef4e71ba578e2 100644 (file)
@@ -242,13 +242,11 @@ out:      kfree(buffer);
        return r;
 }
 
-/* allocate private data */
-static int ch341_attach(struct usb_serial *serial)
+static int ch341_port_probe(struct usb_serial_port *port)
 {
        struct ch341_private *priv;
        int r;
 
-       /* private data */
        priv = kzalloc(sizeof(struct ch341_private), GFP_KERNEL);
        if (!priv)
                return -ENOMEM;
@@ -258,17 +256,27 @@ static int ch341_attach(struct usb_serial *serial)
        priv->baud_rate = DEFAULT_BAUD_RATE;
        priv->line_control = CH341_BIT_RTS | CH341_BIT_DTR;
 
-       r = ch341_configure(serial->dev, priv);
+       r = ch341_configure(port->serial->dev, priv);
        if (r < 0)
                goto error;
 
-       usb_set_serial_port_data(serial->port[0], priv);
+       usb_set_serial_port_data(port, priv);
        return 0;
 
 error: kfree(priv);
        return r;
 }
 
+static int ch341_port_remove(struct usb_serial_port *port)
+{
+       struct ch341_private *priv;
+
+       priv = usb_get_serial_port_data(port);
+       kfree(priv);
+
+       return 0;
+}
+
 static int ch341_carrier_raised(struct usb_serial_port *port)
 {
        struct ch341_private *priv = usb_get_serial_port_data(port);
@@ -304,7 +312,7 @@ static void ch341_close(struct usb_serial_port *port)
 static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port)
 {
        struct usb_serial *serial = port->serial;
-       struct ch341_private *priv = usb_get_serial_port_data(serial->port[0]);
+       struct ch341_private *priv = usb_get_serial_port_data(port);
        int r;
 
        priv->baud_rate = DEFAULT_BAUD_RATE;
@@ -608,7 +616,8 @@ static struct usb_serial_driver ch341_device = {
        .tiocmget          = ch341_tiocmget,
        .tiocmset          = ch341_tiocmset,
        .read_int_callback = ch341_read_int_callback,
-       .attach            = ch341_attach,
+       .port_probe        = ch341_port_probe,
+       .port_remove       = ch341_port_remove,
        .reset_resume      = ch341_reset_resume,
 };
 
index c86f68c6b0785942e16315ebf34443a0f94b2161..b50fa1c6d885be8df8d5675edbedc6637fb9c33f 100644 (file)
@@ -244,6 +244,8 @@ static int digi_startup_device(struct usb_serial *serial);
 static int digi_startup(struct usb_serial *serial);
 static void digi_disconnect(struct usb_serial *serial);
 static void digi_release(struct usb_serial *serial);
+static int digi_port_probe(struct usb_serial_port *port);
+static int digi_port_remove(struct usb_serial_port *port);
 static void digi_read_bulk_callback(struct urb *urb);
 static int digi_read_inb_callback(struct urb *urb);
 static int digi_read_oob_callback(struct urb *urb);
@@ -294,6 +296,8 @@ static struct usb_serial_driver digi_acceleport_2_device = {
        .attach =                       digi_startup,
        .disconnect =                   digi_disconnect,
        .release =                      digi_release,
+       .port_probe =                   digi_port_probe,
+       .port_remove =                  digi_port_remove,
 };
 
 static struct usb_serial_driver digi_acceleport_4_device = {
@@ -320,6 +324,8 @@ static struct usb_serial_driver digi_acceleport_4_device = {
        .attach =                       digi_startup,
        .disconnect =                   digi_disconnect,
        .release =                      digi_release,
+       .port_probe =                   digi_port_probe,
+       .port_remove =                  digi_port_remove,
 };
 
 static struct usb_serial_driver * const serial_drivers[] = {
@@ -1240,59 +1246,50 @@ static int digi_startup_device(struct usb_serial *serial)
        return ret;
 }
 
-
-static int digi_startup(struct usb_serial *serial)
+static int digi_port_init(struct usb_serial_port *port, unsigned port_num)
 {
-
-       int i;
        struct digi_port *priv;
-       struct digi_serial *serial_priv;
 
-       /* allocate the private data structures for all ports */
-       /* number of regular ports + 1 for the out-of-band port */
-       for (i = 0; i < serial->type->num_ports + 1; i++) {
-               /* allocate port private structure */
-               priv = kmalloc(sizeof(struct digi_port), GFP_KERNEL);
-               if (priv == NULL) {
-                       while (--i >= 0)
-                               kfree(usb_get_serial_port_data(serial->port[i]));
-                       return 1;                       /* error */
-               }
+       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
 
-               /* initialize port private structure */
-               spin_lock_init(&priv->dp_port_lock);
-               priv->dp_port_num = i;
-               priv->dp_out_buf_len = 0;
-               priv->dp_write_urb_in_use = 0;
-               priv->dp_modem_signals = 0;
-               init_waitqueue_head(&priv->dp_modem_change_wait);
-               priv->dp_transmit_idle = 0;
-               init_waitqueue_head(&priv->dp_transmit_idle_wait);
-               priv->dp_throttled = 0;
-               priv->dp_throttle_restart = 0;
-               init_waitqueue_head(&priv->dp_flush_wait);
-               init_waitqueue_head(&priv->dp_close_wait);
-               INIT_WORK(&priv->dp_wakeup_work, digi_wakeup_write_lock);
-               priv->dp_port = serial->port[i];
-               /* initialize write wait queue for this port */
-               init_waitqueue_head(&serial->port[i]->write_wait);
-
-               usb_set_serial_port_data(serial->port[i], priv);
-       }
+       spin_lock_init(&priv->dp_port_lock);
+       priv->dp_port_num = port_num;
+       init_waitqueue_head(&priv->dp_modem_change_wait);
+       init_waitqueue_head(&priv->dp_transmit_idle_wait);
+       init_waitqueue_head(&priv->dp_flush_wait);
+       init_waitqueue_head(&priv->dp_close_wait);
+       INIT_WORK(&priv->dp_wakeup_work, digi_wakeup_write_lock);
+       priv->dp_port = port;
 
-       /* allocate serial private structure */
-       serial_priv = kmalloc(sizeof(struct digi_serial), GFP_KERNEL);
-       if (serial_priv == NULL) {
-               for (i = 0; i < serial->type->num_ports + 1; i++)
-                       kfree(usb_get_serial_port_data(serial->port[i]));
-               return 1;                       /* error */
-       }
+       init_waitqueue_head(&port->write_wait);
+
+       usb_set_serial_port_data(port, priv);
+
+       return 0;
+}
+
+static int digi_startup(struct usb_serial *serial)
+{
+       struct digi_serial *serial_priv;
+       int ret;
+
+       serial_priv = kzalloc(sizeof(*serial_priv), GFP_KERNEL);
+       if (!serial_priv)
+               return -ENOMEM;
 
-       /* initialize serial private structure */
        spin_lock_init(&serial_priv->ds_serial_lock);
        serial_priv->ds_oob_port_num = serial->type->num_ports;
        serial_priv->ds_oob_port = serial->port[serial_priv->ds_oob_port_num];
-       serial_priv->ds_device_started = 0;
+
+       ret = digi_port_init(serial_priv->ds_oob_port,
+                                               serial_priv->ds_oob_port_num);
+       if (ret) {
+               kfree(serial_priv);
+               return ret;
+       }
+
        usb_set_serial_data(serial, serial_priv);
 
        return 0;
@@ -1313,15 +1310,35 @@ static void digi_disconnect(struct usb_serial *serial)
 
 static void digi_release(struct usb_serial *serial)
 {
-       int i;
+       struct digi_serial *serial_priv;
+       struct digi_port *priv;
+
+       serial_priv = usb_get_serial_data(serial);
+
+       priv = usb_get_serial_port_data(serial_priv->ds_oob_port);
+       kfree(priv);
 
-       /* free the private data structures for all ports */
-       /* number of regular ports + 1 for the out-of-band port */
-       for (i = 0; i < serial->type->num_ports + 1; i++)
-               kfree(usb_get_serial_port_data(serial->port[i]));
-       kfree(usb_get_serial_data(serial));
+       kfree(serial_priv);
 }
 
+static int digi_port_probe(struct usb_serial_port *port)
+{
+       unsigned port_num;
+
+       port_num = port->number - port->serial->minor;
+
+       return digi_port_init(port, port_num);
+}
+
+static int digi_port_remove(struct usb_serial_port *port)
+{
+       struct digi_port *priv;
+
+       priv = usb_get_serial_port_data(port);
+       kfree(priv);
+
+       return 0;
+}
 
 static void digi_read_bulk_callback(struct urb *urb)
 {
index 20a132ec39e201c4190027a4f2d6750654d553cd..4264821a3b34fb653d28dafe2171e6b9239ca8e5 100644 (file)
@@ -203,8 +203,7 @@ static int ipw_open(struct tty_struct *tty, struct usb_serial_port *port)
        return 0;
 }
 
-/* fake probe - only to allocate data structures */
-static int ipw_probe(struct usb_serial *serial, const struct usb_device_id *id)
+static int ipw_attach(struct usb_serial *serial)
 {
        struct usb_wwan_intf_private *data;
 
@@ -303,9 +302,9 @@ static struct usb_serial_driver ipw_device = {
        .num_ports =            1,
        .open =                 ipw_open,
        .close =                ipw_close,
-       .probe =                ipw_probe,
-       .attach =               usb_wwan_startup,
+       .attach =               ipw_attach,
        .release =              ipw_release,
+       .port_probe =           usb_wwan_port_probe,
        .port_remove =          usb_wwan_port_remove,
        .dtr_rts =              ipw_dtr_rts,
        .write =                usb_wwan_write,
index 29c943d737d0db508b70cda61ce6770d3a335f43..cff8dd5b462d0c35a264ef850c0b7877f9702afa 100644 (file)
@@ -1374,13 +1374,9 @@ static struct callbacks {
           data in device_details */
 static void keyspan_setup_urbs(struct usb_serial *serial)
 {
-       int                             i, j;
        struct keyspan_serial_private   *s_priv;
        const struct keyspan_device_details     *d_details;
-       struct usb_serial_port          *port;
-       struct keyspan_port_private     *p_priv;
        struct callbacks                *cback;
-       int                             endp;
 
        s_priv = usb_get_serial_data(serial);
        d_details = s_priv->device_details;
@@ -1404,45 +1400,6 @@ static void keyspan_setup_urbs(struct usb_serial *serial)
                (serial, d_details->glocont_endpoint, USB_DIR_OUT,
                 serial, s_priv->glocont_buf, GLOCONT_BUFLEN,
                 cback->glocont_callback);
-
-       /* Setup endpoints for each port specific thing */
-       for (i = 0; i < d_details->num_ports; i++) {
-               port = serial->port[i];
-               p_priv = usb_get_serial_port_data(port);
-
-               /* Do indat endpoints first, once for each flip */
-               endp = d_details->indat_endpoints[i];
-               for (j = 0; j <= d_details->indat_endp_flip; ++j, ++endp) {
-                       p_priv->in_urbs[j] = keyspan_setup_urb
-                               (serial, endp, USB_DIR_IN, port,
-                                p_priv->in_buffer[j], 64,
-                                cback->indat_callback);
-               }
-               for (; j < 2; ++j)
-                       p_priv->in_urbs[j] = NULL;
-
-               /* outdat endpoints also have flip */
-               endp = d_details->outdat_endpoints[i];
-               for (j = 0; j <= d_details->outdat_endp_flip; ++j, ++endp) {
-                       p_priv->out_urbs[j] = keyspan_setup_urb
-                               (serial, endp, USB_DIR_OUT, port,
-                                p_priv->out_buffer[j], 64,
-                                cback->outdat_callback);
-               }
-               for (; j < 2; ++j)
-                       p_priv->out_urbs[j] = NULL;
-
-               /* inack endpoint */
-               p_priv->inack_urb = keyspan_setup_urb
-                       (serial, d_details->inack_endpoints[i], USB_DIR_IN,
-                        port, p_priv->inack_buffer, 1, cback->inack_callback);
-
-               /* outcont endpoint */
-               p_priv->outcont_urb = keyspan_setup_urb
-                       (serial, d_details->outcont_endpoints[i], USB_DIR_OUT,
-                        port, p_priv->outcont_buffer, 64,
-                        cback->outcont_callback);
-       }
 }
 
 /* usa19 function doesn't require prescaler */
@@ -2407,9 +2364,7 @@ static void keyspan_send_setup(struct usb_serial_port *port, int reset_port)
 static int keyspan_startup(struct usb_serial *serial)
 {
        int                             i, err;
-       struct usb_serial_port          *port;
        struct keyspan_serial_private   *s_priv;
-       struct keyspan_port_private     *p_priv;
        const struct keyspan_device_details     *d_details;
 
        for (i = 0; (d_details = keyspan_devices[i]) != NULL; ++i)
@@ -2432,19 +2387,6 @@ static int keyspan_startup(struct usb_serial *serial)
        s_priv->device_details = d_details;
        usb_set_serial_data(serial, s_priv);
 
-       /* Now setup per port private data */
-       for (i = 0; i < serial->num_ports; i++) {
-               port = serial->port[i];
-               p_priv = kzalloc(sizeof(struct keyspan_port_private),
-                                                               GFP_KERNEL);
-               if (!p_priv) {
-                       dev_dbg(&port->dev, "%s - kmalloc for keyspan_port_private (%d) failed!.\n", __func__, i);
-                       return 1;
-               }
-               p_priv->device_details = d_details;
-               usb_set_serial_port_data(port, p_priv);
-       }
-
        keyspan_setup_urbs(serial);
 
        if (s_priv->instat_urb != NULL) {
@@ -2463,59 +2405,111 @@ static int keyspan_startup(struct usb_serial *serial)
 
 static void keyspan_disconnect(struct usb_serial *serial)
 {
-       int                             i, j;
-       struct usb_serial_port          *port;
-       struct keyspan_serial_private   *s_priv;
-       struct keyspan_port_private     *p_priv;
+       struct keyspan_serial_private *s_priv;
 
        s_priv = usb_get_serial_data(serial);
 
-       /* Stop reading/writing urbs */
        stop_urb(s_priv->instat_urb);
        stop_urb(s_priv->glocont_urb);
        stop_urb(s_priv->indat_urb);
-       for (i = 0; i < serial->num_ports; ++i) {
-               port = serial->port[i];
-               p_priv = usb_get_serial_port_data(port);
-               stop_urb(p_priv->inack_urb);
-               stop_urb(p_priv->outcont_urb);
-               for (j = 0; j < 2; j++) {
-                       stop_urb(p_priv->in_urbs[j]);
-                       stop_urb(p_priv->out_urbs[j]);
-               }
-       }
+}
+
+static void keyspan_release(struct usb_serial *serial)
+{
+       struct keyspan_serial_private *s_priv;
+
+       s_priv = usb_get_serial_data(serial);
 
-       /* Now free them */
        usb_free_urb(s_priv->instat_urb);
        usb_free_urb(s_priv->indat_urb);
        usb_free_urb(s_priv->glocont_urb);
-       for (i = 0; i < serial->num_ports; ++i) {
-               port = serial->port[i];
-               p_priv = usb_get_serial_port_data(port);
-               usb_free_urb(p_priv->inack_urb);
-               usb_free_urb(p_priv->outcont_urb);
-               for (j = 0; j < 2; j++) {
-                       usb_free_urb(p_priv->in_urbs[j]);
-                       usb_free_urb(p_priv->out_urbs[j]);
-               }
-       }
+
+       kfree(s_priv);
 }
 
-static void keyspan_release(struct usb_serial *serial)
+static int keyspan_port_probe(struct usb_serial_port *port)
 {
-       int                             i;
-       struct usb_serial_port          *port;
-       struct keyspan_serial_private   *s_priv;
+       struct usb_serial *serial = port->serial;
+       struct keyspan_serial_private *s_priv;
+       struct keyspan_port_private *p_priv;
+       const struct keyspan_device_details *d_details;
+       struct callbacks *cback;
+       int endp;
+       int port_num;
+       int i;
 
        s_priv = usb_get_serial_data(serial);
+       d_details = s_priv->device_details;
 
-       kfree(s_priv);
+       p_priv = kzalloc(sizeof(*p_priv), GFP_KERNEL);
+       if (!p_priv)
+               return -ENOMEM;
 
-       /* Now free per port private data */
-       for (i = 0; i < serial->num_ports; i++) {
-               port = serial->port[i];
-               kfree(usb_get_serial_port_data(port));
+       p_priv->device_details = d_details;
+
+       /* Setup values for the various callback routines */
+       cback = &keyspan_callbacks[d_details->msg_format];
+
+       port_num = port->number - port->serial->minor;
+
+       /* Do indat endpoints first, once for each flip */
+       endp = d_details->indat_endpoints[port_num];
+       for (i = 0; i <= d_details->indat_endp_flip; ++i, ++endp) {
+               p_priv->in_urbs[i] = keyspan_setup_urb(serial, endp,
+                                               USB_DIR_IN, port,
+                                               p_priv->in_buffer[i], 64,
+                                               cback->indat_callback);
+       }
+       /* outdat endpoints also have flip */
+       endp = d_details->outdat_endpoints[port_num];
+       for (i = 0; i <= d_details->outdat_endp_flip; ++i, ++endp) {
+               p_priv->out_urbs[i] = keyspan_setup_urb(serial, endp,
+                                               USB_DIR_OUT, port,
+                                               p_priv->out_buffer[i], 64,
+                                               cback->outdat_callback);
+       }
+       /* inack endpoint */
+       p_priv->inack_urb = keyspan_setup_urb(serial,
+                                       d_details->inack_endpoints[port_num],
+                                       USB_DIR_IN, port,
+                                       p_priv->inack_buffer, 1,
+                                       cback->inack_callback);
+       /* outcont endpoint */
+       p_priv->outcont_urb = keyspan_setup_urb(serial,
+                                       d_details->outcont_endpoints[port_num],
+                                       USB_DIR_OUT, port,
+                                       p_priv->outcont_buffer, 64,
+                                        cback->outcont_callback);
+
+       usb_set_serial_port_data(port, p_priv);
+
+       return 0;
+}
+
+static int keyspan_port_remove(struct usb_serial_port *port)
+{
+       struct keyspan_port_private *p_priv;
+       int i;
+
+       p_priv = usb_get_serial_port_data(port);
+
+       stop_urb(p_priv->inack_urb);
+       stop_urb(p_priv->outcont_urb);
+       for (i = 0; i < 2; i++) {
+               stop_urb(p_priv->in_urbs[i]);
+               stop_urb(p_priv->out_urbs[i]);
+       }
+
+       usb_free_urb(p_priv->inack_urb);
+       usb_free_urb(p_priv->outcont_urb);
+       for (i = 0; i < 2; i++) {
+               usb_free_urb(p_priv->in_urbs[i]);
+               usb_free_urb(p_priv->out_urbs[i]);
        }
+
+       kfree(p_priv);
+
+       return 0;
 }
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
index 0a8a40b5711e8d288a222aef5c86573c1a674cc1..0273dda303a4672f348175b6787b03c356a62b72 100644 (file)
@@ -42,6 +42,8 @@ static void keyspan_dtr_rts           (struct usb_serial_port *port, int on);
 static int  keyspan_startup            (struct usb_serial *serial);
 static void keyspan_disconnect         (struct usb_serial *serial);
 static void keyspan_release            (struct usb_serial *serial);
+static int keyspan_port_probe(struct usb_serial_port *port);
+static int keyspan_port_remove(struct usb_serial_port *port);
 static int  keyspan_write_room         (struct tty_struct *tty);
 
 static int  keyspan_write              (struct tty_struct *tty,
@@ -567,6 +569,8 @@ static struct usb_serial_driver keyspan_1port_device = {
        .attach                 = keyspan_startup,
        .disconnect             = keyspan_disconnect,
        .release                = keyspan_release,
+       .port_probe             = keyspan_port_probe,
+       .port_remove            = keyspan_port_remove,
 };
 
 static struct usb_serial_driver keyspan_2port_device = {
@@ -589,6 +593,8 @@ static struct usb_serial_driver keyspan_2port_device = {
        .attach                 = keyspan_startup,
        .disconnect             = keyspan_disconnect,
        .release                = keyspan_release,
+       .port_probe             = keyspan_port_probe,
+       .port_remove            = keyspan_port_remove,
 };
 
 static struct usb_serial_driver keyspan_4port_device = {
@@ -611,6 +617,8 @@ static struct usb_serial_driver keyspan_4port_device = {
        .attach                 = keyspan_startup,
        .disconnect             = keyspan_disconnect,
        .release                = keyspan_release,
+       .port_probe             = keyspan_port_probe,
+       .port_remove            = keyspan_port_remove,
 };
 
 static struct usb_serial_driver * const serial_drivers[] = {
index f3947712e1375db3ee407a5efa20a1acad3d3c9d..8a2081004107977dc929d586ffda41fdf34abf06 100644 (file)
@@ -49,7 +49,8 @@
  * Function prototypes
  */
 static int  mct_u232_startup(struct usb_serial *serial);
-static void mct_u232_release(struct usb_serial *serial);
+static int  mct_u232_port_probe(struct usb_serial_port *port);
+static int  mct_u232_port_remove(struct usb_serial_port *remove);
 static int  mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port);
 static void mct_u232_close(struct usb_serial_port *port);
 static void mct_u232_dtr_rts(struct usb_serial_port *port, int on);
@@ -99,7 +100,8 @@ static struct usb_serial_driver mct_u232_device = {
        .tiocmget =          mct_u232_tiocmget,
        .tiocmset =          mct_u232_tiocmset,
        .attach =            mct_u232_startup,
-       .release =           mct_u232_release,
+       .port_probe =        mct_u232_port_probe,
+       .port_remove =       mct_u232_port_remove,
        .ioctl =             mct_u232_ioctl,
        .get_icount =        mct_u232_get_icount,
 };
@@ -388,18 +390,8 @@ static void mct_u232_msr_to_state(struct usb_serial_port *port,
 
 static int mct_u232_startup(struct usb_serial *serial)
 {
-       struct mct_u232_private *priv;
        struct usb_serial_port *port, *rport;
 
-       priv = kzalloc(sizeof(struct mct_u232_private), GFP_KERNEL);
-       if (!priv)
-               return -ENOMEM;
-       spin_lock_init(&priv->lock);
-       init_waitqueue_head(&priv->msr_wait);
-       usb_set_serial_port_data(serial->port[0], priv);
-
-       init_waitqueue_head(&serial->port[0]->write_wait);
-
        /* Puh, that's dirty */
        port = serial->port[0];
        rport = serial->port[1];
@@ -412,18 +404,31 @@ static int mct_u232_startup(struct usb_serial *serial)
        return 0;
 } /* mct_u232_startup */
 
+static int mct_u232_port_probe(struct usb_serial_port *port)
+{
+       struct mct_u232_private *priv;
+
+       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       spin_lock_init(&priv->lock);
+       init_waitqueue_head(&priv->msr_wait);
+
+       usb_set_serial_port_data(port, priv);
 
-static void mct_u232_release(struct usb_serial *serial)
+       return 0;
+}
+
+static int mct_u232_port_remove(struct usb_serial_port *port)
 {
        struct mct_u232_private *priv;
-       int i;
 
-       for (i = 0; i < serial->num_ports; ++i) {
-               /* My special items, the standard routines free my urbs */
-               priv = usb_get_serial_port_data(serial->port[i]);
-               kfree(priv);
-       }
-} /* mct_u232_release */
+       priv = usb_get_serial_port_data(port);
+       kfree(priv);
+
+       return 0;
+}
 
 static int  mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port)
 {
@@ -515,12 +520,14 @@ static void mct_u232_dtr_rts(struct usb_serial_port *port, int on)
 
 static void mct_u232_close(struct usb_serial_port *port)
 {
-       if (port->serial->dev) {
-               /* shutdown our urbs */
-               usb_kill_urb(port->write_urb);
-               usb_kill_urb(port->read_urb);
-               usb_kill_urb(port->interrupt_in_urb);
-       }
+       /*
+        * Must kill the read urb as it is actually an interrupt urb, which
+        * generic close thus fails to kill.
+        */
+       usb_kill_urb(port->read_urb);
+       usb_kill_urb(port->interrupt_in_urb);
+
+       usb_serial_generic_close(port);
 } /* mct_u232_close */
 
 
index 0b257ddffbdbd903da48db51746bee3da9ebe4d6..6f29c74eb76925098a9cab841142c955c6d3a725 100644 (file)
@@ -179,16 +179,13 @@ static void metrousb_cleanup(struct usb_serial_port *port)
 {
        dev_dbg(&port->dev, "%s\n", __func__);
 
-       if (port->serial->dev) {
-               /* Shutdown any interrupt in urbs. */
-               if (port->interrupt_in_urb) {
-                       usb_unlink_urb(port->interrupt_in_urb);
-                       usb_kill_urb(port->interrupt_in_urb);
-               }
-
-               /* Send deactivate cmd to device */
+       usb_unlink_urb(port->interrupt_in_urb);
+       usb_kill_urb(port->interrupt_in_urb);
+
+       mutex_lock(&port->serial->disc_mutex);
+       if (!port->serial->disconnected)
                metrousb_send_unidirectional_cmd(UNI_CMD_CLOSE, port);
-       }
+       mutex_unlock(&port->serial->disc_mutex);
 }
 
 static int metrousb_open(struct tty_struct *tty, struct usb_serial_port *port)
@@ -271,51 +268,27 @@ static int metrousb_set_modem_ctrl(struct usb_serial *serial, unsigned int contr
        return retval;
 }
 
-static void metrousb_shutdown(struct usb_serial *serial)
+static int metrousb_port_probe(struct usb_serial_port *port)
 {
-       int i = 0;
+       struct metrousb_private *metro_priv;
 
-       dev_dbg(&serial->dev->dev, "%s\n", __func__);
+       metro_priv = kzalloc(sizeof(*metro_priv), GFP_KERNEL);
+       if (!metro_priv)
+               return -ENOMEM;
 
-       /* Stop reading and writing on all ports. */
-       for (i = 0; i < serial->num_ports; ++i) {
-               /* Close any open urbs. */
-               metrousb_cleanup(serial->port[i]);
+       spin_lock_init(&metro_priv->lock);
 
-               /* Free memory. */
-               kfree(usb_get_serial_port_data(serial->port[i]));
-               usb_set_serial_port_data(serial->port[i], NULL);
+       usb_set_serial_port_data(port, metro_priv);
 
-               dev_dbg(&serial->dev->dev, "%s - freed port number=%d\n",
-                       __func__, serial->port[i]->number);
-       }
+       return 0;
 }
 
-static int metrousb_startup(struct usb_serial *serial)
+static int metrousb_port_remove(struct usb_serial_port *port)
 {
        struct metrousb_private *metro_priv;
-       struct usb_serial_port *port;
-       int i = 0;
 
-       dev_dbg(&serial->dev->dev, "%s\n", __func__);
-
-       /* Loop through the serial ports setting up the private structures.
-        * Currently we only use one port. */
-       for (i = 0; i < serial->num_ports; ++i) {
-               port = serial->port[i];
-
-               /* Declare memory. */
-               metro_priv = kzalloc(sizeof(struct metrousb_private), GFP_KERNEL);
-               if (!metro_priv)
-                       return -ENOMEM;
-
-               /* Initialize memory. */
-               spin_lock_init(&metro_priv->lock);
-               usb_set_serial_port_data(port, metro_priv);
-
-               dev_dbg(&serial->dev->dev, "%s - port number=%d\n ",
-                       __func__, port->number);
-       }
+       metro_priv = usb_get_serial_port_data(port);
+       kfree(metro_priv);
 
        return 0;
 }
@@ -414,8 +387,8 @@ static struct usb_serial_driver metrousb_device = {
        .close                  = metrousb_cleanup,
        .read_int_callback      = metrousb_read_int_callback,
        .write_int_callback     = metrousb_write_int_callback,
-       .attach                 = metrousb_startup,
-       .release                = metrousb_shutdown,
+       .port_probe             = metrousb_port_probe,
+       .port_remove            = metrousb_port_remove,
        .throttle               = metrousb_throttle,
        .unthrottle             = metrousb_unthrottle,
        .tiocmget               = metrousb_tiocmget,
index 1bf1ad0666667a9c31284c658814b651d91d2c66..75267421aad85636d480b732a507a176e874814f 100644 (file)
@@ -1966,9 +1966,7 @@ static int mos7720_ioctl(struct tty_struct *tty,
 
 static int mos7720_startup(struct usb_serial *serial)
 {
-       struct moschip_port *mos7720_port;
        struct usb_device *dev;
-       int i;
        char data;
        u16 product;
        int ret_val;
@@ -1999,29 +1997,6 @@ static int mos7720_startup(struct usb_serial *serial)
                serial->port[1]->interrupt_in_buffer = NULL;
        }
 
-
-       /* set up serial port private structures */
-       for (i = 0; i < serial->num_ports; ++i) {
-               mos7720_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL);
-               if (mos7720_port == NULL) {
-                       dev_err(&dev->dev, "%s - Out of memory\n", __func__);
-                       return -ENOMEM;
-               }
-
-               /* Initialize all port interrupt end point to port 0 int
-                * endpoint.  Our device has only one interrupt endpoint
-                * common to all ports */
-               serial->port[i]->interrupt_in_endpointAddress =
-                               serial->port[0]->interrupt_in_endpointAddress;
-
-               mos7720_port->port = serial->port[i];
-               usb_set_serial_port_data(serial->port[i], mos7720_port);
-
-               dev_dbg(&dev->dev, "port number is %d\n", serial->port[i]->number);
-               dev_dbg(&dev->dev, "serial number is %d\n", serial->minor);
-       }
-
-
        /* setting configuration feature to one */
        usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
                        (__u8)0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5*HZ);
@@ -2049,8 +2024,6 @@ static int mos7720_startup(struct usb_serial *serial)
 
 static void mos7720_release(struct usb_serial *serial)
 {
-       int i;
-
 #ifdef CONFIG_USB_SERIAL_MOS7715_PARPORT
        /* close the parallel port */
 
@@ -2089,9 +2062,36 @@ static void mos7720_release(struct usb_serial *serial)
                kref_put(&mos_parport->ref_count, destroy_mos_parport);
        }
 #endif
-       /* free private structure allocated for serial port */
-       for (i = 0; i < serial->num_ports; ++i)
-               kfree(usb_get_serial_port_data(serial->port[i]));
+}
+
+static int mos7720_port_probe(struct usb_serial_port *port)
+{
+       struct moschip_port *mos7720_port;
+
+       mos7720_port = kzalloc(sizeof(*mos7720_port), GFP_KERNEL);
+       if (!mos7720_port)
+               return -ENOMEM;
+
+       /* Initialize all port interrupt end point to port 0 int endpoint.
+        * Our device has only one interrupt endpoint common to all ports.
+        */
+       port->interrupt_in_endpointAddress =
+               port->serial->port[0]->interrupt_in_endpointAddress;
+       mos7720_port->port = port;
+
+       usb_set_serial_port_data(port, mos7720_port);
+
+       return 0;
+}
+
+static int mos7720_port_remove(struct usb_serial_port *port)
+{
+       struct moschip_port *mos7720_port;
+
+       mos7720_port = usb_get_serial_port_data(port);
+       kfree(mos7720_port);
+
+       return 0;
 }
 
 static struct usb_serial_driver moschip7720_2port_driver = {
@@ -2109,6 +2109,8 @@ static struct usb_serial_driver moschip7720_2port_driver = {
        .probe                  = mos77xx_probe,
        .attach                 = mos7720_startup,
        .release                = mos7720_release,
+       .port_probe             = mos7720_port_probe,
+       .port_remove            = mos7720_port_remove,
        .ioctl                  = mos7720_ioctl,
        .tiocmget               = mos7720_tiocmget,
        .tiocmset               = mos7720_tiocmset,
index d6d4eeca8c68390ef4555e455cbfea66c68038b9..1cf3375ec1afb12fbea2314a63539ced2c36b221 100644 (file)
@@ -218,12 +218,10 @@ struct moschip_port {
        int port_num;           /*Actual port number in the device(1,2,etc) */
        struct urb *write_urb;  /* write URB for this port */
        struct urb *read_urb;   /* read URB for this port */
-       struct urb *int_urb;
        __u8 shadowLCR;         /* last LCR value received */
        __u8 shadowMCR;         /* last MCR value received */
        char open;
        char open_ports;
-       char zombie;
        wait_queue_head_t wait_chase;   /* for handling sleeping while waiting for chase to finish */
        wait_queue_head_t delta_msr_wait;       /* for handling sleeping while waiting for msr change to happen */
        int delta_msr_cond;
@@ -478,7 +476,6 @@ static void mos7840_control_callback(struct urb *urb)
        struct moschip_port *mos7840_port;
        struct device *dev = &urb->dev->dev;
        __u8 regval = 0x0;
-       int result = 0;
        int status = urb->status;
 
        mos7840_port = urb->context;
@@ -495,7 +492,7 @@ static void mos7840_control_callback(struct urb *urb)
                return;
        default:
                dev_dbg(dev, "%s - nonzero urb status received: %d\n", __func__, status);
-               goto exit;
+               return;
        }
 
        dev_dbg(dev, "%s urb buffer size is %d\n", __func__, urb->actual_length);
@@ -508,16 +505,6 @@ static void mos7840_control_callback(struct urb *urb)
                mos7840_handle_new_msr(mos7840_port, regval);
        else if (mos7840_port->MsrLsr == 1)
                mos7840_handle_new_lsr(mos7840_port, regval);
-
-exit:
-       spin_lock(&mos7840_port->pool_lock);
-       if (!mos7840_port->zombie)
-               result = usb_submit_urb(mos7840_port->int_urb, GFP_ATOMIC);
-       spin_unlock(&mos7840_port->pool_lock);
-       if (result) {
-               dev_err(dev, "%s - Error %d submitting interrupt urb\n",
-                       __func__, result);
-       }
 }
 
 static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg,
@@ -686,14 +673,7 @@ static void mos7840_interrupt_callback(struct urb *urb)
                                        wreg = MODEM_STATUS_REGISTER;
                                        break;
                                }
-                               spin_lock(&mos7840_port->pool_lock);
-                               if (!mos7840_port->zombie) {
-                                       rv = mos7840_get_reg(mos7840_port, wval, wreg, &Data);
-                               } else {
-                                       spin_unlock(&mos7840_port->pool_lock);
-                                       return;
-                               }
-                               spin_unlock(&mos7840_port->pool_lock);
+                               rv = mos7840_get_reg(mos7840_port, wval, wreg, &Data);
                        }
                }
        }
@@ -2347,309 +2327,249 @@ static int mos7840_calc_num_ports(struct usb_serial *serial)
        return mos7840_num_ports;
 }
 
-/****************************************************************************
- * mos7840_startup
- ****************************************************************************/
-
-static int mos7840_startup(struct usb_serial *serial)
+static int mos7840_port_probe(struct usb_serial_port *port)
 {
+       struct usb_serial *serial = port->serial;
        struct moschip_port *mos7840_port;
-       struct usb_device *dev;
-       int i, status;
+       int status;
+       int pnum;
        __u16 Data;
 
-       dev = serial->dev;
-
        /* we set up the pointers to the endpoints in the mos7840_open *
         * function, as the structures aren't created yet.             */
 
-       /* set up port private structures */
-       for (i = 0; i < serial->num_ports; ++i) {
-               dev_dbg(&dev->dev, "mos7840_startup: configuring port %d............\n", i);
-               mos7840_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL);
-               if (mos7840_port == NULL) {
-                       dev_err(&dev->dev, "%s - Out of memory\n", __func__);
-                       status = -ENOMEM;
-                       i--; /* don't follow NULL pointer cleaning up */
-                       goto error;
-               }
-
-               /* Initialize all port interrupt end point to port 0 int
-                * endpoint. Our device has only one interrupt end point
-                * common to all port */
-
-               mos7840_port->port = serial->port[i];
-               mos7840_set_port_private(serial->port[i], mos7840_port);
-               spin_lock_init(&mos7840_port->pool_lock);
-
-               /* minor is not initialised until later by
-                * usb-serial.c:get_free_serial() and cannot therefore be used
-                * to index device instances */
-               mos7840_port->port_num = i + 1;
-               dev_dbg(&dev->dev, "serial->port[i]->number = %d\n", serial->port[i]->number);
-               dev_dbg(&dev->dev, "serial->port[i]->serial->minor = %d\n", serial->port[i]->serial->minor);
-               dev_dbg(&dev->dev, "mos7840_port->port_num = %d\n", mos7840_port->port_num);
-               dev_dbg(&dev->dev, "serial->minor = %d\n", serial->minor);
-
-               if (mos7840_port->port_num == 1) {
-                       mos7840_port->SpRegOffset = 0x0;
-                       mos7840_port->ControlRegOffset = 0x1;
-                       mos7840_port->DcrRegOffset = 0x4;
-               } else if ((mos7840_port->port_num == 2)
-                          && (serial->num_ports == 4)) {
-                       mos7840_port->SpRegOffset = 0x8;
-                       mos7840_port->ControlRegOffset = 0x9;
-                       mos7840_port->DcrRegOffset = 0x16;
-               } else if ((mos7840_port->port_num == 2)
-                          && (serial->num_ports == 2)) {
-                       mos7840_port->SpRegOffset = 0xa;
-                       mos7840_port->ControlRegOffset = 0xb;
-                       mos7840_port->DcrRegOffset = 0x19;
-               } else if ((mos7840_port->port_num == 3)
-                          && (serial->num_ports == 4)) {
-                       mos7840_port->SpRegOffset = 0xa;
-                       mos7840_port->ControlRegOffset = 0xb;
-                       mos7840_port->DcrRegOffset = 0x19;
-               } else if ((mos7840_port->port_num == 4)
-                          && (serial->num_ports == 4)) {
-                       mos7840_port->SpRegOffset = 0xc;
-                       mos7840_port->ControlRegOffset = 0xd;
-                       mos7840_port->DcrRegOffset = 0x1c;
-               }
-               mos7840_dump_serial_port(serial->port[i], mos7840_port);
-               mos7840_set_port_private(serial->port[i], mos7840_port);
+       pnum = port->number - serial->minor;
 
-               /* enable rx_disable bit in control register */
-               status = mos7840_get_reg_sync(serial->port[i],
-                                mos7840_port->ControlRegOffset, &Data);
-               if (status < 0) {
-                       dev_dbg(&dev->dev, "Reading ControlReg failed status-0x%x\n", status);
-                       break;
-               } else
-                       dev_dbg(&dev->dev, "ControlReg Reading success val is %x, status%d\n", Data, status);
-               Data |= 0x08;   /* setting driver done bit */
-               Data |= 0x04;   /* sp1_bit to have cts change reflect in
-                                  modem status reg */
-
-               /* Data |= 0x20; //rx_disable bit */
-               status = mos7840_set_reg_sync(serial->port[i],
-                                        mos7840_port->ControlRegOffset, Data);
-               if (status < 0) {
-                       dev_dbg(&dev->dev, "Writing ControlReg failed(rx_disable) status-0x%x\n", status);
-                       break;
-               } else
-                       dev_dbg(&dev->dev, "ControlReg Writing success(rx_disable) status%d\n", status);
+       dev_dbg(&port->dev, "mos7840_startup: configuring port %d\n", pnum);
+       mos7840_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL);
+       if (mos7840_port == NULL) {
+               dev_err(&port->dev, "%s - Out of memory\n", __func__);
+               return -ENOMEM;
+       }
 
-               /* Write default values in DCR (i.e 0x01 in DCR0, 0x05 in DCR2
-                  and 0x24 in DCR3 */
-               Data = 0x01;
-               status = mos7840_set_reg_sync(serial->port[i],
-                        (__u16) (mos7840_port->DcrRegOffset + 0), Data);
-               if (status < 0) {
-                       dev_dbg(&dev->dev, "Writing DCR0 failed status-0x%x\n", status);
-                       break;
-               } else
-                       dev_dbg(&dev->dev, "DCR0 Writing success status%d\n", status);
+       /* Initialize all port interrupt end point to port 0 int
+        * endpoint. Our device has only one interrupt end point
+        * common to all port */
+
+       mos7840_port->port = port;
+       mos7840_set_port_private(port, mos7840_port);
+       spin_lock_init(&mos7840_port->pool_lock);
+
+       /* minor is not initialised until later by
+        * usb-serial.c:get_free_serial() and cannot therefore be used
+        * to index device instances */
+       mos7840_port->port_num = pnum + 1;
+       dev_dbg(&port->dev, "port->number = %d\n", port->number);
+       dev_dbg(&port->dev, "port->serial->minor = %d\n", port->serial->minor);
+       dev_dbg(&port->dev, "mos7840_port->port_num = %d\n", mos7840_port->port_num);
+       dev_dbg(&port->dev, "serial->minor = %d\n", serial->minor);
+
+       if (mos7840_port->port_num == 1) {
+               mos7840_port->SpRegOffset = 0x0;
+               mos7840_port->ControlRegOffset = 0x1;
+               mos7840_port->DcrRegOffset = 0x4;
+       } else if ((mos7840_port->port_num == 2) && (serial->num_ports == 4)) {
+               mos7840_port->SpRegOffset = 0x8;
+               mos7840_port->ControlRegOffset = 0x9;
+               mos7840_port->DcrRegOffset = 0x16;
+       } else if ((mos7840_port->port_num == 2) && (serial->num_ports == 2)) {
+               mos7840_port->SpRegOffset = 0xa;
+               mos7840_port->ControlRegOffset = 0xb;
+               mos7840_port->DcrRegOffset = 0x19;
+       } else if ((mos7840_port->port_num == 3) && (serial->num_ports == 4)) {
+               mos7840_port->SpRegOffset = 0xa;
+               mos7840_port->ControlRegOffset = 0xb;
+               mos7840_port->DcrRegOffset = 0x19;
+       } else if ((mos7840_port->port_num == 4) && (serial->num_ports == 4)) {
+               mos7840_port->SpRegOffset = 0xc;
+               mos7840_port->ControlRegOffset = 0xd;
+               mos7840_port->DcrRegOffset = 0x1c;
+       }
+       mos7840_dump_serial_port(port, mos7840_port);
+       mos7840_set_port_private(port, mos7840_port);
+
+       /* enable rx_disable bit in control register */
+       status = mos7840_get_reg_sync(port,
+                       mos7840_port->ControlRegOffset, &Data);
+       if (status < 0) {
+               dev_dbg(&port->dev, "Reading ControlReg failed status-0x%x\n", status);
+               goto out;
+       } else
+               dev_dbg(&port->dev, "ControlReg Reading success val is %x, status%d\n", Data, status);
+       Data |= 0x08;   /* setting driver done bit */
+       Data |= 0x04;   /* sp1_bit to have cts change reflect in
+                          modem status reg */
 
-               Data = 0x05;
-               status = mos7840_set_reg_sync(serial->port[i],
-                        (__u16) (mos7840_port->DcrRegOffset + 1), Data);
-               if (status < 0) {
-                       dev_dbg(&dev->dev, "Writing DCR1 failed status-0x%x\n", status);
-                       break;
-               } else
-                       dev_dbg(&dev->dev, "DCR1 Writing success status%d\n", status);
+       /* Data |= 0x20; //rx_disable bit */
+       status = mos7840_set_reg_sync(port,
+                       mos7840_port->ControlRegOffset, Data);
+       if (status < 0) {
+               dev_dbg(&port->dev, "Writing ControlReg failed(rx_disable) status-0x%x\n", status);
+               goto out;
+       } else
+               dev_dbg(&port->dev, "ControlReg Writing success(rx_disable) status%d\n", status);
 
-               Data = 0x24;
-               status = mos7840_set_reg_sync(serial->port[i],
-                        (__u16) (mos7840_port->DcrRegOffset + 2), Data);
-               if (status < 0) {
-                       dev_dbg(&dev->dev, "Writing DCR2 failed status-0x%x\n", status);
-                       break;
-               } else
-                       dev_dbg(&dev->dev, "DCR2 Writing success status%d\n", status);
+       /* Write default values in DCR (i.e 0x01 in DCR0, 0x05 in DCR2
+          and 0x24 in DCR3 */
+       Data = 0x01;
+       status = mos7840_set_reg_sync(port,
+                       (__u16) (mos7840_port->DcrRegOffset + 0), Data);
+       if (status < 0) {
+               dev_dbg(&port->dev, "Writing DCR0 failed status-0x%x\n", status);
+               goto out;
+       } else
+               dev_dbg(&port->dev, "DCR0 Writing success status%d\n", status);
 
-               /* write values in clkstart0x0 and clkmulti 0x20 */
-               Data = 0x0;
-               status = mos7840_set_reg_sync(serial->port[i],
-                                        CLK_START_VALUE_REGISTER, Data);
-               if (status < 0) {
-                       dev_dbg(&dev->dev, "Writing CLK_START_VALUE_REGISTER failed status-0x%x\n", status);
-                       break;
-               } else
-                       dev_dbg(&dev->dev, "CLK_START_VALUE_REGISTER Writing success status%d\n", status);
+       Data = 0x05;
+       status = mos7840_set_reg_sync(port,
+                       (__u16) (mos7840_port->DcrRegOffset + 1), Data);
+       if (status < 0) {
+               dev_dbg(&port->dev, "Writing DCR1 failed status-0x%x\n", status);
+               goto out;
+       } else
+               dev_dbg(&port->dev, "DCR1 Writing success status%d\n", status);
 
-               Data = 0x20;
-               status = mos7840_set_reg_sync(serial->port[i],
-                                       CLK_MULTI_REGISTER, Data);
-               if (status < 0) {
-                       dev_dbg(&dev->dev, "Writing CLK_MULTI_REGISTER failed status-0x%x\n", status);
-                       goto error;
-               } else
-                       dev_dbg(&dev->dev, "CLK_MULTI_REGISTER Writing success status%d\n", status);
+       Data = 0x24;
+       status = mos7840_set_reg_sync(port,
+                       (__u16) (mos7840_port->DcrRegOffset + 2), Data);
+       if (status < 0) {
+               dev_dbg(&port->dev, "Writing DCR2 failed status-0x%x\n", status);
+               goto out;
+       } else
+               dev_dbg(&port->dev, "DCR2 Writing success status%d\n", status);
 
-               /* write value 0x0 to scratchpad register */
-               Data = 0x00;
-               status = mos7840_set_uart_reg(serial->port[i],
-                                               SCRATCH_PAD_REGISTER, Data);
-               if (status < 0) {
-                       dev_dbg(&dev->dev, "Writing SCRATCH_PAD_REGISTER failed status-0x%x\n", status);
-                       break;
-               } else
-                       dev_dbg(&dev->dev, "SCRATCH_PAD_REGISTER Writing success status%d\n", status);
+       /* write values in clkstart0x0 and clkmulti 0x20 */
+       Data = 0x0;
+       status = mos7840_set_reg_sync(port, CLK_START_VALUE_REGISTER, Data);
+       if (status < 0) {
+               dev_dbg(&port->dev, "Writing CLK_START_VALUE_REGISTER failed status-0x%x\n", status);
+               goto out;
+       } else
+               dev_dbg(&port->dev, "CLK_START_VALUE_REGISTER Writing success status%d\n", status);
 
-               /* Zero Length flag register */
-               if ((mos7840_port->port_num != 1)
-                   && (serial->num_ports == 2)) {
+       Data = 0x20;
+       status = mos7840_set_reg_sync(port, CLK_MULTI_REGISTER, Data);
+       if (status < 0) {
+               dev_dbg(&port->dev, "Writing CLK_MULTI_REGISTER failed status-0x%x\n", status);
+               goto error;
+       } else
+               dev_dbg(&port->dev, "CLK_MULTI_REGISTER Writing success status%d\n", status);
 
-                       Data = 0xff;
-                       status = mos7840_set_reg_sync(serial->port[i],
-                                     (__u16) (ZLP_REG1 +
-                                     ((__u16)mos7840_port->port_num)), Data);
-                       dev_dbg(&dev->dev, "ZLIP offset %x\n",
+       /* write value 0x0 to scratchpad register */
+       Data = 0x00;
+       status = mos7840_set_uart_reg(port, SCRATCH_PAD_REGISTER, Data);
+       if (status < 0) {
+               dev_dbg(&port->dev, "Writing SCRATCH_PAD_REGISTER failed status-0x%x\n", status);
+               goto out;
+       } else
+               dev_dbg(&port->dev, "SCRATCH_PAD_REGISTER Writing success status%d\n", status);
+
+       /* Zero Length flag register */
+       if ((mos7840_port->port_num != 1) && (serial->num_ports == 2)) {
+               Data = 0xff;
+               status = mos7840_set_reg_sync(port,
+                               (__u16) (ZLP_REG1 +
+                                       ((__u16)mos7840_port->port_num)), Data);
+               dev_dbg(&port->dev, "ZLIP offset %x\n",
                                (__u16)(ZLP_REG1 + ((__u16) mos7840_port->port_num)));
-                       if (status < 0) {
-                               dev_dbg(&dev->dev, "Writing ZLP_REG%d failed status-0x%x\n", i + 2, status);
-                               break;
-                       } else
-                               dev_dbg(&dev->dev, "ZLP_REG%d Writing success status%d\n", i + 2, status);
-               } else {
-                       Data = 0xff;
-                       status = mos7840_set_reg_sync(serial->port[i],
-                             (__u16) (ZLP_REG1 +
-                             ((__u16)mos7840_port->port_num) - 0x1), Data);
-                       dev_dbg(&dev->dev, "ZLIP offset %x\n",
+               if (status < 0) {
+                       dev_dbg(&port->dev, "Writing ZLP_REG%d failed status-0x%x\n", pnum + 2, status);
+                       goto out;
+               } else
+                       dev_dbg(&port->dev, "ZLP_REG%d Writing success status%d\n", pnum + 2, status);
+       } else {
+               Data = 0xff;
+               status = mos7840_set_reg_sync(port,
+                               (__u16) (ZLP_REG1 +
+                                       ((__u16)mos7840_port->port_num) - 0x1), Data);
+               dev_dbg(&port->dev, "ZLIP offset %x\n",
                                (__u16)(ZLP_REG1 + ((__u16) mos7840_port->port_num) - 0x1));
-                       if (status < 0) {
-                               dev_dbg(&dev->dev, "Writing ZLP_REG%d failed status-0x%x\n", i + 1, status);
-                               break;
-                       } else
-                               dev_dbg(&dev->dev, "ZLP_REG%d Writing success status%d\n", i + 1, status);
+               if (status < 0) {
+                       dev_dbg(&port->dev, "Writing ZLP_REG%d failed status-0x%x\n", pnum + 1, status);
+                       goto out;
+               } else
+                       dev_dbg(&port->dev, "ZLP_REG%d Writing success status%d\n", pnum + 1, status);
 
-               }
-               mos7840_port->control_urb = usb_alloc_urb(0, GFP_KERNEL);
-               mos7840_port->ctrl_buf = kmalloc(16, GFP_KERNEL);
-               mos7840_port->dr = kmalloc(sizeof(struct usb_ctrlrequest),
-                                                               GFP_KERNEL);
-               if (!mos7840_port->control_urb || !mos7840_port->ctrl_buf ||
-                                                       !mos7840_port->dr) {
-                       status = -ENOMEM;
-                       goto error;
-               }
+       }
+       mos7840_port->control_urb = usb_alloc_urb(0, GFP_KERNEL);
+       mos7840_port->ctrl_buf = kmalloc(16, GFP_KERNEL);
+       mos7840_port->dr = kmalloc(sizeof(struct usb_ctrlrequest),
+                       GFP_KERNEL);
+       if (!mos7840_port->control_urb || !mos7840_port->ctrl_buf ||
+                       !mos7840_port->dr) {
+               status = -ENOMEM;
+               goto error;
+       }
 
-               mos7840_port->has_led = false;
+       mos7840_port->has_led = false;
 
-               /* Initialize LED timers */
-               if (device_type == MOSCHIP_DEVICE_ID_7810) {
-                       mos7840_port->has_led = true;
+       /* Initialize LED timers */
+       if (device_type == MOSCHIP_DEVICE_ID_7810) {
+               mos7840_port->has_led = true;
 
-                       init_timer(&mos7840_port->led_timer1);
-                       mos7840_port->led_timer1.function = mos7840_led_off;
-                       mos7840_port->led_timer1.expires =
-                                       jiffies + msecs_to_jiffies(LED_ON_MS);
-                       mos7840_port->led_timer1.data =
-                                               (unsigned long)mos7840_port;
+               init_timer(&mos7840_port->led_timer1);
+               mos7840_port->led_timer1.function = mos7840_led_off;
+               mos7840_port->led_timer1.expires =
+                       jiffies + msecs_to_jiffies(LED_ON_MS);
+               mos7840_port->led_timer1.data = (unsigned long)mos7840_port;
 
-                       init_timer(&mos7840_port->led_timer2);
-                       mos7840_port->led_timer2.function =
-                                               mos7840_led_flag_off;
-                       mos7840_port->led_timer2.expires =
-                                       jiffies + msecs_to_jiffies(LED_OFF_MS);
-                       mos7840_port->led_timer2.data =
-                                               (unsigned long)mos7840_port;
+               init_timer(&mos7840_port->led_timer2);
+               mos7840_port->led_timer2.function = mos7840_led_flag_off;
+               mos7840_port->led_timer2.expires =
+                       jiffies + msecs_to_jiffies(LED_OFF_MS);
+               mos7840_port->led_timer2.data = (unsigned long)mos7840_port;
 
-                       mos7840_port->led_flag = false;
+               mos7840_port->led_flag = false;
 
-                       /* Turn off LED */
-                       mos7840_set_led_sync(serial->port[i],
-                                               MODEM_CONTROL_REGISTER, 0x0300);
-               }
+               /* Turn off LED */
+               mos7840_set_led_sync(port, MODEM_CONTROL_REGISTER, 0x0300);
        }
+out:
+       if (pnum == serial->num_ports - 1) {
+               /* Zero Length flag enable */
+               Data = 0x0f;
+               status = mos7840_set_reg_sync(serial->port[0], ZLP_REG5, Data);
+               if (status < 0) {
+                       dev_dbg(&port->dev, "Writing ZLP_REG5 failed status-0x%x\n", status);
+                       goto error;
+               } else
+                       dev_dbg(&port->dev, "ZLP_REG5 Writing success status%d\n", status);
 
-       /* Zero Length flag enable */
-       Data = 0x0f;
-       status = mos7840_set_reg_sync(serial->port[0], ZLP_REG5, Data);
-       if (status < 0) {
-               dev_dbg(&dev->dev, "Writing ZLP_REG5 failed status-0x%x\n", status);
-               goto error;
-       } else
-               dev_dbg(&dev->dev, "ZLP_REG5 Writing success status%d\n", status);
-
-       /* setting configuration feature to one */
-       usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
-                       (__u8) 0x03, 0x00, 0x01, 0x00, NULL, 0x00, MOS_WDR_TIMEOUT);
+               /* setting configuration feature to one */
+               usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+                               0x03, 0x00, 0x01, 0x00, NULL, 0x00,
+                               MOS_WDR_TIMEOUT);
+       }
        return 0;
 error:
-       for (/* nothing */; i >= 0; i--) {
-               mos7840_port = mos7840_get_port_private(serial->port[i]);
+       kfree(mos7840_port->dr);
+       kfree(mos7840_port->ctrl_buf);
+       usb_free_urb(mos7840_port->control_urb);
+       kfree(mos7840_port);
 
-               kfree(mos7840_port->dr);
-               kfree(mos7840_port->ctrl_buf);
-               usb_free_urb(mos7840_port->control_urb);
-               kfree(mos7840_port);
-               serial->port[i] = NULL;
-       }
        return status;
 }
 
-/****************************************************************************
- * mos7840_disconnect
- *     This function is called whenever the device is removed from the usb bus.
- ****************************************************************************/
-
-static void mos7840_disconnect(struct usb_serial *serial)
+static int mos7840_port_remove(struct usb_serial_port *port)
 {
-       int i;
-       unsigned long flags;
        struct moschip_port *mos7840_port;
 
-       /* check for the ports to be closed,close the ports and disconnect */
+       mos7840_port = mos7840_get_port_private(port);
 
-       /* free private structure allocated for serial port  *
-        * stop reads and writes on all ports                */
+       if (mos7840_port->has_led) {
+               /* Turn off LED */
+               mos7840_set_led_sync(port, MODEM_CONTROL_REGISTER, 0x0300);
 
-       for (i = 0; i < serial->num_ports; ++i) {
-               mos7840_port = mos7840_get_port_private(serial->port[i]);
-               if (mos7840_port) {
-                       spin_lock_irqsave(&mos7840_port->pool_lock, flags);
-                       mos7840_port->zombie = 1;
-                       spin_unlock_irqrestore(&mos7840_port->pool_lock, flags);
-                       usb_kill_urb(mos7840_port->control_urb);
-               }
+               del_timer_sync(&mos7840_port->led_timer1);
+               del_timer_sync(&mos7840_port->led_timer2);
        }
-}
-
-/****************************************************************************
- * mos7840_release
- *     This function is called when the usb_serial structure is freed.
- ****************************************************************************/
-
-static void mos7840_release(struct usb_serial *serial)
-{
-       int i;
-       struct moschip_port *mos7840_port;
-
-       /* check for the ports to be closed,close the ports and disconnect */
+       usb_kill_urb(mos7840_port->control_urb);
+       usb_free_urb(mos7840_port->control_urb);
+       kfree(mos7840_port->ctrl_buf);
+       kfree(mos7840_port->dr);
+       kfree(mos7840_port);
 
-       /* free private structure allocated for serial port  *
-        * stop reads and writes on all ports                */
-
-       for (i = 0; i < serial->num_ports; ++i) {
-               mos7840_port = mos7840_get_port_private(serial->port[i]);
-               if (mos7840_port) {
-                       if (mos7840_port->has_led) {
-                               /* Turn off LED */
-                               mos7840_set_led_sync(mos7840_port->port,
-                                               MODEM_CONTROL_REGISTER, 0x0300);
-
-                               del_timer_sync(&mos7840_port->led_timer1);
-                               del_timer_sync(&mos7840_port->led_timer2);
-                       }
-                       kfree(mos7840_port->ctrl_buf);
-                       kfree(mos7840_port->dr);
-                       kfree(mos7840_port);
-               }
-       }
+       return 0;
 }
 
 static struct usb_serial_driver moschip7840_4port_device = {
@@ -2677,9 +2597,8 @@ static struct usb_serial_driver moschip7840_4port_device = {
        .tiocmget = mos7840_tiocmget,
        .tiocmset = mos7840_tiocmset,
        .get_icount = mos7840_get_icount,
-       .attach = mos7840_startup,
-       .disconnect = mos7840_disconnect,
-       .release = mos7840_release,
+       .port_probe = mos7840_port_probe,
+       .port_remove = mos7840_port_remove,
        .read_bulk_callback = mos7840_bulk_in_callback,
        .read_int_callback = mos7840_interrupt_callback,
 };
index 6def58b79382f97511929b2c3fc8e386c71ffa51..9ab73d2957746d49292357382f7a081faa25cd55 100644 (file)
@@ -44,8 +44,8 @@ static int  omninet_write(struct tty_struct *tty, struct usb_serial_port *port,
                                const unsigned char *buf, int count);
 static int  omninet_write_room(struct tty_struct *tty);
 static void omninet_disconnect(struct usb_serial *serial);
-static void omninet_release(struct usb_serial *serial);
-static int omninet_attach(struct usb_serial *serial);
+static int omninet_port_probe(struct usb_serial_port *port);
+static int omninet_port_remove(struct usb_serial_port *port);
 
 static const struct usb_device_id id_table[] = {
        { USB_DEVICE(ZYXEL_VENDOR_ID, ZYXEL_OMNINET_ID) },
@@ -62,7 +62,8 @@ static struct usb_serial_driver zyxel_omninet_device = {
        .description =          "ZyXEL - omni.net lcd plus usb",
        .id_table =             id_table,
        .num_ports =            1,
-       .attach =               omninet_attach,
+       .port_probe =           omninet_port_probe,
+       .port_remove =          omninet_port_remove,
        .open =                 omninet_open,
        .close =                omninet_close,
        .write =                omninet_write,
@@ -70,7 +71,6 @@ static struct usb_serial_driver zyxel_omninet_device = {
        .read_bulk_callback =   omninet_read_bulk_callback,
        .write_bulk_callback =  omninet_write_bulk_callback,
        .disconnect =           omninet_disconnect,
-       .release =              omninet_release,
 };
 
 static struct usb_serial_driver * const serial_drivers[] = {
@@ -112,18 +112,26 @@ struct omninet_data {
        __u8    od_outseq;      /* Sequence number for bulk_out URBs */
 };
 
-static int omninet_attach(struct usb_serial *serial)
+static int omninet_port_probe(struct usb_serial_port *port)
 {
        struct omninet_data *od;
-       struct usb_serial_port *port = serial->port[0];
 
        od = kmalloc(sizeof(struct omninet_data), GFP_KERNEL);
-       if (!od) {
-               dev_err(&port->dev, "%s- kmalloc(%Zd) failed.\n",
-                       __func__, sizeof(struct omninet_data));
+       if (!od)
                return -ENOMEM;
-       }
+
        usb_set_serial_port_data(port, od);
+
+       return 0;
+}
+
+static int omninet_port_remove(struct usb_serial_port *port)
+{
+       struct omninet_data *od;
+
+       od = usb_get_serial_port_data(port);
+       kfree(od);
+
        return 0;
 }
 
@@ -279,14 +287,6 @@ static void omninet_disconnect(struct usb_serial *serial)
        usb_kill_urb(wport->write_urb);
 }
 
-
-static void omninet_release(struct usb_serial *serial)
-{
-       struct usb_serial_port *port = serial->port[0];
-
-       kfree(usb_get_serial_port_data(port));
-}
-
 module_usb_serial_driver(serial_drivers, id_table);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
index 41b1647306eb0970f55993f0099307af50739349..6aba731d4864457acba4e644b463a5c2f725dfc7 100644 (file)
@@ -155,7 +155,11 @@ static int send_control_msg(struct usb_serial_port *port, u8 requesttype,
 {
        struct usb_serial *serial = port->serial;
        int retval;
-       u8 buffer[2];
+       u8 *buffer;
+
+       buffer = kzalloc(1, GFP_KERNEL);
+       if (!buffer)
+               return -ENOMEM;
 
        buffer[0] = val;
        /* Send the message to the vendor control endpoint
@@ -164,6 +168,7 @@ static int send_control_msg(struct usb_serial_port *port, u8 requesttype,
                                requesttype,
                                USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE,
                                0, 0, buffer, 1, 0);
+       kfree(buffer);
 
        return retval;
 }
@@ -281,7 +286,7 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port,
        if (!dr) {
                dev_err(&port->dev, "out of memory\n");
                count = -ENOMEM;
-               goto error;
+               goto error_no_dr;
        }
 
        dr->bRequestType = USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT;
@@ -311,6 +316,8 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port,
 
        return count;
 error:
+       kfree(dr);
+error_no_dr:
        usb_free_urb(urb);
 error_no_urb:
        kfree(buffer);
index 54d4148d01d120a6d5c2085eb3d884328405a109..edc64bb6f457e45408f2c360dfc6de4500108499 100644 (file)
@@ -47,6 +47,7 @@
 /* Function prototypes */
 static int  option_probe(struct usb_serial *serial,
                        const struct usb_device_id *id);
+static int option_attach(struct usb_serial *serial);
 static void option_release(struct usb_serial *serial);
 static int option_send_setup(struct usb_serial_port *port);
 static void option_instat_callback(struct urb *urb);
@@ -157,6 +158,7 @@ static void option_instat_callback(struct urb *urb);
 #define NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_HIGHSPEED        0x8001
 #define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED        0x9000
 #define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_HIGHSPEED        0x9001
+#define NOVATELWIRELESS_PRODUCT_E362           0x9010
 #define NOVATELWIRELESS_PRODUCT_G1             0xA001
 #define NOVATELWIRELESS_PRODUCT_G1_M           0xA002
 #define NOVATELWIRELESS_PRODUCT_G2             0xA010
@@ -192,6 +194,9 @@ static void option_instat_callback(struct urb *urb);
 #define DELL_PRODUCT_5730_MINICARD_TELUS       0x8181
 #define DELL_PRODUCT_5730_MINICARD_VZW         0x8182
 
+#define DELL_PRODUCT_5800_MINICARD_VZW         0x8195  /* Novatel E362 */
+#define DELL_PRODUCT_5800_V2_MINICARD_VZW      0x8196  /* Novatel E362 */
+
 #define KYOCERA_VENDOR_ID                      0x0c88
 #define KYOCERA_PRODUCT_KPC650                 0x17da
 #define KYOCERA_PRODUCT_KPC680                 0x180a
@@ -282,6 +287,7 @@ static void option_instat_callback(struct urb *urb);
 /* ALCATEL PRODUCTS */
 #define ALCATEL_VENDOR_ID                      0x1bbb
 #define ALCATEL_PRODUCT_X060S_X200             0x0000
+#define ALCATEL_PRODUCT_X220_X500D             0x0017
 
 #define PIRELLI_VENDOR_ID                      0x1266
 #define PIRELLI_PRODUCT_C100_1                 0x1002
@@ -705,6 +711,7 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_G2) },
        /* Novatel Ovation MC551 a.k.a. Verizon USB551L */
        { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC551, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_E362, 0xff, 0xff, 0xff) },
 
        { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01) },
        { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01A) },
@@ -727,6 +734,8 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_SPRINT) },      /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */
        { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_TELUS) },       /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */
        { 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(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) },
@@ -1156,6 +1165,7 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S_X200),
          .driver_info = (kernel_ulong_t)&alcatel_x200_blacklist
        },
+       { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X220_X500D) },
        { USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) },
        { USB_DEVICE(TLAYTECH_VENDOR_ID, TLAYTECH_PRODUCT_TEU800) },
        { USB_DEVICE(LONGCHEER_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W14),
@@ -1288,8 +1298,9 @@ static struct usb_serial_driver option_1port_device = {
        .tiocmget          = usb_wwan_tiocmget,
        .tiocmset          = usb_wwan_tiocmset,
        .ioctl             = usb_wwan_ioctl,
-       .attach            = usb_wwan_startup,
+       .attach            = option_attach,
        .release           = option_release,
+       .port_probe        = usb_wwan_port_probe,
        .port_remove       = usb_wwan_port_remove,
        .read_int_callback = option_instat_callback,
 #ifdef CONFIG_PM
@@ -1335,8 +1346,6 @@ static bool is_blacklisted(const u8 ifnum, enum option_blacklist_reason reason,
 static int option_probe(struct usb_serial *serial,
                        const struct usb_device_id *id)
 {
-       struct usb_wwan_intf_private *data;
-       struct option_private *priv;
        struct usb_interface_descriptor *iface_desc =
                                &serial->interface->cur_altsetting->desc;
        struct usb_device_descriptor *dev_desc = &serial->dev->descriptor;
@@ -1374,6 +1383,19 @@ static int option_probe(struct usb_serial *serial,
                iface_desc->bInterfaceClass != USB_CLASS_CDC_DATA)
                return -ENODEV;
 
+       /* Store device id so we can use it during attach. */
+       usb_set_serial_data(serial, (void *)id);
+
+       return 0;
+}
+
+static int option_attach(struct usb_serial *serial)
+{
+       struct usb_interface_descriptor *iface_desc;
+       const struct usb_device_id *id;
+       struct usb_wwan_intf_private *data;
+       struct option_private *priv;
+
        data = kzalloc(sizeof(struct usb_wwan_intf_private), GFP_KERNEL);
        if (!data)
                return -ENOMEM;
@@ -1384,6 +1406,10 @@ static int option_probe(struct usb_serial *serial,
                return -ENOMEM;
        }
 
+       /* Retrieve device id stored at probe. */
+       id = usb_get_serial_data(serial);
+       iface_desc = &serial->interface->cur_altsetting->desc;
+
        priv->bInterfaceNumber = iface_desc->bInterfaceNumber;
        data->private = priv;
 
index c3ddb65c05f295158ee6ac4022cbca367bf11f21..aa148c21ea40e82a6f49b58b855ed2278f53cf3a 100644 (file)
@@ -138,7 +138,6 @@ MODULE_DEVICE_TABLE(usb, id_table);
 
 static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
 {
-       struct usb_wwan_intf_private *data;
        struct usb_host_interface *intf = serial->interface->cur_altsetting;
        struct device *dev = &serial->dev->dev;
        int retval = -ENODEV;
@@ -154,13 +153,6 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
        ifnum = intf->desc.bInterfaceNumber;
        dev_dbg(dev, "This Interface = %d\n", ifnum);
 
-       data = kzalloc(sizeof(struct usb_wwan_intf_private),
-                                        GFP_KERNEL);
-       if (!data)
-               return -ENOMEM;
-
-       spin_lock_init(&data->susp_lock);
-
        if (nintf == 1) {
                /* QDL mode */
                /* Gobi 2000 has a single altsetting, older ones have two */
@@ -253,20 +245,28 @@ done:
                }
        }
 
-       /* Set serial->private if not returning error */
-       if (retval == 0)
-               usb_set_serial_data(serial, data);
-       else
-               kfree(data);
-
        return retval;
 }
 
+static int qc_attach(struct usb_serial *serial)
+{
+       struct usb_wwan_intf_private *data;
+
+       data = kzalloc(sizeof(*data), GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
+       spin_lock_init(&data->susp_lock);
+
+       usb_set_serial_data(serial, data);
+
+       return 0;
+}
+
 static void qc_release(struct usb_serial *serial)
 {
        struct usb_wwan_intf_private *priv = usb_get_serial_data(serial);
 
-       /* Free the private data allocated in qcprobe */
        usb_set_serial_data(serial, NULL);
        kfree(priv);
 }
@@ -285,8 +285,9 @@ static struct usb_serial_driver qcdevice = {
        .write               = usb_wwan_write,
        .write_room          = usb_wwan_write_room,
        .chars_in_buffer     = usb_wwan_chars_in_buffer,
-       .attach              = usb_wwan_startup,
+       .attach              = qc_attach,
        .release             = qc_release,
+       .port_probe          = usb_wwan_port_probe,
        .port_remove         = usb_wwan_port_remove,
 #ifdef CONFIG_PM
        .suspend             = usb_wwan_suspend,
index 2cdfdcc90b378b68402fc016cb0f1b4344b10ef3..ffcfc962ab10b5a4043cd900f8ca6e90094ff417 100644 (file)
@@ -143,12 +143,12 @@ static void qt2_read_bulk_callback(struct urb *urb);
 
 static void qt2_release(struct usb_serial *serial)
 {
-       int i;
+       struct qt2_serial_private *serial_priv;
 
-       kfree(usb_get_serial_data(serial));
+       serial_priv = usb_get_serial_data(serial);
 
-       for (i = 0; i < serial->num_ports; i++)
-               kfree(usb_get_serial_port_data(serial->port[i]));
+       usb_free_urb(serial_priv->read_urb);
+       kfree(serial_priv);
 }
 
 static inline int calc_baud_divisor(int baudrate)
@@ -423,11 +423,16 @@ static void qt2_close(struct usb_serial_port *port)
        port_priv->is_open = false;
 
        spin_lock_irqsave(&port_priv->urb_lock, flags);
-       if (port_priv->write_urb->status == -EINPROGRESS)
-               usb_kill_urb(port_priv->write_urb);
+       usb_kill_urb(port_priv->write_urb);
        port_priv->urb_in_use = false;
        spin_unlock_irqrestore(&port_priv->urb_lock, flags);
 
+       mutex_lock(&port->serial->disc_mutex);
+       if (port->serial->disconnected) {
+               mutex_unlock(&port->serial->disc_mutex);
+               return;
+       }
+
        /* flush the port transmit buffer */
        i = usb_control_msg(serial->dev,
                            usb_rcvctrlpipe(serial->dev, 0),
@@ -459,26 +464,14 @@ static void qt2_close(struct usb_serial_port *port)
                dev_err(&port->dev, "%s - close port failed %i\n",
                        __func__, i);
 
+       mutex_unlock(&port->serial->disc_mutex);
 }
 
 static void qt2_disconnect(struct usb_serial *serial)
 {
        struct qt2_serial_private *serial_priv = usb_get_serial_data(serial);
-       struct qt2_port_private *port_priv;
-       int i;
-
-       if (serial_priv->read_urb->status == -EINPROGRESS)
-               usb_kill_urb(serial_priv->read_urb);
-
-       usb_free_urb(serial_priv->read_urb);
 
-       for (i = 0; i < serial->num_ports; i++) {
-               port_priv = usb_get_serial_port_data(serial->port[i]);
-
-               if (port_priv->write_urb->status == -EINPROGRESS)
-                       usb_kill_urb(port_priv->write_urb);
-               usb_free_urb(port_priv->write_urb);
-       }
+       usb_kill_urb(serial_priv->read_urb);
 }
 
 static int get_serial_info(struct usb_serial_port *port,
@@ -773,11 +766,9 @@ static void qt2_read_bulk_callback(struct urb *urb)
 
 static int qt2_setup_urbs(struct usb_serial *serial)
 {
-       struct usb_serial_port *port;
        struct usb_serial_port *port0;
        struct qt2_serial_private *serial_priv;
-       struct qt2_port_private *port_priv;
-       int pcount, status;
+       int status;
 
        port0 = serial->port[0];
 
@@ -795,46 +786,21 @@ static int qt2_setup_urbs(struct usb_serial *serial)
                          sizeof(serial_priv->read_buffer),
                          qt2_read_bulk_callback, serial);
 
-       /* setup write_urb for each port */
-       for (pcount = 0; pcount < serial->num_ports; pcount++) {
-
-               port = serial->port[pcount];
-               port_priv = usb_get_serial_port_data(port);
-
-               port_priv->write_urb = usb_alloc_urb(0, GFP_KERNEL);
-               if (!port_priv->write_urb) {
-                       dev_err(&serial->dev->dev,
-                               "failed to alloc write_urb for port %i\n",
-                               pcount);
-                       return -ENOMEM;
-               }
-
-               usb_fill_bulk_urb(port_priv->write_urb,
-                                 serial->dev,
-                                 usb_sndbulkpipe(serial->dev,
-                                                 port0->
-                                                 bulk_out_endpointAddress),
-                                 port_priv->write_buffer,
-                                 sizeof(port_priv->write_buffer),
-                                 qt2_write_bulk_callback, port);
-       }
-
        status = usb_submit_urb(serial_priv->read_urb, GFP_KERNEL);
        if (status != 0) {
                dev_err(&serial->dev->dev,
                        "%s - submit read urb failed %i\n", __func__, status);
+               usb_free_urb(serial_priv->read_urb);
                return status;
        }
 
        return 0;
-
 }
 
 static int qt2_attach(struct usb_serial *serial)
 {
        struct qt2_serial_private *serial_priv;
-       struct qt2_port_private *port_priv;
-       int status, pcount;
+       int status;
 
        /* power on unit */
        status = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
@@ -854,26 +820,6 @@ static int qt2_attach(struct usb_serial *serial)
 
        usb_set_serial_data(serial, serial_priv);
 
-       for (pcount = 0; pcount < serial->num_ports; pcount++) {
-               port_priv = kzalloc(sizeof(*port_priv), GFP_KERNEL);
-               if (!port_priv) {
-                       dev_err(&serial->dev->dev,
-                               "%s- kmalloc(%Zd) failed.\n", __func__,
-                               sizeof(*port_priv));
-                       pcount--;
-                       status = -ENOMEM;
-                       goto attach_failed;
-               }
-
-               spin_lock_init(&port_priv->lock);
-               spin_lock_init(&port_priv->urb_lock);
-               init_waitqueue_head(&port_priv->delta_msr_wait);
-
-               port_priv->port = serial->port[pcount];
-
-               usb_set_serial_port_data(serial->port[pcount], port_priv);
-       }
-
        status = qt2_setup_urbs(serial);
        if (status != 0)
                goto attach_failed;
@@ -881,14 +827,53 @@ static int qt2_attach(struct usb_serial *serial)
        return 0;
 
 attach_failed:
-       for (/* empty */; pcount >= 0; pcount--) {
-               port_priv = usb_get_serial_port_data(serial->port[pcount]);
-               kfree(port_priv);
-       }
        kfree(serial_priv);
        return status;
 }
 
+static int qt2_port_probe(struct usb_serial_port *port)
+{
+       struct usb_serial *serial = port->serial;
+       struct qt2_port_private *port_priv;
+       u8 bEndpointAddress;
+
+       port_priv = kzalloc(sizeof(*port_priv), GFP_KERNEL);
+       if (!port_priv)
+               return -ENOMEM;
+
+       spin_lock_init(&port_priv->lock);
+       spin_lock_init(&port_priv->urb_lock);
+       init_waitqueue_head(&port_priv->delta_msr_wait);
+       port_priv->port = port;
+
+       port_priv->write_urb = usb_alloc_urb(0, GFP_KERNEL);
+       if (!port_priv->write_urb) {
+               kfree(port_priv);
+               return -ENOMEM;
+       }
+       bEndpointAddress = serial->port[0]->bulk_out_endpointAddress;
+       usb_fill_bulk_urb(port_priv->write_urb, serial->dev,
+                               usb_sndbulkpipe(serial->dev, bEndpointAddress),
+                               port_priv->write_buffer,
+                               sizeof(port_priv->write_buffer),
+                               qt2_write_bulk_callback, port);
+
+       usb_set_serial_port_data(port, port_priv);
+
+       return 0;
+}
+
+static int qt2_port_remove(struct usb_serial_port *port)
+{
+       struct qt2_port_private *port_priv;
+
+       port_priv = usb_get_serial_port_data(port);
+       usb_free_urb(port_priv->write_urb);
+       kfree(port_priv);
+
+       return 0;
+}
+
 static int qt2_tiocmget(struct tty_struct *tty)
 {
        struct usb_serial_port *port = tty->driver_data;
@@ -1127,6 +1112,8 @@ static struct usb_serial_driver qt2_device = {
        .attach              = qt2_attach,
        .release             = qt2_release,
        .disconnect          = qt2_disconnect,
+       .port_probe          = qt2_port_probe,
+       .port_remove         = qt2_port_remove,
        .dtr_rts             = qt2_dtr_rts,
        .break_ctl           = qt2_break_ctl,
        .tiocmget            = qt2_tiocmget,
index 01d882cf3775a2523662e4ab40f917a91eac5099..270860f6bb2aee0a97f2091c7c33041332cccc1e 100644 (file)
@@ -161,7 +161,6 @@ static int sierra_probe(struct usb_serial *serial,
 {
        int result = 0;
        struct usb_device *udev;
-       struct sierra_intf_private *data;
        u8 ifnum;
 
        udev = serial->dev;
@@ -188,11 +187,6 @@ static int sierra_probe(struct usb_serial *serial,
                return -ENODEV;
        }
 
-       data = serial->private = kzalloc(sizeof(struct sierra_intf_private), GFP_KERNEL);
-       if (!data)
-               return -ENOMEM;
-       spin_lock_init(&data->susp_lock);
-
        return result;
 }
 
@@ -884,11 +878,15 @@ static void sierra_dtr_rts(struct usb_serial_port *port, int on)
 
 static int sierra_startup(struct usb_serial *serial)
 {
-       struct usb_serial_port *port;
-       struct sierra_port_private *portdata;
-       struct sierra_iface_info *himemoryp = NULL;
-       int i;
-       u8 ifnum;
+       struct sierra_intf_private *intfdata;
+
+       intfdata = kzalloc(sizeof(*intfdata), GFP_KERNEL);
+       if (!intfdata)
+               return -ENOMEM;
+
+       spin_lock_init(&intfdata->susp_lock);
+
+       usb_set_serial_data(serial, intfdata);
 
        /* Set Device mode to D0 */
        sierra_set_power_state(serial->dev, 0x0000);
@@ -897,68 +895,71 @@ static int sierra_startup(struct usb_serial *serial)
        if (nmea)
                sierra_vsc_set_nmea(serial->dev, 1);
 
-       /* Now setup per port private data */
-       for (i = 0; i < serial->num_ports; i++) {
-               port = serial->port[i];
-               portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
-               if (!portdata) {
-                       dev_dbg(&port->dev, "%s: kmalloc for "
-                               "sierra_port_private (%d) failed!\n",
-                               __func__, i);
-                       return -ENOMEM;
-               }
-               spin_lock_init(&portdata->lock);
-               init_usb_anchor(&portdata->active);
-               init_usb_anchor(&portdata->delayed);
-               ifnum = i;
-               /* Assume low memory requirements */
-               portdata->num_out_urbs = N_OUT_URB;
-               portdata->num_in_urbs  = N_IN_URB;
-
-               /* Determine actual memory requirements */
-               if (serial->num_ports == 1) {
-                       /* Get interface number for composite device */
-                       ifnum = sierra_calc_interface(serial);
-                       himemoryp =
-                           (struct sierra_iface_info *)&typeB_interface_list;
-                       if (is_himemory(ifnum, himemoryp)) {
-                               portdata->num_out_urbs = N_OUT_URB_HM;
-                               portdata->num_in_urbs  = N_IN_URB_HM;
-                       }
-               }
-               else {
-                       himemoryp =
-                           (struct sierra_iface_info *)&typeA_interface_list;
-                       if (is_himemory(i, himemoryp)) {
-                               portdata->num_out_urbs = N_OUT_URB_HM;
-                               portdata->num_in_urbs  = N_IN_URB_HM;
-                       }
-               }
-               dev_dbg(&serial->dev->dev,
-                       "Memory usage (urbs) interface #%d, in=%d, out=%d\n",
-                       ifnum,portdata->num_in_urbs, portdata->num_out_urbs );
-               /* Set the port private data pointer */
-               usb_set_serial_port_data(port, portdata);
-       }
-
        return 0;
 }
 
 static void sierra_release(struct usb_serial *serial)
 {
-       int i;
-       struct usb_serial_port *port;
+       struct sierra_intf_private *intfdata;
+
+       intfdata = usb_get_serial_data(serial);
+       kfree(intfdata);
+}
+
+static int sierra_port_probe(struct usb_serial_port *port)
+{
+       struct usb_serial *serial = port->serial;
        struct sierra_port_private *portdata;
+       const struct sierra_iface_info *himemoryp;
+       u8 ifnum;
 
-       for (i = 0; i < serial->num_ports; ++i) {
-               port = serial->port[i];
-               if (!port)
-                       continue;
-               portdata = usb_get_serial_port_data(port);
-               if (!portdata)
-                       continue;
-               kfree(portdata);
+       portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
+       if (!portdata)
+               return -ENOMEM;
+
+       spin_lock_init(&portdata->lock);
+       init_usb_anchor(&portdata->active);
+       init_usb_anchor(&portdata->delayed);
+
+       /* Assume low memory requirements */
+       portdata->num_out_urbs = N_OUT_URB;
+       portdata->num_in_urbs  = N_IN_URB;
+
+       /* Determine actual memory requirements */
+       if (serial->num_ports == 1) {
+               /* Get interface number for composite device */
+               ifnum = sierra_calc_interface(serial);
+               himemoryp = &typeB_interface_list;
+       } else {
+               /* This is really the usb-serial port number of the interface
+                * rather than the interface number.
+                */
+               ifnum = port->number - serial->minor;
+               himemoryp = &typeA_interface_list;
        }
+
+       if (is_himemory(ifnum, himemoryp)) {
+               portdata->num_out_urbs = N_OUT_URB_HM;
+               portdata->num_in_urbs  = N_IN_URB_HM;
+       }
+
+       dev_dbg(&port->dev,
+                       "Memory usage (urbs) interface #%d, in=%d, out=%d\n",
+                       ifnum, portdata->num_in_urbs, portdata->num_out_urbs);
+
+       usb_set_serial_port_data(port, portdata);
+
+       return 0;
+}
+
+static int sierra_port_remove(struct usb_serial_port *port)
+{
+       struct sierra_port_private *portdata;
+
+       portdata = usb_get_serial_port_data(port);
+       kfree(portdata);
+
+       return 0;
 }
 
 #ifdef CONFIG_PM
@@ -1062,6 +1063,8 @@ static struct usb_serial_driver sierra_device = {
        .tiocmset          = sierra_tiocmset,
        .attach            = sierra_startup,
        .release           = sierra_release,
+       .port_probe        = sierra_port_probe,
+       .port_remove       = sierra_port_remove,
        .suspend           = sierra_suspend,
        .resume            = sierra_resume,
        .read_int_callback = sierra_instat_callback,
index 1f034d2397c6c6ea3888e79aa6cd2ddb6d73202b..684739b8efd05b15a5646585d94417f3aa20a53d 100644 (file)
@@ -8,7 +8,7 @@
 extern void usb_wwan_dtr_rts(struct usb_serial_port *port, int on);
 extern int usb_wwan_open(struct tty_struct *tty, struct usb_serial_port *port);
 extern void usb_wwan_close(struct usb_serial_port *port);
-extern int usb_wwan_startup(struct usb_serial *serial);
+extern int usb_wwan_port_probe(struct usb_serial_port *port);
 extern int usb_wwan_port_remove(struct usb_serial_port *port);
 extern int usb_wwan_write_room(struct tty_struct *tty);
 extern void usb_wwan_set_termios(struct tty_struct *tty,
index e42aa398ed37a3e8f774c2cbbdbaed8ae72e6eb3..a3e9c095f0d83a39738ef74b9e3a9ef7b41a2d6e 100644 (file)
@@ -447,15 +447,14 @@ void usb_wwan_close(struct usb_serial_port *port)
 EXPORT_SYMBOL(usb_wwan_close);
 
 /* Helper functions used by usb_wwan_setup_urbs */
-static struct urb *usb_wwan_setup_urb(struct usb_serial *serial, int endpoint,
+static struct urb *usb_wwan_setup_urb(struct usb_serial_port *port,
+                                     int endpoint,
                                      int dir, void *ctx, char *buf, int len,
                                      void (*callback) (struct urb *))
 {
+       struct usb_serial *serial = port->serial;
        struct urb *urb;
 
-       if (endpoint == -1)
-               return NULL;    /* endpoint not needed */
-
        urb = usb_alloc_urb(0, GFP_KERNEL);     /* No ISO */
        if (urb == NULL) {
                dev_dbg(&serial->interface->dev,
@@ -472,101 +471,78 @@ static struct urb *usb_wwan_setup_urb(struct usb_serial *serial, int endpoint,
        return urb;
 }
 
-/* Setup urbs */
-static void usb_wwan_setup_urbs(struct usb_serial *serial)
+int usb_wwan_port_probe(struct usb_serial_port *port)
 {
-       int i, j;
-       struct usb_serial_port *port;
        struct usb_wwan_port_private *portdata;
+       struct urb *urb;
+       u8 *buffer;
+       int err;
+       int i;
 
-       for (i = 0; i < serial->num_ports; i++) {
-               port = serial->port[i];
-               portdata = usb_get_serial_port_data(port);
+       portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
+       if (!portdata)
+               return -ENOMEM;
 
-               /* Do indat endpoints first */
-               for (j = 0; j < N_IN_URB; ++j) {
-                       portdata->in_urbs[j] = usb_wwan_setup_urb(serial,
-                                                                 port->
-                                                                 bulk_in_endpointAddress,
-                                                                 USB_DIR_IN,
-                                                                 port,
-                                                                 portdata->
-                                                                 in_buffer[j],
-                                                                 IN_BUFLEN,
-                                                                 usb_wwan_indat_callback);
-               }
+       init_usb_anchor(&portdata->delayed);
 
-               /* outdat endpoints */
-               for (j = 0; j < N_OUT_URB; ++j) {
-                       portdata->out_urbs[j] = usb_wwan_setup_urb(serial,
-                                                                  port->
-                                                                  bulk_out_endpointAddress,
-                                                                  USB_DIR_OUT,
-                                                                  port,
-                                                                  portdata->
-                                                                  out_buffer
-                                                                  [j],
-                                                                  OUT_BUFLEN,
-                                                                  usb_wwan_outdat_callback);
-               }
-       }
-}
+       for (i = 0; i < N_IN_URB; i++) {
+               if (!port->bulk_in_size)
+                       break;
 
-int usb_wwan_startup(struct usb_serial *serial)
-{
-       int i, j, err;
-       struct usb_serial_port *port;
-       struct usb_wwan_port_private *portdata;
-       u8 *buffer;
+               buffer = (u8 *)__get_free_page(GFP_KERNEL);
+               if (!buffer)
+                       goto bail_out_error;
+               portdata->in_buffer[i] = buffer;
 
-       /* Now setup per port private data */
-       for (i = 0; i < serial->num_ports; i++) {
-               port = serial->port[i];
-               portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
-               if (!portdata) {
-                       dev_dbg(&port->dev, "%s: kmalloc for usb_wwan_port_private (%d) failed!.\n",
-                               __func__, i);
-                       return 1;
-               }
-               init_usb_anchor(&portdata->delayed);
+               urb = usb_wwan_setup_urb(port, port->bulk_in_endpointAddress,
+                                               USB_DIR_IN, port,
+                                               buffer, IN_BUFLEN,
+                                               usb_wwan_indat_callback);
+               portdata->in_urbs[i] = urb;
+       }
 
-               for (j = 0; j < N_IN_URB; j++) {
-                       buffer = (u8 *) __get_free_page(GFP_KERNEL);
-                       if (!buffer)
-                               goto bail_out_error;
-                       portdata->in_buffer[j] = buffer;
-               }
+       for (i = 0; i < N_OUT_URB; i++) {
+               if (!port->bulk_out_size)
+                       break;
 
-               for (j = 0; j < N_OUT_URB; j++) {
-                       buffer = kmalloc(OUT_BUFLEN, GFP_KERNEL);
-                       if (!buffer)
-                               goto bail_out_error2;
-                       portdata->out_buffer[j] = buffer;
-               }
+               buffer = kmalloc(OUT_BUFLEN, GFP_KERNEL);
+               if (!buffer)
+                       goto bail_out_error2;
+               portdata->out_buffer[i] = buffer;
 
-               usb_set_serial_port_data(port, portdata);
+               urb = usb_wwan_setup_urb(port, port->bulk_out_endpointAddress,
+                                               USB_DIR_OUT, port,
+                                               buffer, OUT_BUFLEN,
+                                               usb_wwan_outdat_callback);
+               portdata->out_urbs[i] = urb;
+       }
 
-               if (!port->interrupt_in_urb)
-                       continue;
+       usb_set_serial_port_data(port, portdata);
+
+       if (port->interrupt_in_urb) {
                err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
                if (err)
                        dev_dbg(&port->dev, "%s: submit irq_in urb failed %d\n",
                                __func__, err);
        }
-       usb_wwan_setup_urbs(serial);
+
        return 0;
 
 bail_out_error2:
-       for (j = 0; j < N_OUT_URB; j++)
-               kfree(portdata->out_buffer[j]);
+       for (i = 0; i < N_OUT_URB; i++) {
+               usb_free_urb(portdata->out_urbs[i]);
+               kfree(portdata->out_buffer[i]);
+       }
 bail_out_error:
-       for (j = 0; j < N_IN_URB; j++)
-               if (portdata->in_buffer[j])
-                       free_page((unsigned long)portdata->in_buffer[j]);
+       for (i = 0; i < N_IN_URB; i++) {
+               usb_free_urb(portdata->in_urbs[i]);
+               free_page((unsigned long)portdata->in_buffer[i]);
+       }
        kfree(portdata);
-       return 1;
+
+       return -ENOMEM;
 }
-EXPORT_SYMBOL(usb_wwan_startup);
+EXPORT_SYMBOL_GPL(usb_wwan_port_probe);
 
 int usb_wwan_port_remove(struct usb_serial_port *port)
 {
index 346c7efc20b06d42899616cb8bb0766007cde82e..b9fca3586d741003a50ffb435be7de74020c48e8 100644 (file)
@@ -83,6 +83,8 @@ static int  whiteheat_firmware_attach(struct usb_serial *serial);
 /* function prototypes for the Connect Tech WhiteHEAT serial converter */
 static int  whiteheat_attach(struct usb_serial *serial);
 static void whiteheat_release(struct usb_serial *serial);
+static int  whiteheat_port_probe(struct usb_serial_port *port);
+static int  whiteheat_port_remove(struct usb_serial_port *port);
 static int  whiteheat_open(struct tty_struct *tty,
                        struct usb_serial_port *port);
 static void whiteheat_close(struct usb_serial_port *port);
@@ -117,6 +119,8 @@ static struct usb_serial_driver whiteheat_device = {
        .num_ports =            4,
        .attach =               whiteheat_attach,
        .release =              whiteheat_release,
+       .port_probe =           whiteheat_port_probe,
+       .port_remove =          whiteheat_port_remove,
        .open =                 whiteheat_open,
        .close =                whiteheat_close,
        .ioctl =                whiteheat_ioctl,
@@ -218,15 +222,12 @@ static int whiteheat_attach(struct usb_serial *serial)
 {
        struct usb_serial_port *command_port;
        struct whiteheat_command_private *command_info;
-       struct usb_serial_port *port;
-       struct whiteheat_private *info;
        struct whiteheat_hw_info *hw_info;
        int pipe;
        int ret;
        int alen;
        __u8 *command;
        __u8 *result;
-       int i;
 
        command_port = serial->port[COMMAND_PORT];
 
@@ -285,22 +286,6 @@ static int whiteheat_attach(struct usb_serial *serial)
                 serial->type->description,
                 hw_info->sw_major_rev, hw_info->sw_minor_rev);
 
-       for (i = 0; i < serial->num_ports; i++) {
-               port = serial->port[i];
-
-               info = kmalloc(sizeof(struct whiteheat_private), GFP_KERNEL);
-               if (info == NULL) {
-                       dev_err(&port->dev,
-                               "%s: Out of memory for port structures\n",
-                               serial->type->description);
-                       goto no_private;
-               }
-
-               info->mcr = 0;
-
-               usb_set_serial_port_data(port, info);
-       }
-
        command_info = kmalloc(sizeof(struct whiteheat_command_private),
                                                                GFP_KERNEL);
        if (command_info == NULL) {
@@ -333,16 +318,10 @@ no_firmware:
                "%s: please contact support@connecttech.com\n",
                serial->type->description);
        kfree(result);
+       kfree(command);
        return -ENODEV;
 
 no_command_private:
-       for (i = serial->num_ports - 1; i >= 0; i--) {
-               port = serial->port[i];
-               info = usb_get_serial_port_data(port);
-               kfree(info);
-no_private:
-               ;
-       }
        kfree(result);
 no_result_buffer:
        kfree(command);
@@ -350,21 +329,36 @@ no_command_buffer:
        return -ENOMEM;
 }
 
-
 static void whiteheat_release(struct usb_serial *serial)
 {
        struct usb_serial_port *command_port;
-       struct whiteheat_private *info;
-       int i;
 
        /* free up our private data for our command port */
        command_port = serial->port[COMMAND_PORT];
        kfree(usb_get_serial_port_data(command_port));
+}
 
-       for (i = 0; i < serial->num_ports; i++) {
-               info = usb_get_serial_port_data(serial->port[i]);
-               kfree(info);
-       }
+static int whiteheat_port_probe(struct usb_serial_port *port)
+{
+       struct whiteheat_private *info;
+
+       info = kzalloc(sizeof(*info), GFP_KERNEL);
+       if (!info)
+               return -ENOMEM;
+
+       usb_set_serial_port_data(port, info);
+
+       return 0;
+}
+
+static int whiteheat_port_remove(struct usb_serial_port *port)
+{
+       struct whiteheat_private *info;
+
+       info = usb_get_serial_port_data(port);
+       kfree(info);
+
+       return 0;
 }
 
 static int whiteheat_open(struct tty_struct *tty, struct usb_serial_port *port)
index a3d54366afccde598a4ba5f3240909044f975266..92f35abee92d281990e17ccdb4f388d33ed67f0e 100644 (file)
@@ -186,6 +186,12 @@ static int slave_configure(struct scsi_device *sdev)
                /* Some devices don't handle VPD pages correctly */
                sdev->skip_vpd_pages = 1;
 
+               /* Do not attempt to use REPORT SUPPORTED OPERATION CODES */
+               sdev->no_report_opcodes = 1;
+
+               /* Do not attempt to use WRITE SAME */
+               sdev->no_write_same = 1;
+
                /* Some disks return the total number of blocks in response
                 * to READ CAPACITY rather than the highest block number.
                 * If this device makes that mistake, tell the sd driver. */
index 779cd954abcbd26d1fc935650d102dc524b8ca5a..d305a5aa3a5d7683a5bcd1c2e60c4a0262f35f65 100644 (file)
@@ -1004,6 +1004,12 @@ UNUSUAL_DEV( 0x07cf, 0x1001, 0x1000, 0x9999,
                USB_SC_8070, USB_PR_CB, NULL,
                US_FL_NEED_OVERRIDE | US_FL_FIX_INQUIRY ),
 
+/* Submitted by Oleksandr Chumachenko <ledest@gmail.com> */
+UNUSUAL_DEV( 0x07cf, 0x1167, 0x0100, 0x0100,
+               "Casio",
+               "EX-N1 DigitalCamera",
+               USB_SC_8070, USB_PR_DEVICE, NULL, 0),
+
 /* Submitted by Hartmut Wahl <hwahl@hwahl.de>*/
 UNUSUAL_DEV( 0x0839, 0x000a, 0x0001, 0x0001,
                "Samsung",
index 072cbbadbc3683ef75fd6ff2420e40463b8f722e..7f93f34b7f913e188aa31fbe82372f409817e9dd 100644 (file)
@@ -379,7 +379,8 @@ static void handle_rx(struct vhost_net *net)
                .hdr.gso_type = VIRTIO_NET_HDR_GSO_NONE
        };
        size_t total_len = 0;
-       int err, headcount, mergeable;
+       int err, mergeable;
+       s16 headcount;
        size_t vhost_hlen, sock_hlen;
        size_t vhost_len, sock_len;
        /* TODO: check that we are running from vhost_worker? */
index c101697a4ba708e06b2ea102ba6000d97eaa0ed8..765a945f8ea12ef2e1a9fc80c428a885f9806320 100644 (file)
@@ -60,7 +60,8 @@ config LCD_LTV350QV
          The LTV350QV panel is present on all ATSTK1000 boards.
 
 config LCD_ILI9320
-       tristate
+       tristate "ILI Technology ILI9320 controller support"
+       depends on SPI
        help
          If you have a panel based on the ILI9320 controller chip
          then say y to include a power driver for it.
index d64ac3842884f4e9eac994dd03fdc311646d27b9..bee92846cfab930f6304a9ebb4316b25b8780bc7 100644 (file)
@@ -365,11 +365,20 @@ struct platform_device *dsi_get_dsidev_from_id(int module)
        struct omap_dss_output *out;
        enum omap_dss_output_id id;
 
-       id = module == 0 ? OMAP_DSS_OUTPUT_DSI1 : OMAP_DSS_OUTPUT_DSI2;
+       switch (module) {
+       case 0:
+               id = OMAP_DSS_OUTPUT_DSI1;
+               break;
+       case 1:
+               id = OMAP_DSS_OUTPUT_DSI2;
+               break;
+       default:
+               return NULL;
+       }
 
        out = omap_dss_get_output(id);
 
-       return out->pdev;
+       return out ? out->pdev : NULL;
 }
 
 static inline void dsi_write_reg(struct platform_device *dsidev,
index 2ab1c3e96553d81297ad5f942eed2cfb76a5064b..5f6eea801b064a37949b3cc66bf9ca5f2dde3431 100644 (file)
@@ -697,11 +697,15 @@ static int dss_get_clocks(void)
 
        dss.dss_clk = clk;
 
-       clk = clk_get(NULL, dss.feat->clk_name);
-       if (IS_ERR(clk)) {
-               DSSERR("Failed to get %s\n", dss.feat->clk_name);
-               r = PTR_ERR(clk);
-               goto err;
+       if (dss.feat->clk_name) {
+               clk = clk_get(NULL, dss.feat->clk_name);
+               if (IS_ERR(clk)) {
+                       DSSERR("Failed to get %s\n", dss.feat->clk_name);
+                       r = PTR_ERR(clk);
+                       goto err;
+               }
+       } else {
+               clk = NULL;
        }
 
        dss.dpll4_m4_ck = clk;
@@ -805,10 +809,10 @@ static int __init dss_init_features(struct device *dev)
 
        if (cpu_is_omap24xx())
                src = &omap24xx_dss_feats;
-       else if (cpu_is_omap34xx())
-               src = &omap34xx_dss_feats;
        else if (cpu_is_omap3630())
                src = &omap3630_dss_feats;
+       else if (cpu_is_omap34xx())
+               src = &omap34xx_dss_feats;
        else if (cpu_is_omap44xx())
                src = &omap44xx_dss_feats;
        else if (soc_is_omap54xx())
index a48a7dd75b3303a3bba28e10b01e4c1f133c00d3..8c9b8b3b7f773cd41c00f78b923070f87c325f70 100644 (file)
@@ -644,8 +644,10 @@ static void hdmi_dump_regs(struct seq_file *s)
 {
        mutex_lock(&hdmi.lock);
 
-       if (hdmi_runtime_get())
+       if (hdmi_runtime_get()) {
+               mutex_unlock(&hdmi.lock);
                return;
+       }
 
        hdmi.ip_data.ops->dump_wrapper(&hdmi.ip_data, s);
        hdmi.ip_data.ops->dump_pll(&hdmi.ip_data, s);
index 606b89f12351d4e1cc2cb234fd4e5c481bf82cda..d630b26a005c7ae2e0bea55b1c0a644fc64ad1e9 100644 (file)
@@ -787,7 +787,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
 
        case OMAPFB_WAITFORVSYNC:
                DBG("ioctl WAITFORVSYNC\n");
-               if (!display && !display->output && !display->output->manager) {
+               if (!display || !display->output || !display->output->manager) {
                        r = -EINVAL;
                        break;
                }
index b7f5173ff9e94214ed40c3c40f4444324e128888..917bb5681684d31490e1b228b60db57cc0d53a7b 100644 (file)
@@ -641,7 +641,6 @@ static void xenfb_backend_changed(struct xenbus_device *dev,
        case XenbusStateReconfiguring:
        case XenbusStateReconfigured:
        case XenbusStateUnknown:
-       case XenbusStateClosed:
                break;
 
        case XenbusStateInitWait:
@@ -670,6 +669,10 @@ InitWait:
                info->feature_resize = val;
                break;
 
+       case XenbusStateClosed:
+               if (dev->state == XenbusStateClosed)
+                       break;
+               /* Missed the backend's CLOSING state -- fallthrough */
        case XenbusStateClosing:
                xenbus_frontend_closed(dev);
                break;
index 1e8659ca27ef4228d55e97ec5cbafc99d861b22a..809b0de59c0982cc30bca6d0b06b6229a5403c65 100644 (file)
@@ -225,8 +225,10 @@ EXPORT_SYMBOL_GPL(register_virtio_device);
 
 void unregister_virtio_device(struct virtio_device *dev)
 {
+       int index = dev->index; /* save for after device release */
+
        device_unregister(&dev->dev);
-       ida_simple_remove(&virtio_index_ida, dev->index);
+       ida_simple_remove(&virtio_index_ida, index);
 }
 EXPORT_SYMBOL_GPL(unregister_virtio_device);
 
index d4dffcd528730330a0d4cff238dcf0b56e3f318b..126d8ce591ce5fc7e69348f746e91e60b04bc4ee 100644 (file)
@@ -3,6 +3,7 @@ menu "Xen driver support"
 
 config XEN_BALLOON
        bool "Xen memory balloon driver"
+       depends on !ARM
        default y
        help
          The balloon driver allows the Xen domain to request more memory from
@@ -145,6 +146,7 @@ config SWIOTLB_XEN
 
 config XEN_TMEM
        bool
+       depends on !ARM
        default y if (CLEANCACHE || FRONTSWAP)
        help
          Shim to interface in-kernel Transcendent Memory hooks
index 0e86370354572ac7d4116eb70cf6e41d1a52cf35..74354708c6c4e7dd9040ead14affbfa88924ca74 100644 (file)
@@ -2,6 +2,7 @@ ifneq ($(CONFIG_ARM),y)
 obj-y  += manage.o balloon.o
 obj-$(CONFIG_HOTPLUG_CPU)              += cpu_hotplug.o
 endif
+obj-$(CONFIG_X86)                      += fallback.o
 obj-y  += grant-table.o features.o events.o
 obj-y  += xenbus/
 
index 31ab82fda38a264cd045c4b52c117eb375f8e80e..d6886d90ccfd53eed62773a755ee282e9553a55f 100644 (file)
@@ -55,7 +55,6 @@
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
 #include <asm/tlb.h>
-#include <asm/e820.h>
 
 #include <asm/xen/hypervisor.h>
 #include <asm/xen/hypercall.h>
@@ -88,7 +87,7 @@ struct balloon_stats balloon_stats;
 EXPORT_SYMBOL_GPL(balloon_stats);
 
 /* We increase/decrease in batches which fit in a page */
-static unsigned long frame_list[PAGE_SIZE / sizeof(unsigned long)];
+static xen_pfn_t frame_list[PAGE_SIZE / sizeof(unsigned long)];
 
 #ifdef CONFIG_HIGHMEM
 #define inc_totalhigh_pages() (totalhigh_pages++)
index 42569c77ccc8886d38b924a457489819d0dd53c4..f3ccc80a455f54c0abd15c1018f2fc79c7a0332a 100644 (file)
@@ -8,7 +8,9 @@
 
 static int xen_dbgp_op(struct usb_hcd *hcd, int op)
 {
+#ifdef CONFIG_PCI
        const struct device *ctrlr = hcd_to_bus(hcd)->controller;
+#endif
        struct physdev_dbgp_op dbgp;
 
        if (!xen_initial_domain())
index 59e10a1286d53ff73aa3e0a6c91a5aed9033de9e..0be4df39e953a5b870948e6ed8a1553a15cc2c2a 100644 (file)
@@ -115,7 +115,9 @@ struct irq_info {
 #define PIRQ_SHAREABLE (1 << 1)
 
 static int *evtchn_to_irq;
+#ifdef CONFIG_X86
 static unsigned long *pirq_eoi_map;
+#endif
 static bool (*pirq_needs_eoi)(unsigned irq);
 
 static DEFINE_PER_CPU(unsigned long [NR_EVENT_CHANNELS/BITS_PER_LONG],
@@ -277,10 +279,12 @@ static unsigned int cpu_from_evtchn(unsigned int evtchn)
        return ret;
 }
 
+#ifdef CONFIG_X86
 static bool pirq_check_eoi_map(unsigned irq)
 {
        return test_bit(pirq_from_irq(irq), pirq_eoi_map);
 }
+#endif
 
 static bool pirq_needs_eoi_flag(unsigned irq)
 {
@@ -1391,10 +1395,10 @@ void xen_evtchn_do_upcall(struct pt_regs *regs)
 {
        struct pt_regs *old_regs = set_irq_regs(regs);
 
+       irq_enter();
 #ifdef CONFIG_X86
        exit_idle();
 #endif
-       irq_enter();
 
        __xen_evtchn_do_upcall();
 
diff --git a/drivers/xen/fallback.c b/drivers/xen/fallback.c
new file mode 100644 (file)
index 0000000..0ef7c4d
--- /dev/null
@@ -0,0 +1,80 @@
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/bug.h>
+#include <linux/export.h>
+#include <asm/hypervisor.h>
+#include <asm/xen/hypercall.h>
+
+int xen_event_channel_op_compat(int cmd, void *arg)
+{
+       struct evtchn_op op;
+       int rc;
+
+       op.cmd = cmd;
+       memcpy(&op.u, arg, sizeof(op.u));
+       rc = _hypercall1(int, event_channel_op_compat, &op);
+
+       switch (cmd) {
+       case EVTCHNOP_close:
+       case EVTCHNOP_send:
+       case EVTCHNOP_bind_vcpu:
+       case EVTCHNOP_unmask:
+               /* no output */
+               break;
+
+#define COPY_BACK(eop) \
+       case EVTCHNOP_##eop: \
+               memcpy(arg, &op.u.eop, sizeof(op.u.eop)); \
+               break
+
+       COPY_BACK(bind_interdomain);
+       COPY_BACK(bind_virq);
+       COPY_BACK(bind_pirq);
+       COPY_BACK(status);
+       COPY_BACK(alloc_unbound);
+       COPY_BACK(bind_ipi);
+#undef COPY_BACK
+
+       default:
+               WARN_ON(rc != -ENOSYS);
+               break;
+       }
+
+       return rc;
+}
+EXPORT_SYMBOL_GPL(xen_event_channel_op_compat);
+
+int HYPERVISOR_physdev_op_compat(int cmd, void *arg)
+{
+       struct physdev_op op;
+       int rc;
+
+       op.cmd = cmd;
+       memcpy(&op.u, arg, sizeof(op.u));
+       rc = _hypercall1(int, physdev_op_compat, &op);
+
+       switch (cmd) {
+       case PHYSDEVOP_IRQ_UNMASK_NOTIFY:
+       case PHYSDEVOP_set_iopl:
+       case PHYSDEVOP_set_iobitmap:
+       case PHYSDEVOP_apic_write:
+               /* no output */
+               break;
+
+#define COPY_BACK(pop, fld) \
+       case PHYSDEVOP_##pop: \
+               memcpy(arg, &op.u.fld, sizeof(op.u.fld)); \
+               break
+
+       COPY_BACK(irq_status_query, irq_status_query);
+       COPY_BACK(apic_read, apic_op);
+       COPY_BACK(ASSIGN_VECTOR, irq_op);
+#undef COPY_BACK
+
+       default:
+               WARN_ON(rc != -ENOSYS);
+               break;
+       }
+
+       return rc;
+}
index 610bfc6be17708594783d231d608c14651625376..2e22df2f7a3f8b57fe44ce8842b825602a012658 100644 (file)
@@ -105,6 +105,21 @@ static void gntdev_print_maps(struct gntdev_priv *priv,
 #endif
 }
 
+static void gntdev_free_map(struct grant_map *map)
+{
+       if (map == NULL)
+               return;
+
+       if (map->pages)
+               free_xenballooned_pages(map->count, map->pages);
+       kfree(map->pages);
+       kfree(map->grants);
+       kfree(map->map_ops);
+       kfree(map->unmap_ops);
+       kfree(map->kmap_ops);
+       kfree(map);
+}
+
 static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count)
 {
        struct grant_map *add;
@@ -142,12 +157,7 @@ static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count)
        return add;
 
 err:
-       kfree(add->pages);
-       kfree(add->grants);
-       kfree(add->map_ops);
-       kfree(add->unmap_ops);
-       kfree(add->kmap_ops);
-       kfree(add);
+       gntdev_free_map(add);
        return NULL;
 }
 
@@ -198,17 +208,9 @@ static void gntdev_put_map(struct grant_map *map)
                evtchn_put(map->notify.event);
        }
 
-       if (map->pages) {
-               if (!use_ptemod)
-                       unmap_grant_pages(map, 0, map->count);
-
-               free_xenballooned_pages(map->count, map->pages);
-       }
-       kfree(map->pages);
-       kfree(map->grants);
-       kfree(map->map_ops);
-       kfree(map->unmap_ops);
-       kfree(map);
+       if (map->pages && !use_ptemod)
+               unmap_grant_pages(map, 0, map->count);
+       gntdev_free_map(map);
 }
 
 /* ------------------------------------------------------------------ */
index b2b0a375b3484b162b0c2ebc6cd09d5584f8ec60..b91f14e831648e68093a02f804f82e4113325360 100644 (file)
@@ -84,7 +84,7 @@ struct gnttab_ops {
         * nr_gframes is the number of frames to map grant table. Returning
         * GNTST_okay means success and negative value means failure.
         */
-       int (*map_frames)(unsigned long *frames, unsigned int nr_gframes);
+       int (*map_frames)(xen_pfn_t *frames, unsigned int nr_gframes);
        /*
         * Release a list of frames which are mapped in map_frames for grant
         * entry status.
@@ -960,7 +960,7 @@ static unsigned nr_status_frames(unsigned nr_grant_frames)
        return (nr_grant_frames * GREFS_PER_GRANT_FRAME + SPP - 1) / SPP;
 }
 
-static int gnttab_map_frames_v1(unsigned long *frames, unsigned int nr_gframes)
+static int gnttab_map_frames_v1(xen_pfn_t *frames, unsigned int nr_gframes)
 {
        int rc;
 
@@ -977,7 +977,7 @@ static void gnttab_unmap_frames_v1(void)
        arch_gnttab_unmap(gnttab_shared.addr, nr_grant_frames);
 }
 
-static int gnttab_map_frames_v2(unsigned long *frames, unsigned int nr_gframes)
+static int gnttab_map_frames_v2(xen_pfn_t *frames, unsigned int nr_gframes)
 {
        uint64_t *sframes;
        unsigned int nr_sframes;
@@ -1029,7 +1029,7 @@ static void gnttab_unmap_frames_v2(void)
 static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
 {
        struct gnttab_setup_table setup;
-       unsigned long *frames;
+       xen_pfn_t *frames;
        unsigned int nr_gframes = end_idx + 1;
        int rc;
 
index 8adb9cc267f96e201ade041441ef8a317ce336d8..71f5c459b088aa5e21066b77adbcb5f34f7b9843 100644 (file)
@@ -361,13 +361,13 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version)
        down_write(&mm->mmap_sem);
 
        vma = find_vma(mm, m.addr);
-       ret = -EINVAL;
        if (!vma ||
            vma->vm_ops != &privcmd_vm_ops ||
            (m.addr != vma->vm_start) ||
            ((m.addr + (nr_pages << PAGE_SHIFT)) != vma->vm_end) ||
            !privcmd_enforce_singleshot_mapping(vma)) {
                up_write(&mm->mmap_sem);
+               ret = -EINVAL;
                goto out;
        }
 
@@ -383,12 +383,16 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version)
 
        up_write(&mm->mmap_sem);
 
-       if (state.global_error && (version == 1)) {
-               /* Write back errors in second pass. */
-               state.user_mfn = (xen_pfn_t *)m.arr;
-               state.err      = err_array;
-               ret = traverse_pages(m.num, sizeof(xen_pfn_t),
-                                    &pagelist, mmap_return_errors_v1, &state);
+       if (version == 1) {
+               if (state.global_error) {
+                       /* Write back errors in second pass. */
+                       state.user_mfn = (xen_pfn_t *)m.arr;
+                       state.err      = err_array;
+                       ret = traverse_pages(m.num, sizeof(xen_pfn_t),
+                                            &pagelist, mmap_return_errors_v1, &state);
+               } else
+                       ret = 0;
+
        } else if (version == 2) {
                ret = __copy_to_user(m.err, err_array, m.num * sizeof(int));
                if (ret)
index 5e5ad7e2885832f64f2131aa43aead50548cae0a..96453f8a85c5543f506ecc128f22e91b3d2dbdbb 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/kobject.h>
+#include <linux/err.h>
 
 #include <asm/xen/hypervisor.h>
 #include <asm/xen/hypercall.h>
@@ -284,7 +285,8 @@ static ssize_t virtual_start_show(struct hyp_sysfs_attr *attr, char *buffer)
                ret = HYPERVISOR_xen_version(XENVER_platform_parameters,
                                             parms);
                if (!ret)
-                       ret = sprintf(buffer, "%lx\n", parms->virt_start);
+                       ret = sprintf(buffer, "%"PRI_xen_ulong"\n",
+                                     parms->virt_start);
                kfree(parms);
        }
 
index 46d140baebd8770463b9d37399f5149220920532..0f478ac483cd418e1a8a0b84fdb1b35651ce6404 100644 (file)
@@ -89,9 +89,15 @@ static int __xen_pcibk_add_pci_dev(struct xen_pcibk_device *pdev,
 
        mutex_lock(&vpci_dev->lock);
 
-       /* Keep multi-function devices together on the virtual PCI bus */
-       for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
-               if (!list_empty(&vpci_dev->dev_list[slot])) {
+       /*
+        * Keep multi-function devices together on the virtual PCI bus, except
+        * virtual functions.
+        */
+       if (!dev->is_virtfn) {
+               for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
+                       if (list_empty(&vpci_dev->dev_list[slot]))
+                               continue;
+
                        t = list_entry(list_first(&vpci_dev->dev_list[slot]),
                                       struct pci_dev_entry, list);
 
@@ -116,7 +122,7 @@ static int __xen_pcibk_add_pci_dev(struct xen_pcibk_device *pdev,
                               pci_name(dev), slot);
                        list_add_tail(&dev_entry->list,
                                      &vpci_dev->dev_list[slot]);
-                       func = PCI_FUNC(dev->devfn);
+                       func = dev->is_virtfn ? 0 : PCI_FUNC(dev->devfn);
                        goto unlock;
                }
        }
index 89f76252a16f20e2638ee578faf4e3cbb4a316c6..ac727028e658f75778fa916ca94e91c5d80e0737 100644 (file)
@@ -458,7 +458,7 @@ static ssize_t xenbus_file_write(struct file *filp,
                goto out;
 
        /* Can't write a xenbus message larger we can buffer */
-       if ((len + u->len) > sizeof(u->u.buffer)) {
+       if (len > sizeof(u->u.buffer) - u->len) {
                /* On error, dump existing buffer */
                u->len = 0;
                rc = -EINVAL;
index f5dda83ad7a55048256f29ab79756c092450c08f..acedeabe589c94eaecd5ab5d478f7e7b3bfbe4af 100644 (file)
@@ -627,6 +627,7 @@ static struct xenbus_watch *find_watch(const char *token)
  */
 static bool xen_strict_xenbus_quirk(void)
 {
+#ifdef CONFIG_X86
        uint32_t eax, ebx, ecx, edx, base;
 
        base = xen_cpuid_base();
@@ -634,6 +635,7 @@ static bool xen_strict_xenbus_quirk(void)
 
        if ((eax >> 16) < 4)
                return true;
+#endif
        return false;
 
 }
index 9298c65ad9c74bb1c4adde9ef9ffa07b397ca63f..b96fc6ce485595f0179bc909c807ae197258e671 100644 (file)
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -75,6 +75,7 @@ static struct kmem_cache *bio_find_or_create_slab(unsigned int extra_size)
        unsigned int sz = sizeof(struct bio) + extra_size;
        struct kmem_cache *slab = NULL;
        struct bio_slab *bslab, *new_bio_slabs;
+       unsigned int new_bio_slab_max;
        unsigned int i, entry = -1;
 
        mutex_lock(&bio_slab_lock);
@@ -97,12 +98,13 @@ static struct kmem_cache *bio_find_or_create_slab(unsigned int extra_size)
                goto out_unlock;
 
        if (bio_slab_nr == bio_slab_max && entry == -1) {
-               bio_slab_max <<= 1;
+               new_bio_slab_max = bio_slab_max << 1;
                new_bio_slabs = krealloc(bio_slabs,
-                                        bio_slab_max * sizeof(struct bio_slab),
+                                        new_bio_slab_max * sizeof(struct bio_slab),
                                         GFP_KERNEL);
                if (!new_bio_slabs)
                        goto out_unlock;
+               bio_slab_max = new_bio_slab_max;
                bio_slabs = new_bio_slabs;
        }
        if (entry == -1)
index b3c1d3dae77d06fcde3fa3ecf36b2af9e2b25d85..1a1e5e3b1eafc7f00454cb2d544b8761161d015e 100644 (file)
@@ -1661,6 +1661,39 @@ static int blkdev_mmap(struct file *file, struct vm_area_struct *vma)
        return ret;
 }
 
+static ssize_t blkdev_splice_read(struct file *file, loff_t *ppos,
+                                 struct pipe_inode_info *pipe, size_t len,
+                                 unsigned int flags)
+{
+       ssize_t ret;
+       struct block_device *bdev = I_BDEV(file->f_mapping->host);
+
+       percpu_down_read(&bdev->bd_block_size_semaphore);
+
+       ret = generic_file_splice_read(file, ppos, pipe, len, flags);
+
+       percpu_up_read(&bdev->bd_block_size_semaphore);
+
+       return ret;
+}
+
+static ssize_t blkdev_splice_write(struct pipe_inode_info *pipe,
+                                  struct file *file, loff_t *ppos, size_t len,
+                                  unsigned int flags)
+{
+       ssize_t ret;
+       struct block_device *bdev = I_BDEV(file->f_mapping->host);
+
+       percpu_down_read(&bdev->bd_block_size_semaphore);
+
+       ret = generic_file_splice_write(pipe, file, ppos, len, flags);
+
+       percpu_up_read(&bdev->bd_block_size_semaphore);
+
+       return ret;
+}
+
+
 /*
  * Try to release a page associated with block device when the system
  * is under memory pressure.
@@ -1699,8 +1732,8 @@ const struct file_operations def_blk_fops = {
 #ifdef CONFIG_COMPAT
        .compat_ioctl   = compat_blkdev_ioctl,
 #endif
-       .splice_read    = generic_file_splice_read,
-       .splice_write   = generic_file_splice_write,
+       .splice_read    = blkdev_splice_read,
+       .splice_write   = blkdev_splice_write,
 };
 
 int ioctl_by_bdev(struct block_device *bdev, unsigned cmd, unsigned long arg)
index f3187938e081c7dcbf842d424f5de6ed06d3f93f..208d8aa5b07e488f1f39cb0877ff46bb5d08d5a6 100644 (file)
@@ -283,9 +283,7 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info,
                goto out;
        }
 
-       rcu_read_lock();
-       root_level = btrfs_header_level(root->node);
-       rcu_read_unlock();
+       root_level = btrfs_old_root_level(root, time_seq);
 
        if (root_level + 1 == level)
                goto out;
@@ -1177,16 +1175,15 @@ int btrfs_find_one_extref(struct btrfs_root *root, u64 inode_objectid,
        return ret;
 }
 
-static char *ref_to_path(struct btrfs_root *fs_root,
-                        struct btrfs_path *path,
-                        u32 name_len, unsigned long name_off,
-                        struct extent_buffer *eb_in, u64 parent,
-                        char *dest, u32 size)
+char *btrfs_ref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path,
+                       u32 name_len, unsigned long name_off,
+                       struct extent_buffer *eb_in, u64 parent,
+                       char *dest, u32 size)
 {
        int slot;
        u64 next_inum;
        int ret;
-       s64 bytes_left = size - 1;
+       s64 bytes_left = ((s64)size) - 1;
        struct extent_buffer *eb = eb_in;
        struct btrfs_key found_key;
        int leave_spinning = path->leave_spinning;
@@ -1266,10 +1263,10 @@ char *btrfs_iref_to_path(struct btrfs_root *fs_root,
                         struct extent_buffer *eb_in, u64 parent,
                         char *dest, u32 size)
 {
-       return ref_to_path(fs_root, path,
-                          btrfs_inode_ref_name_len(eb_in, iref),
-                          (unsigned long)(iref + 1),
-                          eb_in, parent, dest, size);
+       return btrfs_ref_to_path(fs_root, path,
+                                btrfs_inode_ref_name_len(eb_in, iref),
+                                (unsigned long)(iref + 1),
+                                eb_in, parent, dest, size);
 }
 
 /*
@@ -1715,9 +1712,8 @@ static int inode_to_path(u64 inum, u32 name_len, unsigned long name_off,
                                        ipath->fspath->bytes_left - s_ptr : 0;
 
        fspath_min = (char *)ipath->fspath->val + (i + 1) * s_ptr;
-       fspath = ref_to_path(ipath->fs_root, ipath->btrfs_path, name_len,
-                            name_off, eb, inum, fspath_min,
-                            bytes_left);
+       fspath = btrfs_ref_to_path(ipath->fs_root, ipath->btrfs_path, name_len,
+                                  name_off, eb, inum, fspath_min, bytes_left);
        if (IS_ERR(fspath))
                return PTR_ERR(fspath);
 
index e75533043a5ffbab21ff133877c352b743ef6592..d61feca79455bda94308c9ab3608b23409a84c73 100644 (file)
@@ -62,6 +62,10 @@ int btrfs_find_all_roots(struct btrfs_trans_handle *trans,
 char *btrfs_iref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path,
                         struct btrfs_inode_ref *iref, struct extent_buffer *eb,
                         u64 parent, char *dest, u32 size);
+char *btrfs_ref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path,
+                       u32 name_len, unsigned long name_off,
+                       struct extent_buffer *eb_in, u64 parent,
+                       char *dest, u32 size);
 
 struct btrfs_data_container *init_data_container(u32 total_bytes);
 struct inode_fs_paths *init_ipath(s32 total_bytes, struct btrfs_root *fs_root,
index b334362110003165a72b63433b192f2b481c3b01..cdfb4c49a806ad4ba0ebe83b5569a4121a10a220 100644 (file)
@@ -596,6 +596,11 @@ tree_mod_log_insert_move(struct btrfs_fs_info *fs_info,
        if (tree_mod_dont_log(fs_info, eb))
                return 0;
 
+       /*
+        * When we override something during the move, we log these removals.
+        * This can only happen when we move towards the beginning of the
+        * buffer, i.e. dst_slot < src_slot.
+        */
        for (i = 0; i + dst_slot < src_slot && i < nr_items; i++) {
                ret = tree_mod_log_insert_key_locked(fs_info, eb, i + dst_slot,
                                              MOD_LOG_KEY_REMOVE_WHILE_MOVING);
@@ -647,8 +652,6 @@ tree_mod_log_insert_root(struct btrfs_fs_info *fs_info,
        if (tree_mod_dont_log(fs_info, NULL))
                return 0;
 
-       __tree_mod_log_free_eb(fs_info, old_root);
-
        ret = tree_mod_alloc(fs_info, flags, &tm);
        if (ret < 0)
                goto out;
@@ -926,12 +929,7 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans,
                        ret = btrfs_dec_ref(trans, root, buf, 1, 1);
                        BUG_ON(ret); /* -ENOMEM */
                }
-               /*
-                * don't log freeing in case we're freeing the root node, this
-                * is done by tree_mod_log_set_root_pointer later
-                */
-               if (buf != root->node && btrfs_header_level(buf) != 0)
-                       tree_mod_log_free_eb(root->fs_info, buf);
+               tree_mod_log_free_eb(root->fs_info, buf);
                clean_tree_block(trans, root, buf);
                *last_ref = 1;
        }
@@ -1225,6 +1223,8 @@ tree_mod_log_rewind(struct btrfs_fs_info *fs_info, struct extent_buffer *eb,
        free_extent_buffer(eb);
 
        __tree_mod_log_rewind(eb_rewin, time_seq, tm);
+       WARN_ON(btrfs_header_nritems(eb_rewin) >
+               BTRFS_NODEPTRS_PER_BLOCK(fs_info->fs_root));
 
        return eb_rewin;
 }
@@ -1241,9 +1241,11 @@ get_old_root(struct btrfs_root *root, u64 time_seq)
 {
        struct tree_mod_elem *tm;
        struct extent_buffer *eb;
+       struct extent_buffer *old;
        struct tree_mod_root *old_root = NULL;
        u64 old_generation = 0;
        u64 logical;
+       u32 blocksize;
 
        eb = btrfs_read_lock_root_node(root);
        tm = __tree_mod_log_oldest_root(root->fs_info, root, time_seq);
@@ -1259,14 +1261,32 @@ get_old_root(struct btrfs_root *root, u64 time_seq)
        }
 
        tm = tree_mod_log_search(root->fs_info, logical, time_seq);
-       if (old_root)
+       if (old_root && tm && tm->op != MOD_LOG_KEY_REMOVE_WHILE_FREEING) {
+               btrfs_tree_read_unlock(root->node);
+               free_extent_buffer(root->node);
+               blocksize = btrfs_level_size(root, old_root->level);
+               old = read_tree_block(root, logical, blocksize, 0);
+               if (!old) {
+                       pr_warn("btrfs: failed to read tree block %llu from get_old_root\n",
+                               logical);
+                       WARN_ON(1);
+               } else {
+                       eb = btrfs_clone_extent_buffer(old);
+                       free_extent_buffer(old);
+               }
+       } else if (old_root) {
+               btrfs_tree_read_unlock(root->node);
+               free_extent_buffer(root->node);
                eb = alloc_dummy_extent_buffer(logical, root->nodesize);
-       else
+       } else {
                eb = btrfs_clone_extent_buffer(root->node);
-       btrfs_tree_read_unlock(root->node);
-       free_extent_buffer(root->node);
+               btrfs_tree_read_unlock(root->node);
+               free_extent_buffer(root->node);
+       }
+
        if (!eb)
                return NULL;
+       extent_buffer_get(eb);
        btrfs_tree_read_lock(eb);
        if (old_root) {
                btrfs_set_header_bytenr(eb, eb->start);
@@ -1279,11 +1299,28 @@ get_old_root(struct btrfs_root *root, u64 time_seq)
                __tree_mod_log_rewind(eb, time_seq, tm);
        else
                WARN_ON(btrfs_header_level(eb) != 0);
-       extent_buffer_get(eb);
+       WARN_ON(btrfs_header_nritems(eb) > BTRFS_NODEPTRS_PER_BLOCK(root));
 
        return eb;
 }
 
+int btrfs_old_root_level(struct btrfs_root *root, u64 time_seq)
+{
+       struct tree_mod_elem *tm;
+       int level;
+
+       tm = __tree_mod_log_oldest_root(root->fs_info, root, time_seq);
+       if (tm && tm->op == MOD_LOG_ROOT_REPLACE) {
+               level = tm->old_root.level;
+       } else {
+               rcu_read_lock();
+               level = btrfs_header_level(root->node);
+               rcu_read_unlock();
+       }
+
+       return level;
+}
+
 static inline int should_cow_block(struct btrfs_trans_handle *trans,
                                   struct btrfs_root *root,
                                   struct extent_buffer *buf)
@@ -1725,6 +1762,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
                        goto enospc;
                }
 
+               tree_mod_log_free_eb(root->fs_info, root->node);
                tree_mod_log_set_root_pointer(root, child);
                rcu_assign_pointer(root->node, child);
 
@@ -2970,8 +3008,10 @@ static int push_node_left(struct btrfs_trans_handle *trans,
                           push_items * sizeof(struct btrfs_key_ptr));
 
        if (push_items < src_nritems) {
-               tree_mod_log_eb_move(root->fs_info, src, 0, push_items,
-                                    src_nritems - push_items);
+               /*
+                * don't call tree_mod_log_eb_move here, key removal was already
+                * fully logged by tree_mod_log_eb_copy above.
+                */
                memmove_extent_buffer(src, btrfs_node_key_ptr_offset(0),
                                      btrfs_node_key_ptr_offset(push_items),
                                      (src_nritems - push_items) *
index 926c9ffc66d93324d155481c4ecba13d27fa3fec..c72ead869507412ac9939c0748a482035baaf2aa 100644 (file)
@@ -3120,6 +3120,7 @@ static inline u64 btrfs_inc_tree_mod_seq(struct btrfs_fs_info *fs_info)
 {
        return atomic_inc_return(&fs_info->tree_mod_seq);
 }
+int btrfs_old_root_level(struct btrfs_root *root, u64 time_seq);
 
 /* root-item.c */
 int btrfs_find_root_ref(struct btrfs_root *tree_root,
@@ -3338,6 +3339,8 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page,
 int btrfs_update_inode(struct btrfs_trans_handle *trans,
                              struct btrfs_root *root,
                              struct inode *inode);
+int btrfs_update_inode_fallback(struct btrfs_trans_handle *trans,
+                               struct btrfs_root *root, struct inode *inode);
 int btrfs_orphan_add(struct btrfs_trans_handle *trans, struct inode *inode);
 int btrfs_orphan_del(struct btrfs_trans_handle *trans, struct inode *inode);
 int btrfs_orphan_cleanup(struct btrfs_root *root);
index 8036d3a848530daed167453ebfb68eb8a83950f3..472873a94d969a86967e832eac2d452f274f11f9 100644 (file)
@@ -4110,8 +4110,8 @@ struct extent_buffer *alloc_dummy_extent_buffer(u64 start, unsigned long len)
 
        return eb;
 err:
-       for (i--; i >= 0; i--)
-               __free_page(eb->pages[i]);
+       for (; i > 0; i--)
+               __free_page(eb->pages[i - 1]);
        __free_extent_buffer(eb);
        return NULL;
 }
index 85a1e5053fe63a9d8df6682da38198883e00bb22..95542a1b3dfc99632219310f0108788789247fc9 100644 (file)
@@ -94,8 +94,6 @@ static noinline int cow_file_range(struct inode *inode,
                                   struct page *locked_page,
                                   u64 start, u64 end, int *page_started,
                                   unsigned long *nr_written, int unlock);
-static noinline int btrfs_update_inode_fallback(struct btrfs_trans_handle *trans,
-                               struct btrfs_root *root, struct inode *inode);
 
 static int btrfs_init_inode_security(struct btrfs_trans_handle *trans,
                                     struct inode *inode,  struct inode *dir,
@@ -2746,8 +2744,9 @@ noinline int btrfs_update_inode(struct btrfs_trans_handle *trans,
        return btrfs_update_inode_item(trans, root, inode);
 }
 
-static noinline int btrfs_update_inode_fallback(struct btrfs_trans_handle *trans,
-                               struct btrfs_root *root, struct inode *inode)
+noinline int btrfs_update_inode_fallback(struct btrfs_trans_handle *trans,
+                                        struct btrfs_root *root,
+                                        struct inode *inode)
 {
        int ret;
 
index 61168805f175b3c50ffef99b87e97fdeb2643ebd..8fcf9a59c28d08c5c8a6c65e34844e321ca2b66c 100644 (file)
@@ -343,7 +343,8 @@ static noinline int btrfs_ioctl_fitrim(struct file *file, void __user *arg)
                return -EOPNOTSUPP;
        if (copy_from_user(&range, arg, sizeof(range)))
                return -EFAULT;
-       if (range.start > total_bytes)
+       if (range.start > total_bytes ||
+           range.len < fs_info->sb->s_blocksize)
                return -EINVAL;
 
        range.len = min(range.len, total_bytes - range.start);
@@ -570,7 +571,8 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry,
                ret = btrfs_commit_transaction(trans,
                                               root->fs_info->extent_root);
        }
-       BUG_ON(ret);
+       if (ret)
+               goto fail;
 
        ret = pending_snapshot->error;
        if (ret)
index 5039686df6ae8e801ed8985eb5e821a226e18855..fe9d02c45f8e521f87b44d6deff3e5f8d99aa3a9 100644 (file)
@@ -790,8 +790,10 @@ int btrfs_quota_enable(struct btrfs_trans_handle *trans,
        }
 
        path = btrfs_alloc_path();
-       if (!path)
-               return -ENOMEM;
+       if (!path) {
+               ret = -ENOMEM;
+               goto out_free_root;
+       }
 
        key.objectid = 0;
        key.type = BTRFS_QGROUP_STATUS_KEY;
@@ -800,7 +802,7 @@ int btrfs_quota_enable(struct btrfs_trans_handle *trans,
        ret = btrfs_insert_empty_item(trans, quota_root, path, &key,
                                      sizeof(*ptr));
        if (ret)
-               goto out;
+               goto out_free_path;
 
        leaf = path->nodes[0];
        ptr = btrfs_item_ptr(leaf, path->slots[0],
@@ -818,8 +820,15 @@ int btrfs_quota_enable(struct btrfs_trans_handle *trans,
        fs_info->quota_root = quota_root;
        fs_info->pending_quota_state = 1;
        spin_unlock(&fs_info->qgroup_lock);
-out:
+out_free_path:
        btrfs_free_path(path);
+out_free_root:
+       if (ret) {
+               free_extent_buffer(quota_root->node);
+               free_extent_buffer(quota_root->commit_root);
+               kfree(quota_root);
+       }
+out:
        return ret;
 }
 
index c7beb543a4a89300f1e586492b767ea8f9bef683..e78b297b0b00cc990e8eb7a3f1f34619638e5ef4 100644 (file)
@@ -745,31 +745,36 @@ typedef int (*iterate_inode_ref_t)(int num, u64 dir, int index,
                                   void *ctx);
 
 /*
- * Helper function to iterate the entries in ONE btrfs_inode_ref.
+ * Helper function to iterate the entries in ONE btrfs_inode_ref or
+ * btrfs_inode_extref.
  * The iterate callback may return a non zero value to stop iteration. This can
  * be a negative value for error codes or 1 to simply stop it.
  *
- * path must point to the INODE_REF when called.
+ * path must point to the INODE_REF or INODE_EXTREF when called.
  */
 static int iterate_inode_ref(struct send_ctx *sctx,
                             struct btrfs_root *root, struct btrfs_path *path,
                             struct btrfs_key *found_key, int resolve,
                             iterate_inode_ref_t iterate, void *ctx)
 {
-       struct extent_buffer *eb;
+       struct extent_buffer *eb = path->nodes[0];
        struct btrfs_item *item;
        struct btrfs_inode_ref *iref;
+       struct btrfs_inode_extref *extref;
        struct btrfs_path *tmp_path;
        struct fs_path *p;
-       u32 cur;
-       u32 len;
+       u32 cur = 0;
        u32 total;
-       int slot;
+       int slot = path->slots[0];
        u32 name_len;
        char *start;
        int ret = 0;
-       int num;
+       int num = 0;
        int index;
+       u64 dir;
+       unsigned long name_off;
+       unsigned long elem_size;
+       unsigned long ptr;
 
        p = fs_path_alloc_reversed(sctx);
        if (!p)
@@ -781,24 +786,40 @@ static int iterate_inode_ref(struct send_ctx *sctx,
                return -ENOMEM;
        }
 
-       eb = path->nodes[0];
-       slot = path->slots[0];
-       item = btrfs_item_nr(eb, slot);
-       iref = btrfs_item_ptr(eb, slot, struct btrfs_inode_ref);
-       cur = 0;
-       len = 0;
-       total = btrfs_item_size(eb, item);
 
-       num = 0;
+       if (found_key->type == BTRFS_INODE_REF_KEY) {
+               ptr = (unsigned long)btrfs_item_ptr(eb, slot,
+                                                   struct btrfs_inode_ref);
+               item = btrfs_item_nr(eb, slot);
+               total = btrfs_item_size(eb, item);
+               elem_size = sizeof(*iref);
+       } else {
+               ptr = btrfs_item_ptr_offset(eb, slot);
+               total = btrfs_item_size_nr(eb, slot);
+               elem_size = sizeof(*extref);
+       }
+
        while (cur < total) {
                fs_path_reset(p);
 
-               name_len = btrfs_inode_ref_name_len(eb, iref);
-               index = btrfs_inode_ref_index(eb, iref);
+               if (found_key->type == BTRFS_INODE_REF_KEY) {
+                       iref = (struct btrfs_inode_ref *)(ptr + cur);
+                       name_len = btrfs_inode_ref_name_len(eb, iref);
+                       name_off = (unsigned long)(iref + 1);
+                       index = btrfs_inode_ref_index(eb, iref);
+                       dir = found_key->offset;
+               } else {
+                       extref = (struct btrfs_inode_extref *)(ptr + cur);
+                       name_len = btrfs_inode_extref_name_len(eb, extref);
+                       name_off = (unsigned long)&extref->name;
+                       index = btrfs_inode_extref_index(eb, extref);
+                       dir = btrfs_inode_extref_parent(eb, extref);
+               }
+
                if (resolve) {
-                       start = btrfs_iref_to_path(root, tmp_path, iref, eb,
-                                               found_key->offset, p->buf,
-                                               p->buf_len);
+                       start = btrfs_ref_to_path(root, tmp_path, name_len,
+                                                 name_off, eb, dir,
+                                                 p->buf, p->buf_len);
                        if (IS_ERR(start)) {
                                ret = PTR_ERR(start);
                                goto out;
@@ -809,9 +830,10 @@ static int iterate_inode_ref(struct send_ctx *sctx,
                                                p->buf_len + p->buf - start);
                                if (ret < 0)
                                        goto out;
-                               start = btrfs_iref_to_path(root, tmp_path, iref,
-                                               eb, found_key->offset, p->buf,
-                                               p->buf_len);
+                               start = btrfs_ref_to_path(root, tmp_path,
+                                                         name_len, name_off,
+                                                         eb, dir,
+                                                         p->buf, p->buf_len);
                                if (IS_ERR(start)) {
                                        ret = PTR_ERR(start);
                                        goto out;
@@ -820,21 +842,16 @@ static int iterate_inode_ref(struct send_ctx *sctx,
                        }
                        p->start = start;
                } else {
-                       ret = fs_path_add_from_extent_buffer(p, eb,
-                                       (unsigned long)(iref + 1), name_len);
+                       ret = fs_path_add_from_extent_buffer(p, eb, name_off,
+                                                            name_len);
                        if (ret < 0)
                                goto out;
                }
 
-
-               len = sizeof(*iref) + name_len;
-               iref = (struct btrfs_inode_ref *)((char *)iref + len);
-               cur += len;
-
-               ret = iterate(num, found_key->offset, index, p, ctx);
+               cur += elem_size + name_len;
+               ret = iterate(num, dir, index, p, ctx);
                if (ret)
                        goto out;
-
                num++;
        }
 
@@ -998,7 +1015,8 @@ static int get_inode_path(struct send_ctx *sctx, struct btrfs_root *root,
        }
        btrfs_item_key_to_cpu(p->nodes[0], &found_key, p->slots[0]);
        if (found_key.objectid != ino ||
-               found_key.type != BTRFS_INODE_REF_KEY) {
+           (found_key.type != BTRFS_INODE_REF_KEY &&
+            found_key.type != BTRFS_INODE_EXTREF_KEY)) {
                ret = -ENOENT;
                goto out;
        }
@@ -1551,8 +1569,8 @@ static int get_first_ref(struct send_ctx *sctx,
        struct btrfs_key key;
        struct btrfs_key found_key;
        struct btrfs_path *path;
-       struct btrfs_inode_ref *iref;
        int len;
+       u64 parent_dir;
 
        path = alloc_path_for_send();
        if (!path)
@@ -1568,27 +1586,41 @@ static int get_first_ref(struct send_ctx *sctx,
        if (!ret)
                btrfs_item_key_to_cpu(path->nodes[0], &found_key,
                                path->slots[0]);
-       if (ret || found_key.objectid != key.objectid ||
-           found_key.type != key.type) {
+       if (ret || found_key.objectid != ino ||
+           (found_key.type != BTRFS_INODE_REF_KEY &&
+            found_key.type != BTRFS_INODE_EXTREF_KEY)) {
                ret = -ENOENT;
                goto out;
        }
 
-       iref = btrfs_item_ptr(path->nodes[0], path->slots[0],
-                       struct btrfs_inode_ref);
-       len = btrfs_inode_ref_name_len(path->nodes[0], iref);
-       ret = fs_path_add_from_extent_buffer(name, path->nodes[0],
-                       (unsigned long)(iref + 1), len);
+       if (key.type == BTRFS_INODE_REF_KEY) {
+               struct btrfs_inode_ref *iref;
+               iref = btrfs_item_ptr(path->nodes[0], path->slots[0],
+                                     struct btrfs_inode_ref);
+               len = btrfs_inode_ref_name_len(path->nodes[0], iref);
+               ret = fs_path_add_from_extent_buffer(name, path->nodes[0],
+                                                    (unsigned long)(iref + 1),
+                                                    len);
+               parent_dir = found_key.offset;
+       } else {
+               struct btrfs_inode_extref *extref;
+               extref = btrfs_item_ptr(path->nodes[0], path->slots[0],
+                                       struct btrfs_inode_extref);
+               len = btrfs_inode_extref_name_len(path->nodes[0], extref);
+               ret = fs_path_add_from_extent_buffer(name, path->nodes[0],
+                                       (unsigned long)&extref->name, len);
+               parent_dir = btrfs_inode_extref_parent(path->nodes[0], extref);
+       }
        if (ret < 0)
                goto out;
        btrfs_release_path(path);
 
-       ret = get_inode_info(root, found_key.offset, NULL, dir_gen, NULL, NULL,
+       ret = get_inode_info(root, parent_dir, NULL, dir_gen, NULL, NULL,
                        NULL, NULL);
        if (ret < 0)
                goto out;
 
-       *dir = found_key.offset;
+       *dir = parent_dir;
 
 out:
        btrfs_free_path(path);
@@ -2430,7 +2462,8 @@ verbose_printk("btrfs: send_create_inode %llu\n", ino);
                TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH_LINK, p);
        } else if (S_ISCHR(mode) || S_ISBLK(mode) ||
                   S_ISFIFO(mode) || S_ISSOCK(mode)) {
-               TLV_PUT_U64(sctx, BTRFS_SEND_A_RDEV, rdev);
+               TLV_PUT_U64(sctx, BTRFS_SEND_A_RDEV, new_encode_dev(rdev));
+               TLV_PUT_U64(sctx, BTRFS_SEND_A_MODE, mode);
        }
 
        ret = send_cmd(sctx);
@@ -3226,7 +3259,8 @@ static int process_all_refs(struct send_ctx *sctx,
                btrfs_item_key_to_cpu(eb, &found_key, slot);
 
                if (found_key.objectid != key.objectid ||
-                   found_key.type != key.type)
+                   (found_key.type != BTRFS_INODE_REF_KEY &&
+                    found_key.type != BTRFS_INODE_EXTREF_KEY))
                        break;
 
                ret = iterate_inode_ref(sctx, root, path, &found_key, 0, cb,
@@ -3987,7 +4021,7 @@ static int process_recorded_refs_if_needed(struct send_ctx *sctx, int at_end)
        if (sctx->cur_ino == 0)
                goto out;
        if (!at_end && sctx->cur_ino == sctx->cmp_key->objectid &&
-           sctx->cmp_key->type <= BTRFS_INODE_REF_KEY)
+           sctx->cmp_key->type <= BTRFS_INODE_EXTREF_KEY)
                goto out;
        if (list_empty(&sctx->new_refs) && list_empty(&sctx->deleted_refs))
                goto out;
@@ -4033,22 +4067,21 @@ static int finish_inode_if_needed(struct send_ctx *sctx, int at_end)
        if (ret < 0)
                goto out;
 
-       if (!S_ISLNK(sctx->cur_inode_mode)) {
-               if (!sctx->parent_root || sctx->cur_inode_new) {
+       if (!sctx->parent_root || sctx->cur_inode_new) {
+               need_chown = 1;
+               if (!S_ISLNK(sctx->cur_inode_mode))
                        need_chmod = 1;
-                       need_chown = 1;
-               } else {
-                       ret = get_inode_info(sctx->parent_root, sctx->cur_ino,
-                                       NULL, NULL, &right_mode, &right_uid,
-                                       &right_gid, NULL);
-                       if (ret < 0)
-                               goto out;
+       } else {
+               ret = get_inode_info(sctx->parent_root, sctx->cur_ino,
+                               NULL, NULL, &right_mode, &right_uid,
+                               &right_gid, NULL);
+               if (ret < 0)
+                       goto out;
 
-                       if (left_uid != right_uid || left_gid != right_gid)
-                               need_chown = 1;
-                       if (left_mode != right_mode)
-                               need_chmod = 1;
-               }
+               if (left_uid != right_uid || left_gid != right_gid)
+                       need_chown = 1;
+               if (!S_ISLNK(sctx->cur_inode_mode) && left_mode != right_mode)
+                       need_chmod = 1;
        }
 
        if (S_ISREG(sctx->cur_inode_mode)) {
@@ -4335,7 +4368,8 @@ static int changed_cb(struct btrfs_root *left_root,
 
        if (key->type == BTRFS_INODE_ITEM_KEY)
                ret = changed_inode(sctx, result);
-       else if (key->type == BTRFS_INODE_REF_KEY)
+       else if (key->type == BTRFS_INODE_REF_KEY ||
+                key->type == BTRFS_INODE_EXTREF_KEY)
                ret = changed_ref(sctx, result);
        else if (key->type == BTRFS_XATTR_ITEM_KEY)
                ret = changed_xattr(sctx, result);
index 77db875b511638b7ff94854c6b1482942da2b3fb..04bbfb1052ebfee9db25427d5542e795cac351cd 100644 (file)
@@ -1200,7 +1200,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
        btrfs_i_size_write(parent_inode, parent_inode->i_size +
                                         dentry->d_name.len * 2);
        parent_inode->i_mtime = parent_inode->i_ctime = CURRENT_TIME;
-       ret = btrfs_update_inode(trans, parent_root, parent_inode);
+       ret = btrfs_update_inode_fallback(trans, parent_root, parent_inode);
        if (ret)
                btrfs_abort_transaction(trans, root, ret);
 fail:
index 029b903a4ae3797322e05090790b86c9e8596c43..0f5ebb72a5ea01693b339d66e3f928de9b783f78 100644 (file)
@@ -1819,6 +1819,13 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
                                    "Failed to relocate sys chunks after "
                                    "device initialization. This can be fixed "
                                    "using the \"btrfs balance\" command.");
+               trans = btrfs_attach_transaction(root);
+               if (IS_ERR(trans)) {
+                       if (PTR_ERR(trans) == -ENOENT)
+                               return 0;
+                       return PTR_ERR(trans);
+               }
+               ret = btrfs_commit_transaction(trans, root);
        }
 
        return ret;
index 02ce90972d81ca6e8b60ed580931c676c441fc2c..9349bb37a2fe68df93651e6afeb384468157edd2 100644 (file)
@@ -90,6 +90,8 @@ static int ceph_encode_fh(struct inode *inode, u32 *rawfh, int *max_len,
                *max_len = handle_length;
                type = 255;
        }
+       if (dentry)
+               dput(dentry);
        return type;
 }
 
index 3f152b92a94ad2824876fd99c9fbfdd05098d0cf..afc2bb6917806e85ee916d8b2c25cb2183890055 100644 (file)
@@ -471,9 +471,19 @@ static int exact_lock(dev_t dev, void *data)
  */
 int cdev_add(struct cdev *p, dev_t dev, unsigned count)
 {
+       int error;
+
        p->dev = dev;
        p->count = count;
-       return kobj_map(cdev_map, dev, count, NULL, exact_match, exact_lock, p);
+
+       error = kobj_map(cdev_map, dev, count, NULL,
+                        exact_match, exact_lock, p);
+       if (error)
+               return error;
+
+       kobject_get(p->kobj.parent);
+
+       return 0;
 }
 
 static void cdev_unmap(dev_t dev, unsigned count)
@@ -498,14 +508,20 @@ void cdev_del(struct cdev *p)
 static void cdev_default_release(struct kobject *kobj)
 {
        struct cdev *p = container_of(kobj, struct cdev, kobj);
+       struct kobject *parent = kobj->parent;
+
        cdev_purge(p);
+       kobject_put(parent);
 }
 
 static void cdev_dynamic_release(struct kobject *kobj)
 {
        struct cdev *p = container_of(kobj, struct cdev, kobj);
+       struct kobject *parent = kobj->parent;
+
        cdev_purge(p);
        kfree(p);
+       kobject_put(parent);
 }
 
 static struct kobj_type ktype_cdev_default = {
index fc783e264420a890751aa81e819fc8b53aaa1a81..0fb15bbbe43cd955150336dec51b415ee1901c5a 100644 (file)
@@ -224,6 +224,13 @@ sid_to_str(struct cifs_sid *sidptr, char *sidstr)
        }
 }
 
+static void
+cifs_copy_sid(struct cifs_sid *dst, const struct cifs_sid *src)
+{
+       memcpy(dst, src, sizeof(*dst));
+       dst->num_subauth = min_t(u8, src->num_subauth, NUM_SUBAUTHS);
+}
+
 static void
 id_rb_insert(struct rb_root *root, struct cifs_sid *sidptr,
                struct cifs_sid_id **psidid, char *typestr)
@@ -248,7 +255,7 @@ id_rb_insert(struct rb_root *root, struct cifs_sid *sidptr,
                }
        }
 
-       memcpy(&(*psidid)->sid, sidptr, sizeof(struct cifs_sid));
+       cifs_copy_sid(&(*psidid)->sid, sidptr);
        (*psidid)->time = jiffies - (SID_MAP_RETRY + 1);
        (*psidid)->refcount = 0;
 
@@ -354,7 +361,7 @@ id_to_sid(unsigned long cid, uint sidtype, struct cifs_sid *ssid)
         * any fields of the node after a reference is put .
         */
        if (test_bit(SID_ID_MAPPED, &psidid->state)) {
-               memcpy(ssid, &psidid->sid, sizeof(struct cifs_sid));
+               cifs_copy_sid(ssid, &psidid->sid);
                psidid->time = jiffies; /* update ts for accessing */
                goto id_sid_out;
        }
@@ -370,14 +377,14 @@ id_to_sid(unsigned long cid, uint sidtype, struct cifs_sid *ssid)
                if (IS_ERR(sidkey)) {
                        rc = -EINVAL;
                        cFYI(1, "%s: Can't map and id to a SID", __func__);
+               } else if (sidkey->datalen < sizeof(struct cifs_sid)) {
+                       rc = -EIO;
+                       cFYI(1, "%s: Downcall contained malformed key "
+                               "(datalen=%hu)", __func__, sidkey->datalen);
                } else {
                        lsid = (struct cifs_sid *)sidkey->payload.data;
-                       memcpy(&psidid->sid, lsid,
-                               sidkey->datalen < sizeof(struct cifs_sid) ?
-                               sidkey->datalen : sizeof(struct cifs_sid));
-                       memcpy(ssid, &psidid->sid,
-                               sidkey->datalen < sizeof(struct cifs_sid) ?
-                               sidkey->datalen : sizeof(struct cifs_sid));
+                       cifs_copy_sid(&psidid->sid, lsid);
+                       cifs_copy_sid(ssid, &psidid->sid);
                        set_bit(SID_ID_MAPPED, &psidid->state);
                        key_put(sidkey);
                        kfree(psidid->sidstr);
@@ -396,7 +403,7 @@ id_to_sid(unsigned long cid, uint sidtype, struct cifs_sid *ssid)
                        return rc;
                }
                if (test_bit(SID_ID_MAPPED, &psidid->state))
-                       memcpy(ssid, &psidid->sid, sizeof(struct cifs_sid));
+                       cifs_copy_sid(ssid, &psidid->sid);
                else
                        rc = -EINVAL;
        }
@@ -675,8 +682,6 @@ int compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
 static void copy_sec_desc(const struct cifs_ntsd *pntsd,
                                struct cifs_ntsd *pnntsd, __u32 sidsoffset)
 {
-       int i;
-
        struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
        struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
 
@@ -692,26 +697,14 @@ static void copy_sec_desc(const struct cifs_ntsd *pntsd,
        owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
                                le32_to_cpu(pntsd->osidoffset));
        nowner_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset);
-
-       nowner_sid_ptr->revision = owner_sid_ptr->revision;
-       nowner_sid_ptr->num_subauth = owner_sid_ptr->num_subauth;
-       for (i = 0; i < 6; i++)
-               nowner_sid_ptr->authority[i] = owner_sid_ptr->authority[i];
-       for (i = 0; i < 5; i++)
-               nowner_sid_ptr->sub_auth[i] = owner_sid_ptr->sub_auth[i];
+       cifs_copy_sid(nowner_sid_ptr, owner_sid_ptr);
 
        /* copy group sid */
        group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
                                le32_to_cpu(pntsd->gsidoffset));
        ngroup_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset +
                                        sizeof(struct cifs_sid));
-
-       ngroup_sid_ptr->revision = group_sid_ptr->revision;
-       ngroup_sid_ptr->num_subauth = group_sid_ptr->num_subauth;
-       for (i = 0; i < 6; i++)
-               ngroup_sid_ptr->authority[i] = group_sid_ptr->authority[i];
-       for (i = 0; i < 5; i++)
-               ngroup_sid_ptr->sub_auth[i] = group_sid_ptr->sub_auth[i];
+       cifs_copy_sid(ngroup_sid_ptr, group_sid_ptr);
 
        return;
 }
@@ -1120,8 +1113,7 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
                                kfree(nowner_sid_ptr);
                                return rc;
                        }
-                       memcpy(owner_sid_ptr, nowner_sid_ptr,
-                                       sizeof(struct cifs_sid));
+                       cifs_copy_sid(owner_sid_ptr, nowner_sid_ptr);
                        kfree(nowner_sid_ptr);
                        *aclflag = CIFS_ACL_OWNER;
                }
@@ -1139,8 +1131,7 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
                                kfree(ngroup_sid_ptr);
                                return rc;
                        }
-                       memcpy(group_sid_ptr, ngroup_sid_ptr,
-                                       sizeof(struct cifs_sid));
+                       cifs_copy_sid(group_sid_ptr, ngroup_sid_ptr);
                        kfree(ngroup_sid_ptr);
                        *aclflag = CIFS_ACL_GROUP;
                }
index 7c0a8128364546111322b4a89caef9009a276980..d3671f2acb29bd313779cf8022efe4c41e9987ef 100644 (file)
@@ -398,7 +398,16 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,
         * in network traffic in the other paths.
         */
        if (!(oflags & O_CREAT)) {
-               struct dentry *res = cifs_lookup(inode, direntry, 0);
+               struct dentry *res;
+
+               /*
+                * Check for hashed negative dentry. We have already revalidated
+                * the dentry and it is fine. No need to perform another lookup.
+                */
+               if (!d_unhashed(direntry))
+                       return -ENOENT;
+
+               res = cifs_lookup(inode, direntry, 0);
                if (IS_ERR(res))
                        return PTR_ERR(res);
 
index f5054025f9da7c154b067db092cc44f8b953f835..4c6285fff598e1faf9bb471f8b3b5593db74b355 100644 (file)
@@ -210,6 +210,8 @@ static int do_video_set_spu_palette(unsigned int fd, unsigned int cmd,
 
        err  = get_user(palp, &up->palette);
        err |= get_user(length, &up->length);
+       if (err)
+               return -EFAULT;
 
        up_native = compat_alloc_user_space(sizeof(struct video_spu_palette));
        err  = put_user(compat_ptr(palp), &up_native->palette);
index da72250ddc1cf2331336a23cbe8239bf880a10cf..cd96649bfe62da9e408dbd629f56f6452c139bc9 100644 (file)
@@ -346,7 +346,7 @@ static inline struct epitem *ep_item_from_epqueue(poll_table *p)
 /* Tells if the epoll_ctl(2) operation needs an event copy from userspace */
 static inline int ep_op_has_event(int op)
 {
-       return op == EPOLL_CTL_ADD || op == EPOLL_CTL_MOD;
+       return op != EPOLL_CTL_DEL;
 }
 
 /* Initialize the poll safe wake up structure */
@@ -676,34 +676,6 @@ static int ep_remove(struct eventpoll *ep, struct epitem *epi)
        return 0;
 }
 
-/*
- * Disables a "struct epitem" in the eventpoll set. Returns -EBUSY if the item
- * had no event flags set, indicating that another thread may be currently
- * handling that item's events (in the case that EPOLLONESHOT was being
- * used). Otherwise a zero result indicates that the item has been disabled
- * from receiving events. A disabled item may be re-enabled via
- * EPOLL_CTL_MOD. Must be called with "mtx" held.
- */
-static int ep_disable(struct eventpoll *ep, struct epitem *epi)
-{
-       int result = 0;
-       unsigned long flags;
-
-       spin_lock_irqsave(&ep->lock, flags);
-       if (epi->event.events & ~EP_PRIVATE_BITS) {
-               if (ep_is_linked(&epi->rdllink))
-                       list_del_init(&epi->rdllink);
-               /* Ensure ep_poll_callback will not add epi back onto ready
-                  list: */
-               epi->event.events &= EP_PRIVATE_BITS;
-               }
-       else
-               result = -EBUSY;
-       spin_unlock_irqrestore(&ep->lock, flags);
-
-       return result;
-}
-
 static void ep_free(struct eventpoll *ep)
 {
        struct rb_node *rbp;
@@ -1048,6 +1020,8 @@ static void ep_rbtree_insert(struct eventpoll *ep, struct epitem *epi)
        rb_insert_color(&epi->rbn, &ep->rbr);
 }
 
+
+
 #define PATH_ARR_SIZE 5
 /*
  * These are the number paths of length 1 to 5, that we are allowing to emanate
@@ -1813,12 +1787,6 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
                } else
                        error = -ENOENT;
                break;
-       case EPOLL_CTL_DISABLE:
-               if (epi)
-                       error = ep_disable(ep, epi);
-               else
-                       error = -ENOENT;
-               break;
        }
        mutex_unlock(&ep->mtx);
 
index 8b9011b67041ddcd57dbcc42e77fa7d0d8b05f7e..0039055b1fc6533c636ca98dd2b9ad73b52d5de6 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1083,7 +1083,8 @@ int flush_old_exec(struct linux_binprm * bprm)
        bprm->mm = NULL;                /* We're using it now */
 
        set_fs(USER_DS);
-       current->flags &= ~(PF_RANDOMIZE | PF_FORKNOEXEC | PF_KTHREAD);
+       current->flags &=
+               ~(PF_RANDOMIZE | PF_FORKNOEXEC | PF_KTHREAD | PF_NOFREEZE);
        flush_thread();
        current->personality &= ~bprm->per_clear;
 
index 7320a66e958f8d45e796c796ee150b786c3f7f8e..22548f56197b52cf06b343285b7e7beb7d74cb10 100644 (file)
@@ -2101,8 +2101,9 @@ int ext3_trim_fs(struct super_block *sb, struct fstrim_range *range)
        end = start + (range->len >> sb->s_blocksize_bits) - 1;
        minlen = range->minlen >> sb->s_blocksize_bits;
 
-       if (unlikely(minlen > EXT3_BLOCKS_PER_GROUP(sb)) ||
-           unlikely(start >= max_blks))
+       if (minlen > EXT3_BLOCKS_PER_GROUP(sb) ||
+           start >= max_blks ||
+           range->len < sb->s_blocksize)
                return -EINVAL;
        if (end >= max_blks)
                end = max_blks - 1;
index 1b5089067d018d581c68242f39fcf522a8fee55d..cf1821784a16bff41349319400940c7e4218fa5a 100644 (file)
@@ -174,8 +174,7 @@ void ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
                ext4_free_inodes_set(sb, gdp, 0);
                ext4_itable_unused_set(sb, gdp, 0);
                memset(bh->b_data, 0xff, sb->s_blocksize);
-               ext4_block_bitmap_csum_set(sb, block_group, gdp, bh,
-                                          EXT4_BLOCKS_PER_GROUP(sb) / 8);
+               ext4_block_bitmap_csum_set(sb, block_group, gdp, bh);
                return;
        }
        memset(bh->b_data, 0, sb->s_blocksize);
@@ -212,8 +211,7 @@ void ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
         */
        ext4_mark_bitmap_end(num_clusters_in_group(sb, block_group),
                             sb->s_blocksize * 8, bh->b_data);
-       ext4_block_bitmap_csum_set(sb, block_group, gdp, bh,
-                                  EXT4_BLOCKS_PER_GROUP(sb) / 8);
+       ext4_block_bitmap_csum_set(sb, block_group, gdp, bh);
        ext4_group_desc_csum_set(sb, block_group, gdp);
 }
 
@@ -350,7 +348,7 @@ void ext4_validate_block_bitmap(struct super_block *sb,
                return;
        }
        if (unlikely(!ext4_block_bitmap_csum_verify(sb, block_group,
-                       desc, bh, EXT4_BLOCKS_PER_GROUP(sb) / 8))) {
+                       desc, bh))) {
                ext4_unlock_group(sb, block_group);
                ext4_error(sb, "bg %u: bad block bitmap checksum", block_group);
                return;
index 5c2d1813ebe919188d53dac74de8b512a7f02965..3285aa5a706af3f97c6a182a12304c7478177d9d 100644 (file)
@@ -58,11 +58,12 @@ void ext4_inode_bitmap_csum_set(struct super_block *sb, ext4_group_t group,
 
 int ext4_block_bitmap_csum_verify(struct super_block *sb, ext4_group_t group,
                                  struct ext4_group_desc *gdp,
-                                 struct buffer_head *bh, int sz)
+                                 struct buffer_head *bh)
 {
        __u32 hi;
        __u32 provided, calculated;
        struct ext4_sb_info *sbi = EXT4_SB(sb);
+       int sz = EXT4_CLUSTERS_PER_GROUP(sb) / 8;
 
        if (!EXT4_HAS_RO_COMPAT_FEATURE(sb,
                                        EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
@@ -84,8 +85,9 @@ int ext4_block_bitmap_csum_verify(struct super_block *sb, ext4_group_t group,
 
 void ext4_block_bitmap_csum_set(struct super_block *sb, ext4_group_t group,
                                struct ext4_group_desc *gdp,
-                               struct buffer_head *bh, int sz)
+                               struct buffer_head *bh)
 {
+       int sz = EXT4_CLUSTERS_PER_GROUP(sb) / 8;
        __u32 csum;
        struct ext4_sb_info *sbi = EXT4_SB(sb);
 
index 3ab2539b7b2eb477222a3dbb7dd8b51cea3cca84..3c20de1d59d0d44586199ade586864758e2ce204 100644 (file)
@@ -1882,10 +1882,10 @@ int ext4_inode_bitmap_csum_verify(struct super_block *sb, ext4_group_t group,
                                  struct buffer_head *bh, int sz);
 void ext4_block_bitmap_csum_set(struct super_block *sb, ext4_group_t group,
                                struct ext4_group_desc *gdp,
-                               struct buffer_head *bh, int sz);
+                               struct buffer_head *bh);
 int ext4_block_bitmap_csum_verify(struct super_block *sb, ext4_group_t group,
                                  struct ext4_group_desc *gdp,
-                                 struct buffer_head *bh, int sz);
+                                 struct buffer_head *bh);
 
 /* balloc.c */
 extern void ext4_validate_block_bitmap(struct super_block *sb,
@@ -2063,8 +2063,7 @@ extern int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count);
 extern int ext4_calculate_overhead(struct super_block *sb);
 extern int ext4_superblock_csum_verify(struct super_block *sb,
                                       struct ext4_super_block *es);
-extern void ext4_superblock_csum_set(struct super_block *sb,
-                                    struct ext4_super_block *es);
+extern void ext4_superblock_csum_set(struct super_block *sb);
 extern void *ext4_kvmalloc(size_t size, gfp_t flags);
 extern void *ext4_kvzalloc(size_t size, gfp_t flags);
 extern void ext4_kvfree(void *ptr);
index bfa65b49d4243d75a5c73456fc2ee4e3698537f4..b4323ba846b52ad09fe0740699ea2d82ff92ba65 100644 (file)
@@ -143,17 +143,13 @@ int __ext4_handle_dirty_super(const char *where, unsigned int line,
        struct buffer_head *bh = EXT4_SB(sb)->s_sbh;
        int err = 0;
 
+       ext4_superblock_csum_set(sb);
        if (ext4_handle_valid(handle)) {
-               ext4_superblock_csum_set(sb,
-                               (struct ext4_super_block *)bh->b_data);
                err = jbd2_journal_dirty_metadata(handle, bh);
                if (err)
                        ext4_journal_abort_handle(where, line, __func__,
                                                  bh, handle, err);
-       } else {
-               ext4_superblock_csum_set(sb,
-                               (struct ext4_super_block *)bh->b_data);
+       } else
                mark_buffer_dirty(bh);
-       }
        return err;
 }
index 1c94cca35ed1a12ce42ce39bddea7c9dd23111cf..7011ac967208e941272f09a07e3292d72ef576f9 100644 (file)
@@ -52,6 +52,9 @@
 #define EXT4_EXT_MARK_UNINIT1  0x2  /* mark first half uninitialized */
 #define EXT4_EXT_MARK_UNINIT2  0x4  /* mark second half uninitialized */
 
+#define EXT4_EXT_DATA_VALID1   0x8  /* first half contains valid data */
+#define EXT4_EXT_DATA_VALID2   0x10 /* second half contains valid data */
+
 static __le32 ext4_extent_block_csum(struct inode *inode,
                                     struct ext4_extent_header *eh)
 {
@@ -2914,6 +2917,9 @@ static int ext4_split_extent_at(handle_t *handle,
        unsigned int ee_len, depth;
        int err = 0;
 
+       BUG_ON((split_flag & (EXT4_EXT_DATA_VALID1 | EXT4_EXT_DATA_VALID2)) ==
+              (EXT4_EXT_DATA_VALID1 | EXT4_EXT_DATA_VALID2));
+
        ext_debug("ext4_split_extents_at: inode %lu, logical"
                "block %llu\n", inode->i_ino, (unsigned long long)split);
 
@@ -2972,7 +2978,14 @@ static int ext4_split_extent_at(handle_t *handle,
 
        err = ext4_ext_insert_extent(handle, inode, path, &newex, flags);
        if (err == -ENOSPC && (EXT4_EXT_MAY_ZEROOUT & split_flag)) {
-               err = ext4_ext_zeroout(inode, &orig_ex);
+               if (split_flag & (EXT4_EXT_DATA_VALID1|EXT4_EXT_DATA_VALID2)) {
+                       if (split_flag & EXT4_EXT_DATA_VALID1)
+                               err = ext4_ext_zeroout(inode, ex2);
+                       else
+                               err = ext4_ext_zeroout(inode, ex);
+               } else
+                       err = ext4_ext_zeroout(inode, &orig_ex);
+
                if (err)
                        goto fix_extent_len;
                /* update the extent length and mark as initialized */
@@ -3025,12 +3038,13 @@ static int ext4_split_extent(handle_t *handle,
        uninitialized = ext4_ext_is_uninitialized(ex);
 
        if (map->m_lblk + map->m_len < ee_block + ee_len) {
-               split_flag1 = split_flag & EXT4_EXT_MAY_ZEROOUT ?
-                             EXT4_EXT_MAY_ZEROOUT : 0;
+               split_flag1 = split_flag & EXT4_EXT_MAY_ZEROOUT;
                flags1 = flags | EXT4_GET_BLOCKS_PRE_IO;
                if (uninitialized)
                        split_flag1 |= EXT4_EXT_MARK_UNINIT1 |
                                       EXT4_EXT_MARK_UNINIT2;
+               if (split_flag & EXT4_EXT_DATA_VALID2)
+                       split_flag1 |= EXT4_EXT_DATA_VALID1;
                err = ext4_split_extent_at(handle, inode, path,
                                map->m_lblk + map->m_len, split_flag1, flags1);
                if (err)
@@ -3043,8 +3057,8 @@ static int ext4_split_extent(handle_t *handle,
                return PTR_ERR(path);
 
        if (map->m_lblk >= ee_block) {
-               split_flag1 = split_flag & EXT4_EXT_MAY_ZEROOUT ?
-                             EXT4_EXT_MAY_ZEROOUT : 0;
+               split_flag1 = split_flag & (EXT4_EXT_MAY_ZEROOUT |
+                                           EXT4_EXT_DATA_VALID2);
                if (uninitialized)
                        split_flag1 |= EXT4_EXT_MARK_UNINIT1;
                if (split_flag & EXT4_EXT_MARK_UNINIT2)
@@ -3323,26 +3337,47 @@ static int ext4_split_unwritten_extents(handle_t *handle,
 
        split_flag |= ee_block + ee_len <= eof_block ? EXT4_EXT_MAY_ZEROOUT : 0;
        split_flag |= EXT4_EXT_MARK_UNINIT2;
-
+       if (flags & EXT4_GET_BLOCKS_CONVERT)
+               split_flag |= EXT4_EXT_DATA_VALID2;
        flags |= EXT4_GET_BLOCKS_PRE_IO;
        return ext4_split_extent(handle, inode, path, map, split_flag, flags);
 }
 
 static int ext4_convert_unwritten_extents_endio(handle_t *handle,
-                                             struct inode *inode,
-                                             struct ext4_ext_path *path)
+                                               struct inode *inode,
+                                               struct ext4_map_blocks *map,
+                                               struct ext4_ext_path *path)
 {
        struct ext4_extent *ex;
+       ext4_lblk_t ee_block;
+       unsigned int ee_len;
        int depth;
        int err = 0;
 
        depth = ext_depth(inode);
        ex = path[depth].p_ext;
+       ee_block = le32_to_cpu(ex->ee_block);
+       ee_len = ext4_ext_get_actual_len(ex);
 
        ext_debug("ext4_convert_unwritten_extents_endio: inode %lu, logical"
                "block %llu, max_blocks %u\n", inode->i_ino,
-               (unsigned long long)le32_to_cpu(ex->ee_block),
-               ext4_ext_get_actual_len(ex));
+                 (unsigned long long)ee_block, ee_len);
+
+       /* If extent is larger than requested then split is required */
+       if (ee_block != map->m_lblk || ee_len > map->m_len) {
+               err = ext4_split_unwritten_extents(handle, inode, map, path,
+                                                  EXT4_GET_BLOCKS_CONVERT);
+               if (err < 0)
+                       goto out;
+               ext4_ext_drop_refs(path);
+               path = ext4_ext_find_extent(inode, map->m_lblk, path);
+               if (IS_ERR(path)) {
+                       err = PTR_ERR(path);
+                       goto out;
+               }
+               depth = ext_depth(inode);
+               ex = path[depth].p_ext;
+       }
 
        err = ext4_ext_get_access(handle, inode, path + depth);
        if (err)
@@ -3652,7 +3687,7 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode,
        }
        /* IO end_io complete, convert the filled extent to written */
        if ((flags & EXT4_GET_BLOCKS_CONVERT)) {
-               ret = ext4_convert_unwritten_extents_endio(handle, inode,
+               ret = ext4_convert_unwritten_extents_endio(handle, inode, map,
                                                        path);
                if (ret >= 0) {
                        ext4_update_inode_fsync_trans(handle, inode, 1);
@@ -4428,6 +4463,9 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
         */
        if (len <= EXT_UNINIT_MAX_LEN << blkbits)
                flags |= EXT4_GET_BLOCKS_NO_NORMALIZE;
+
+       /* Prevent race condition between unwritten */
+       ext4_flush_unwritten_io(inode);
 retry:
        while (ret >= 0 && ret < max_blocks) {
                map.m_lblk = map.m_lblk + ret;
index fa36372f3fdf827ed2557a3ecf5ccceab9e2cfe1..3a100e7a62a8343d31912a423330e11ea40e2e2a 100644 (file)
@@ -725,6 +725,10 @@ repeat_in_this_group:
                                   "inode=%lu", ino + 1);
                        continue;
                }
+               BUFFER_TRACE(inode_bitmap_bh, "get_write_access");
+               err = ext4_journal_get_write_access(handle, inode_bitmap_bh);
+               if (err)
+                       goto fail;
                ext4_lock_group(sb, group);
                ret2 = ext4_test_and_set_bit(ino, inode_bitmap_bh->b_data);
                ext4_unlock_group(sb, group);
@@ -738,6 +742,11 @@ repeat_in_this_group:
        goto out;
 
 got:
+       BUFFER_TRACE(inode_bitmap_bh, "call ext4_handle_dirty_metadata");
+       err = ext4_handle_dirty_metadata(handle, NULL, inode_bitmap_bh);
+       if (err)
+               goto fail;
+
        /* We may have to initialize the block bitmap if it isn't already */
        if (ext4_has_group_desc_csum(sb) &&
            gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
@@ -762,9 +771,7 @@ got:
                        ext4_free_group_clusters_set(sb, gdp,
                                ext4_free_clusters_after_init(sb, group, gdp));
                        ext4_block_bitmap_csum_set(sb, group, gdp,
-                                                  block_bitmap_bh,
-                                                  EXT4_BLOCKS_PER_GROUP(sb) /
-                                                  8);
+                                                  block_bitmap_bh);
                        ext4_group_desc_csum_set(sb, group, gdp);
                }
                ext4_unlock_group(sb, group);
@@ -773,11 +780,6 @@ got:
                        goto fail;
        }
 
-       BUFFER_TRACE(inode_bitmap_bh, "get_write_access");
-       err = ext4_journal_get_write_access(handle, inode_bitmap_bh);
-       if (err)
-               goto fail;
-
        BUFFER_TRACE(group_desc_bh, "get_write_access");
        err = ext4_journal_get_write_access(handle, group_desc_bh);
        if (err)
@@ -825,11 +827,6 @@ got:
        }
        ext4_unlock_group(sb, group);
 
-       BUFFER_TRACE(inode_bitmap_bh, "call ext4_handle_dirty_metadata");
-       err = ext4_handle_dirty_metadata(handle, NULL, inode_bitmap_bh);
-       if (err)
-               goto fail;
-
        BUFFER_TRACE(group_desc_bh, "call ext4_handle_dirty_metadata");
        err = ext4_handle_dirty_metadata(handle, NULL, group_desc_bh);
        if (err)
index f8b27bf80acaf45a3b9ce9aa872d2bed48b2f27d..526e55358606c83a548657449907cd94eed3c155 100644 (file)
@@ -2805,8 +2805,7 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
        }
        len = ext4_free_group_clusters(sb, gdp) - ac->ac_b_ex.fe_len;
        ext4_free_group_clusters_set(sb, gdp, len);
-       ext4_block_bitmap_csum_set(sb, ac->ac_b_ex.fe_group, gdp, bitmap_bh,
-                                  EXT4_BLOCKS_PER_GROUP(sb) / 8);
+       ext4_block_bitmap_csum_set(sb, ac->ac_b_ex.fe_group, gdp, bitmap_bh);
        ext4_group_desc_csum_set(sb, ac->ac_b_ex.fe_group, gdp);
 
        ext4_unlock_group(sb, ac->ac_b_ex.fe_group);
@@ -4666,8 +4665,7 @@ do_more:
 
        ret = ext4_free_group_clusters(sb, gdp) + count_clusters;
        ext4_free_group_clusters_set(sb, gdp, ret);
-       ext4_block_bitmap_csum_set(sb, block_group, gdp, bitmap_bh,
-                                  EXT4_BLOCKS_PER_GROUP(sb) / 8);
+       ext4_block_bitmap_csum_set(sb, block_group, gdp, bitmap_bh);
        ext4_group_desc_csum_set(sb, block_group, gdp);
        ext4_unlock_group(sb, block_group);
        percpu_counter_add(&sbi->s_freeclusters_counter, count_clusters);
@@ -4811,8 +4809,7 @@ int ext4_group_add_blocks(handle_t *handle, struct super_block *sb,
        mb_free_blocks(NULL, &e4b, bit, count);
        blk_free_count = blocks_freed + ext4_free_group_clusters(sb, desc);
        ext4_free_group_clusters_set(sb, desc, blk_free_count);
-       ext4_block_bitmap_csum_set(sb, block_group, desc, bitmap_bh,
-                                  EXT4_BLOCKS_PER_GROUP(sb) / 8);
+       ext4_block_bitmap_csum_set(sb, block_group, desc, bitmap_bh);
        ext4_group_desc_csum_set(sb, block_group, desc);
        ext4_unlock_group(sb, block_group);
        percpu_counter_add(&sbi->s_freeclusters_counter,
@@ -4993,8 +4990,9 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range)
        minlen = EXT4_NUM_B2C(EXT4_SB(sb),
                              range->minlen >> sb->s_blocksize_bits);
 
-       if (unlikely(minlen > EXT4_CLUSTERS_PER_GROUP(sb)) ||
-           unlikely(start >= max_blks))
+       if (minlen > EXT4_CLUSTERS_PER_GROUP(sb) ||
+           start >= max_blks ||
+           range->len < sb->s_blocksize)
                return -EINVAL;
        if (end >= max_blks)
                end = max_blks - 1;
index 7a75e1086961eedb674b8c2bf1bb84e657f4dfa2..47bf06a2765ddcbbd37eb84e693680278ea96fb9 100644 (file)
@@ -1212,8 +1212,7 @@ static int ext4_set_bitmap_checksums(struct super_block *sb,
        bh = ext4_get_bitmap(sb, group_data->block_bitmap);
        if (!bh)
                return -EIO;
-       ext4_block_bitmap_csum_set(sb, group, gdp, bh,
-                                  EXT4_BLOCKS_PER_GROUP(sb) / 8);
+       ext4_block_bitmap_csum_set(sb, group, gdp, bh);
        brelse(bh);
 
        return 0;
index 7265a0367476a87f0355b17c22b2488f65ec9a5f..80928f716850924cb34e7a591367cadf115fb95a 100644 (file)
@@ -143,9 +143,10 @@ int ext4_superblock_csum_verify(struct super_block *sb,
        return es->s_checksum == ext4_superblock_csum(sb, es);
 }
 
-void ext4_superblock_csum_set(struct super_block *sb,
-                             struct ext4_super_block *es)
+void ext4_superblock_csum_set(struct super_block *sb)
 {
+       struct ext4_super_block *es = EXT4_SB(sb)->s_es;
+
        if (!EXT4_HAS_RO_COMPAT_FEATURE(sb,
                EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
                return;
@@ -1963,7 +1964,7 @@ static int ext4_fill_flex_info(struct super_block *sb)
                sbi->s_log_groups_per_flex = 0;
                return 1;
        }
-       groups_per_flex = 1 << sbi->s_log_groups_per_flex;
+       groups_per_flex = 1U << sbi->s_log_groups_per_flex;
 
        err = ext4_alloc_flex_bg_array(sb, sbi->s_groups_count);
        if (err)
@@ -4381,7 +4382,7 @@ static int ext4_commit_super(struct super_block *sb, int sync)
                cpu_to_le32(percpu_counter_sum_positive(
                                &EXT4_SB(sb)->s_freeinodes_counter));
        BUFFER_TRACE(sbh, "marking dirty");
-       ext4_superblock_csum_set(sb, es);
+       ext4_superblock_csum_set(sb);
        mark_buffer_dirty(sbh);
        if (sync) {
                error = sync_dirty_buffer(sbh);
index d3b5fa80b71b76a973919a6b9cfa2ebb34096adf..7cb71b99260340fe7302d2a8c5dc4f84f8029aff 100644 (file)
--- a/fs/file.c
+++ b/fs/file.c
@@ -685,7 +685,6 @@ void do_close_on_exec(struct files_struct *files)
        struct fdtable *fdt;
 
        /* exec unshares first */
-       BUG_ON(atomic_read(&files->count) != 1);
        spin_lock(&files->file_lock);
        for (i = 0; ; i++) {
                unsigned long set;
@@ -900,7 +899,7 @@ int replace_fd(unsigned fd, struct file *file, unsigned flags)
                return __close_fd(files, fd);
 
        if (fd >= rlimit(RLIMIT_NOFILE))
-               return -EMFILE;
+               return -EBADF;
 
        spin_lock(&files->file_lock);
        err = expand_files(files, fd);
@@ -926,7 +925,7 @@ SYSCALL_DEFINE3(dup3, unsigned int, oldfd, unsigned int, newfd, int, flags)
                return -EINVAL;
 
        if (newfd >= rlimit(RLIMIT_NOFILE))
-               return -EMFILE;
+               return -EBADF;
 
        spin_lock(&files->file_lock);
        err = expand_files(files, newfd);
index 0def0504afc1816ae40b55de02c07aa68cc3a003..e056b4ce487777bbe794d64a11e4cbe2756205d3 100644 (file)
@@ -516,15 +516,13 @@ static int gfs2_mmap(struct file *file, struct vm_area_struct *vma)
                struct gfs2_holder i_gh;
                int error;
 
-               gfs2_holder_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh);
-               error = gfs2_glock_nq(&i_gh);
-               if (error == 0) {
-                       file_accessed(file);
-                       gfs2_glock_dq(&i_gh);
-               }
-               gfs2_holder_uninit(&i_gh);
+               error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY,
+                                          &i_gh);
                if (error)
                        return error;
+               /* grab lock to update inode */
+               gfs2_glock_dq_uninit(&i_gh);
+               file_accessed(file);
        }
        vma->vm_ops = &gfs2_vm_ops;
 
@@ -677,10 +675,8 @@ static ssize_t gfs2_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
        size_t writesize = iov_length(iov, nr_segs);
        struct dentry *dentry = file->f_dentry;
        struct gfs2_inode *ip = GFS2_I(dentry->d_inode);
-       struct gfs2_sbd *sdp;
        int ret;
 
-       sdp = GFS2_SB(file->f_mapping->host);
        ret = gfs2_rs_alloc(ip);
        if (ret)
                return ret;
index 8ff95a2d54ee7dae3de7a9ad6945b5a6c0f17b13..9ceccb1595a3d6f454dd0818eaea92cc8593114f 100644 (file)
@@ -393,12 +393,10 @@ static void buf_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
        struct gfs2_meta_header *mh;
        struct gfs2_trans *tr;
 
-       lock_buffer(bd->bd_bh);
-       gfs2_log_lock(sdp);
        tr = current->journal_info;
        tr->tr_touched = 1;
        if (!list_empty(&bd->bd_list))
-               goto out;
+               return;
        set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags);
        set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags);
        mh = (struct gfs2_meta_header *)bd->bd_bh->b_data;
@@ -414,9 +412,6 @@ static void buf_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
        sdp->sd_log_num_buf++;
        list_add(&bd->bd_list, &sdp->sd_log_le_buf);
        tr->tr_num_buf_new++;
-out:
-       gfs2_log_unlock(sdp);
-       unlock_buffer(bd->bd_bh);
 }
 
 static void gfs2_check_magic(struct buffer_head *bh)
@@ -621,7 +616,6 @@ static void revoke_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
 
 static void revoke_lo_before_commit(struct gfs2_sbd *sdp)
 {
-       struct gfs2_log_descriptor *ld;
        struct gfs2_meta_header *mh;
        unsigned int offset;
        struct list_head *head = &sdp->sd_log_le_revoke;
@@ -634,7 +628,6 @@ static void revoke_lo_before_commit(struct gfs2_sbd *sdp)
 
        length = gfs2_struct2blk(sdp, sdp->sd_log_num_revoke, sizeof(u64));
        page = gfs2_get_log_desc(sdp, GFS2_LOG_DESC_REVOKE, length, sdp->sd_log_num_revoke);
-       ld = page_address(page);
        offset = sizeof(struct gfs2_log_descriptor);
 
        list_for_each_entry(bd, head, bd_list) {
@@ -777,12 +770,10 @@ static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
        struct address_space *mapping = bd->bd_bh->b_page->mapping;
        struct gfs2_inode *ip = GFS2_I(mapping->host);
 
-       lock_buffer(bd->bd_bh);
-       gfs2_log_lock(sdp);
        if (tr)
                tr->tr_touched = 1;
        if (!list_empty(&bd->bd_list))
-               goto out;
+               return;
        set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags);
        set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags);
        if (gfs2_is_jdata(ip)) {
@@ -793,9 +784,6 @@ static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
        } else {
                list_add_tail(&bd->bd_list, &sdp->sd_log_le_ordered);
        }
-out:
-       gfs2_log_unlock(sdp);
-       unlock_buffer(bd->bd_bh);
 }
 
 /**
index 40c4b0d42fa8fea10b73102b4fd7d155ebf8daa0..c5af8e18f27af8a3b0c899ce1fe5404fede93831 100644 (file)
@@ -497,8 +497,11 @@ int gfs2_quota_hold(struct gfs2_inode *ip, u32 uid, u32 gid)
        struct gfs2_quota_data **qd;
        int error;
 
-       if (ip->i_res == NULL)
-               gfs2_rs_alloc(ip);
+       if (ip->i_res == NULL) {
+               error = gfs2_rs_alloc(ip);
+               if (error)
+                       return error;
+       }
 
        qd = ip->i_res->rs_qa_qd;
 
index 3cc402ce6fea6b3957e82646851e9646fa7cd26b..38fe18f2f055af2e5e842573a475e7b6836bb940 100644 (file)
@@ -553,7 +553,6 @@ void gfs2_free_clones(struct gfs2_rgrpd *rgd)
  */
 int gfs2_rs_alloc(struct gfs2_inode *ip)
 {
-       int error = 0;
        struct gfs2_blkreserv *res;
 
        if (ip->i_res)
@@ -561,7 +560,7 @@ int gfs2_rs_alloc(struct gfs2_inode *ip)
 
        res = kmem_cache_zalloc(gfs2_rsrv_cachep, GFP_NOFS);
        if (!res)
-               error = -ENOMEM;
+               return -ENOMEM;
 
        RB_CLEAR_NODE(&res->rs_node);
 
@@ -571,7 +570,7 @@ int gfs2_rs_alloc(struct gfs2_inode *ip)
        else
                ip->i_res = res;
        up_write(&ip->i_rw_mutex);
-       return error;
+       return 0;
 }
 
 static void dump_rs(struct seq_file *seq, const struct gfs2_blkreserv *rs)
@@ -1263,7 +1262,9 @@ int gfs2_fitrim(struct file *filp, void __user *argp)
        int ret = 0;
        u64 amt;
        u64 trimmed = 0;
+       u64 start, end, minlen;
        unsigned int x;
+       unsigned bs_shift = sdp->sd_sb.sb_bsize_shift;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
@@ -1271,19 +1272,25 @@ int gfs2_fitrim(struct file *filp, void __user *argp)
        if (!blk_queue_discard(q))
                return -EOPNOTSUPP;
 
-       if (argp == NULL) {
-               r.start = 0;
-               r.len = ULLONG_MAX;
-               r.minlen = 0;
-       } else if (copy_from_user(&r, argp, sizeof(r)))
+       if (copy_from_user(&r, argp, sizeof(r)))
                return -EFAULT;
 
        ret = gfs2_rindex_update(sdp);
        if (ret)
                return ret;
 
-       rgd = gfs2_blk2rgrpd(sdp, r.start, 0);
-       rgd_end = gfs2_blk2rgrpd(sdp, r.start + r.len, 0);
+       start = r.start >> bs_shift;
+       end = start + (r.len >> bs_shift);
+       minlen = max_t(u64, r.minlen,
+                      q->limits.discard_granularity) >> bs_shift;
+
+       rgd = gfs2_blk2rgrpd(sdp, start, 0);
+       rgd_end = gfs2_blk2rgrpd(sdp, end - 1, 0);
+
+       if (end <= start ||
+           minlen > sdp->sd_max_rg_data ||
+           start > rgd_end->rd_data0 + rgd_end->rd_data)
+               return -EINVAL;
 
        while (1) {
 
@@ -1295,7 +1302,9 @@ int gfs2_fitrim(struct file *filp, void __user *argp)
                        /* Trim each bitmap in the rgrp */
                        for (x = 0; x < rgd->rd_length; x++) {
                                struct gfs2_bitmap *bi = rgd->rd_bits + x;
-                               ret = gfs2_rgrp_send_discards(sdp, rgd->rd_data0, NULL, bi, r.minlen, &amt);
+                               ret = gfs2_rgrp_send_discards(sdp,
+                                               rgd->rd_data0, NULL, bi, minlen,
+                                               &amt);
                                if (ret) {
                                        gfs2_glock_dq_uninit(&gh);
                                        goto out;
@@ -1324,7 +1333,7 @@ int gfs2_fitrim(struct file *filp, void __user *argp)
 
 out:
        r.len = trimmed << 9;
-       if (argp && copy_to_user(argp, &r, sizeof(r)))
+       if (copy_to_user(argp, &r, sizeof(r)))
                return -EFAULT;
 
        return ret;
index bc737261f234872ad2df43411e6e74296b26b61c..d6488674d916273398b0bf8bd9cd3b2328c8a1fb 100644 (file)
@@ -810,7 +810,8 @@ static void gfs2_dirty_inode(struct inode *inode, int flags)
                        return;
                }
                need_unlock = 1;
-       }
+       } else if (WARN_ON_ONCE(ip->i_gl->gl_state != LM_ST_EXCLUSIVE))
+               return;
 
        if (current->journal_info == NULL) {
                ret = gfs2_trans_begin(sdp, RES_DINODE, 0);
index adbd27875ef957e5b54846d8494865d51ff156be..413627072f368168814f0df6ba340103c45f9e10 100644 (file)
@@ -155,14 +155,22 @@ void gfs2_trans_add_bh(struct gfs2_glock *gl, struct buffer_head *bh, int meta)
        struct gfs2_sbd *sdp = gl->gl_sbd;
        struct gfs2_bufdata *bd;
 
+       lock_buffer(bh);
+       gfs2_log_lock(sdp);
        bd = bh->b_private;
        if (bd)
                gfs2_assert(sdp, bd->bd_gl == gl);
        else {
+               gfs2_log_unlock(sdp);
+               unlock_buffer(bh);
                gfs2_attach_bufdata(gl, bh, meta);
                bd = bh->b_private;
+               lock_buffer(bh);
+               gfs2_log_lock(sdp);
        }
        lops_add(sdp, bd);
+       gfs2_log_unlock(sdp);
+       unlock_buffer(bh);
 }
 
 void gfs2_trans_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
index 60ef3fb707ffbfc6a77f1257efc82544cf0f9489..1506673c087e11ae820245baadc8ae74cb9f01b2 100644 (file)
@@ -138,33 +138,39 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
        struct page *pg;
        struct inode *inode = mapping->host;
        struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
+       struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
+       struct jffs2_raw_inode ri;
+       uint32_t alloc_len = 0;
        pgoff_t index = pos >> PAGE_CACHE_SHIFT;
        uint32_t pageofs = index << PAGE_CACHE_SHIFT;
        int ret = 0;
 
+       jffs2_dbg(1, "%s()\n", __func__);
+
+       if (pageofs > inode->i_size) {
+               ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len,
+                                         ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
+               if (ret)
+                       return ret;
+       }
+
+       mutex_lock(&f->sem);
        pg = grab_cache_page_write_begin(mapping, index, flags);
-       if (!pg)
+       if (!pg) {
+               if (alloc_len)
+                       jffs2_complete_reservation(c);
+               mutex_unlock(&f->sem);
                return -ENOMEM;
+       }
        *pagep = pg;
 
-       jffs2_dbg(1, "%s()\n", __func__);
-
-       if (pageofs > inode->i_size) {
+       if (alloc_len) {
                /* Make new hole frag from old EOF to new page */
-               struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
-               struct jffs2_raw_inode ri;
                struct jffs2_full_dnode *fn;
-               uint32_t alloc_len;
 
                jffs2_dbg(1, "Writing new hole frag 0x%x-0x%x between current EOF and new page\n",
                          (unsigned int)inode->i_size, pageofs);
 
-               ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len,
-                                         ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
-               if (ret)
-                       goto out_page;
-
-               mutex_lock(&f->sem);
                memset(&ri, 0, sizeof(ri));
 
                ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
@@ -191,7 +197,6 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
                if (IS_ERR(fn)) {
                        ret = PTR_ERR(fn);
                        jffs2_complete_reservation(c);
-                       mutex_unlock(&f->sem);
                        goto out_page;
                }
                ret = jffs2_add_full_dnode_to_inode(c, f, fn);
@@ -206,12 +211,10 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
                        jffs2_mark_node_obsolete(c, fn->raw);
                        jffs2_free_full_dnode(fn);
                        jffs2_complete_reservation(c);
-                       mutex_unlock(&f->sem);
                        goto out_page;
                }
                jffs2_complete_reservation(c);
                inode->i_size = pageofs;
-               mutex_unlock(&f->sem);
        }
 
        /*
@@ -220,18 +223,18 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
         * case of a short-copy.
         */
        if (!PageUptodate(pg)) {
-               mutex_lock(&f->sem);
                ret = jffs2_do_readpage_nolock(inode, pg);
-               mutex_unlock(&f->sem);
                if (ret)
                        goto out_page;
        }
+       mutex_unlock(&f->sem);
        jffs2_dbg(1, "end write_begin(). pg->flags %lx\n", pg->flags);
        return ret;
 
 out_page:
        unlock_page(pg);
        page_cache_release(pg);
+       mutex_unlock(&f->sem);
        return ret;
 }
 
index 9947563e41750223035daa3aeeaba785a9baf82c..dfcd5030455933bcfbc795c251bc3f0b6fa8e36a 100644 (file)
@@ -83,7 +83,7 @@ int jfs_ioc_trim(struct inode *ip, struct fstrim_range *range)
        struct bmap *bmp = JFS_SBI(ip->i_sb)->bmap;
        struct super_block *sb = ipbmap->i_sb;
        int agno, agno_end;
-       s64 start, end, minlen;
+       u64 start, end, minlen;
        u64 trimmed = 0;
 
        /**
@@ -93,15 +93,19 @@ int jfs_ioc_trim(struct inode *ip, struct fstrim_range *range)
         * minlen:      minimum extent length in Bytes
         */
        start = range->start >> sb->s_blocksize_bits;
-       if (start < 0)
-               start = 0;
        end = start + (range->len >> sb->s_blocksize_bits) - 1;
-       if (end >= bmp->db_mapsize)
-               end = bmp->db_mapsize - 1;
        minlen = range->minlen >> sb->s_blocksize_bits;
-       if (minlen <= 0)
+       if (minlen == 0)
                minlen = 1;
 
+       if (minlen > bmp->db_agsize ||
+           start >= bmp->db_mapsize ||
+           range->len < sb->s_blocksize)
+               return -EINVAL;
+
+       if (end >= bmp->db_mapsize)
+               end = bmp->db_mapsize - 1;
+
        /**
         * we trim all ag's within the range
         */
index e4fb3ba5a58a3d50eb11a0f9533ca58ae5150283..3d7e09bcc0e9efad7418803737e385c76d22a776 100644 (file)
@@ -85,29 +85,38 @@ static struct rpc_clnt *nsm_create(struct net *net)
        return rpc_create(&args);
 }
 
+static struct rpc_clnt *nsm_client_set(struct lockd_net *ln,
+               struct rpc_clnt *clnt)
+{
+       spin_lock(&ln->nsm_clnt_lock);
+       if (ln->nsm_users == 0) {
+               if (clnt == NULL)
+                       goto out;
+               ln->nsm_clnt = clnt;
+       }
+       clnt = ln->nsm_clnt;
+       ln->nsm_users++;
+out:
+       spin_unlock(&ln->nsm_clnt_lock);
+       return clnt;
+}
+
 static struct rpc_clnt *nsm_client_get(struct net *net)
 {
-       static DEFINE_MUTEX(nsm_create_mutex);
-       struct rpc_clnt *clnt;
+       struct rpc_clnt *clnt, *new;
        struct lockd_net *ln = net_generic(net, lockd_net_id);
 
-       spin_lock(&ln->nsm_clnt_lock);
-       if (ln->nsm_users) {
-               ln->nsm_users++;
-               clnt = ln->nsm_clnt;
-               spin_unlock(&ln->nsm_clnt_lock);
+       clnt = nsm_client_set(ln, NULL);
+       if (clnt != NULL)
                goto out;
-       }
-       spin_unlock(&ln->nsm_clnt_lock);
 
-       mutex_lock(&nsm_create_mutex);
-       clnt = nsm_create(net);
-       if (!IS_ERR(clnt)) {
-               ln->nsm_clnt = clnt;
-               smp_wmb();
-               ln->nsm_users = 1;
-       }
-       mutex_unlock(&nsm_create_mutex);
+       clnt = new = nsm_create(net);
+       if (IS_ERR(clnt))
+               goto out;
+
+       clnt = nsm_client_set(ln, new);
+       if (clnt != new)
+               rpc_shutdown_client(new);
 out:
        return clnt;
 }
@@ -115,18 +124,16 @@ out:
 static void nsm_client_put(struct net *net)
 {
        struct lockd_net *ln = net_generic(net, lockd_net_id);
-       struct rpc_clnt *clnt = ln->nsm_clnt;
-       int shutdown = 0;
+       struct rpc_clnt *clnt = NULL;
 
        spin_lock(&ln->nsm_clnt_lock);
-       if (ln->nsm_users) {
-               if (--ln->nsm_users)
-                       ln->nsm_clnt = NULL;
-               shutdown = !ln->nsm_users;
+       ln->nsm_users--;
+       if (ln->nsm_users == 0) {
+               clnt = ln->nsm_clnt;
+               ln->nsm_clnt = NULL;
        }
        spin_unlock(&ln->nsm_clnt_lock);
-
-       if (shutdown)
+       if (clnt != NULL)
                rpc_shutdown_client(clnt);
 }
 
index d1895f30815670de8abd8a6c921443035c21a364..937f9d50c84bdead7516057fead3d5a702ead4b9 100644 (file)
@@ -705,8 +705,8 @@ static inline void put_link(struct nameidata *nd, struct path *link, void *cooki
        path_put(link);
 }
 
-int sysctl_protected_symlinks __read_mostly = 1;
-int sysctl_protected_hardlinks __read_mostly = 1;
+int sysctl_protected_symlinks __read_mostly = 0;
+int sysctl_protected_hardlinks __read_mostly = 0;
 
 /**
  * may_follow_link - Check symlink following for unsafe situations
index 9a521fb3986955aab3f32e755bdef94e9c313aa2..5088b57b078a729d09ced36b3e491c01cba9cf4c 100644 (file)
@@ -241,7 +241,7 @@ static int nfs_callback_start_svc(int minorversion, struct rpc_xprt *xprt,
                svc_exit_thread(cb_info->rqst);
                cb_info->rqst = NULL;
                cb_info->task = NULL;
-               return PTR_ERR(cb_info->task);
+               return ret;
        }
        dprintk("nfs_callback_up: service started\n");
        return 0;
index 31c26c4dcc238110de0fa7374f1a2ab51a1541cd..ca4b11ec87a292e92e5d9496f8ac194d97a5bf9f 100644 (file)
@@ -217,7 +217,7 @@ static int nfs_dns_parse(struct cache_detail *cd, char *buf, int buflen)
 {
        char buf1[NFS_DNS_HOSTNAME_MAXLEN+1];
        struct nfs_dns_ent key, *item;
-       unsigned long ttl;
+       unsigned int ttl;
        ssize_t len;
        int ret = -EINVAL;
 
@@ -240,7 +240,8 @@ static int nfs_dns_parse(struct cache_detail *cd, char *buf, int buflen)
        key.namelen = len;
        memset(&key.h, 0, sizeof(key.h));
 
-       ttl = get_expiry(&buf);
+       if (get_uint(&buf, &ttl) < 0)
+               goto out;
        if (ttl == 0)
                goto out;
        key.h.expiry_time = ttl + seconds_since_boot();
index 5c7325c5c5e66b23beacd6fb7485fda5a640dcd9..6fa01aea24889cae08385e5bfe0aab16c742adc8 100644 (file)
@@ -685,7 +685,10 @@ static void __put_nfs_open_context(struct nfs_open_context *ctx, int is_sync)
        if (ctx->cred != NULL)
                put_rpccred(ctx->cred);
        dput(ctx->dentry);
-       nfs_sb_deactive(sb);
+       if (is_sync)
+               nfs_sb_deactive(sb);
+       else
+               nfs_sb_deactive_async(sb);
        kfree(ctx->mdsthreshold);
        kfree(ctx);
 }
index 59b133c5d652df5d2397b1e24e22f390fed459fc..05521cadac2e9821292c8c4eeefa037f5ef0a726 100644 (file)
@@ -351,10 +351,12 @@ extern int __init register_nfs_fs(void);
 extern void __exit unregister_nfs_fs(void);
 extern void nfs_sb_active(struct super_block *sb);
 extern void nfs_sb_deactive(struct super_block *sb);
+extern void nfs_sb_deactive_async(struct super_block *sb);
 
 /* namespace.c */
+#define NFS_PATH_CANONICAL 1
 extern char *nfs_path(char **p, struct dentry *dentry,
-                     char *buffer, ssize_t buflen);
+                     char *buffer, ssize_t buflen, unsigned flags);
 extern struct vfsmount *nfs_d_automount(struct path *path);
 struct vfsmount *nfs_submount(struct nfs_server *, struct dentry *,
                              struct nfs_fh *, struct nfs_fattr *);
@@ -498,7 +500,7 @@ static inline char *nfs_devname(struct dentry *dentry,
                                char *buffer, ssize_t buflen)
 {
        char *dummy;
-       return nfs_path(&dummy, dentry, buffer, buflen);
+       return nfs_path(&dummy, dentry, buffer, buflen, NFS_PATH_CANONICAL);
 }
 
 /*
index 8e65c7f1f87c526707959c0e691e36532406d1fa..015f71f8f62c271ebcd6c6ec3949aeff446ce420 100644 (file)
@@ -181,7 +181,7 @@ int nfs_mount(struct nfs_mount_request *info)
        else
                msg.rpc_proc = &mnt_clnt->cl_procinfo[MOUNTPROC_MNT];
 
-       status = rpc_call_sync(mnt_clnt, &msg, 0);
+       status = rpc_call_sync(mnt_clnt, &msg, RPC_TASK_SOFT|RPC_TASK_TIMEOUT);
        rpc_shutdown_client(mnt_clnt);
 
        if (status < 0)
index 655925373b9161c6a6c64ad157002d10cf8064e2..dd057bc6b65b28d3822229e0c0d5d0777b7955b9 100644 (file)
@@ -33,6 +33,7 @@ int nfs_mountpoint_expiry_timeout = 500 * HZ;
  * @dentry - pointer to dentry
  * @buffer - result buffer
  * @buflen - length of buffer
+ * @flags - options (see below)
  *
  * Helper function for constructing the server pathname
  * by arbitrary hashed dentry.
@@ -40,8 +41,14 @@ int nfs_mountpoint_expiry_timeout = 500 * HZ;
  * This is mainly for use in figuring out the path on the
  * server side when automounting on top of an existing partition
  * and in generating /proc/mounts and friends.
+ *
+ * Supported flags:
+ * NFS_PATH_CANONICAL: ensure there is exactly one slash after
+ *                    the original device (export) name
+ *                    (if unset, the original name is returned verbatim)
  */
-char *nfs_path(char **p, struct dentry *dentry, char *buffer, ssize_t buflen)
+char *nfs_path(char **p, struct dentry *dentry, char *buffer, ssize_t buflen,
+              unsigned flags)
 {
        char *end;
        int namelen;
@@ -74,7 +81,7 @@ rename_retry:
                rcu_read_unlock();
                goto rename_retry;
        }
-       if (*end != '/') {
+       if ((flags & NFS_PATH_CANONICAL) && *end != '/') {
                if (--buflen < 0) {
                        spin_unlock(&dentry->d_lock);
                        rcu_read_unlock();
@@ -91,9 +98,11 @@ rename_retry:
                return end;
        }
        namelen = strlen(base);
-       /* Strip off excess slashes in base string */
-       while (namelen > 0 && base[namelen - 1] == '/')
-               namelen--;
+       if (flags & NFS_PATH_CANONICAL) {
+               /* Strip off excess slashes in base string */
+               while (namelen > 0 && base[namelen - 1] == '/')
+                       namelen--;
+       }
        buflen -= namelen;
        if (buflen < 0) {
                spin_unlock(&dentry->d_lock);
index 52d8472120663de91855690fa0996cdf03e4a8a4..2e45fd9c02a38cc9d7b3ee0ee87150fa3a8e7ea8 100644 (file)
@@ -122,12 +122,21 @@ static void filelayout_reset_read(struct nfs_read_data *data)
        }
 }
 
+static void filelayout_fenceme(struct inode *inode, struct pnfs_layout_hdr *lo)
+{
+       if (!test_and_clear_bit(NFS_LAYOUT_RETURN, &lo->plh_flags))
+               return;
+       clear_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(inode)->flags);
+       pnfs_return_layout(inode);
+}
+
 static int filelayout_async_handle_error(struct rpc_task *task,
                                         struct nfs4_state *state,
                                         struct nfs_client *clp,
                                         struct pnfs_layout_segment *lseg)
 {
-       struct inode *inode = lseg->pls_layout->plh_inode;
+       struct pnfs_layout_hdr *lo = lseg->pls_layout;
+       struct inode *inode = lo->plh_inode;
        struct nfs_server *mds_server = NFS_SERVER(inode);
        struct nfs4_deviceid_node *devid = FILELAYOUT_DEVID_NODE(lseg);
        struct nfs_client *mds_client = mds_server->nfs_client;
@@ -204,10 +213,8 @@ static int filelayout_async_handle_error(struct rpc_task *task,
                dprintk("%s DS connection error %d\n", __func__,
                        task->tk_status);
                nfs4_mark_deviceid_unavailable(devid);
-               clear_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(inode)->flags);
-               _pnfs_return_layout(inode);
+               set_bit(NFS_LAYOUT_RETURN, &lo->plh_flags);
                rpc_wake_up(&tbl->slot_tbl_waitq);
-               nfs4_ds_disconnect(clp);
                /* fall through */
        default:
 reset:
@@ -331,7 +338,9 @@ static void filelayout_read_count_stats(struct rpc_task *task, void *data)
 static void filelayout_read_release(void *data)
 {
        struct nfs_read_data *rdata = data;
+       struct pnfs_layout_hdr *lo = rdata->header->lseg->pls_layout;
 
+       filelayout_fenceme(lo->plh_inode, lo);
        nfs_put_client(rdata->ds_clp);
        rdata->header->mds_ops->rpc_release(data);
 }
@@ -429,7 +438,9 @@ static void filelayout_write_count_stats(struct rpc_task *task, void *data)
 static void filelayout_write_release(void *data)
 {
        struct nfs_write_data *wdata = data;
+       struct pnfs_layout_hdr *lo = wdata->header->lseg->pls_layout;
 
+       filelayout_fenceme(lo->plh_inode, lo);
        nfs_put_client(wdata->ds_clp);
        wdata->header->mds_ops->rpc_release(data);
 }
@@ -739,7 +750,7 @@ filelayout_decode_layout(struct pnfs_layout_hdr *flo,
                goto out_err;
 
        if (fl->num_fh > 0) {
-               fl->fh_array = kzalloc(fl->num_fh * sizeof(struct nfs_fh *),
+               fl->fh_array = kcalloc(fl->num_fh, sizeof(fl->fh_array[0]),
                                       gfp_flags);
                if (!fl->fh_array)
                        goto out_err;
index dca47d78671026810c67b139763cd1b27548d42d..8c07241fe52b0ac86c7d1ef241923f20f0d56a1e 100644 (file)
@@ -149,6 +149,5 @@ extern void nfs4_fl_put_deviceid(struct nfs4_file_layout_dsaddr *dsaddr);
 extern void nfs4_fl_free_deviceid(struct nfs4_file_layout_dsaddr *dsaddr);
 struct nfs4_file_layout_dsaddr *
 filelayout_get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id, gfp_t gfp_flags);
-void nfs4_ds_disconnect(struct nfs_client *clp);
 
 #endif /* FS_NFS_NFS4FILELAYOUT_H */
index 3336d5eaf879adc07a2e95f64b512835935763a6..a8eaa9b7bb0f2c8fc704b8eb752c2ebc564b52bf 100644 (file)
@@ -148,28 +148,6 @@ _data_server_lookup_locked(const struct list_head *dsaddrs)
        return NULL;
 }
 
-/*
- * Lookup DS by nfs_client pointer. Zero data server client pointer
- */
-void nfs4_ds_disconnect(struct nfs_client *clp)
-{
-       struct nfs4_pnfs_ds *ds;
-       struct nfs_client *found = NULL;
-
-       dprintk("%s clp %p\n", __func__, clp);
-       spin_lock(&nfs4_ds_cache_lock);
-       list_for_each_entry(ds, &nfs4_data_server_cache, ds_node)
-               if (ds->ds_clp && ds->ds_clp == clp) {
-                       found = ds->ds_clp;
-                       ds->ds_clp = NULL;
-               }
-       spin_unlock(&nfs4_ds_cache_lock);
-       if (found) {
-               set_bit(NFS_CS_STOP_RENEW, &clp->cl_res_state);
-               nfs_put_client(clp);
-       }
-}
-
 /*
  * Create an rpc connection to the nfs4_pnfs_ds data server
  * Currently only supports IPv4 and IPv6 addresses
index 6a83780e0ce6b9a9888ce51dfd303ca454b54ea8..549462e5b9b0633239a1b2766ce17433446874dc 100644 (file)
@@ -5,6 +5,7 @@
 
 #include <linux/nfs_fs.h>
 #include "nfs4_fs.h"
+#include "internal.h"
 
 #define NFSDBG_FACILITY                NFSDBG_CLIENT
 
index 79fbb61ce202bcb90df2c8ad0f7f3ecf3bba7aac..1e09eb78543b2d50f9da025c733e52a99957ba64 100644 (file)
@@ -81,7 +81,8 @@ static char *nfs_path_component(const char *nfspath, const char *end)
 static char *nfs4_path(struct dentry *dentry, char *buffer, ssize_t buflen)
 {
        char *limit;
-       char *path = nfs_path(&limit, dentry, buffer, buflen);
+       char *path = nfs_path(&limit, dentry, buffer, buflen,
+                             NFS_PATH_CANONICAL);
        if (!IS_ERR(path)) {
                char *path_component = nfs_path_component(path, limit);
                if (path_component)
index 68b21d81b7acfa79bef010023195c1f45023c82b..5eec4429970c6e98af7a18732794c6fceaba4951 100644 (file)
@@ -339,8 +339,7 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc
                        dprintk("%s ERROR: %d Reset session\n", __func__,
                                errorcode);
                        nfs4_schedule_session_recovery(clp->cl_session, errorcode);
-                       exception->retry = 1;
-                       break;
+                       goto wait_on_recovery;
 #endif /* defined(CONFIG_NFS_V4_1) */
                case -NFS4ERR_FILE_OPEN:
                        if (exception->timeout > HZ) {
@@ -1572,9 +1571,11 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata)
        data->timestamp = jiffies;
        if (nfs4_setup_sequence(data->o_arg.server,
                                &data->o_arg.seq_args,
-                               &data->o_res.seq_res, task))
-               return;
-       rpc_call_start(task);
+                               &data->o_res.seq_res,
+                               task) != 0)
+               nfs_release_seqid(data->o_arg.seqid);
+       else
+               rpc_call_start(task);
        return;
 unlock_no_action:
        rcu_read_unlock();
@@ -1748,7 +1749,7 @@ static int nfs4_opendata_access(struct rpc_cred *cred,
 
        /* even though OPEN succeeded, access is denied. Close the file */
        nfs4_close_state(state, fmode);
-       return -NFS4ERR_ACCESS;
+       return -EACCES;
 }
 
 /*
@@ -2196,7 +2197,7 @@ static void nfs4_free_closedata(void *data)
        nfs4_put_open_state(calldata->state);
        nfs_free_seqid(calldata->arg.seqid);
        nfs4_put_state_owner(sp);
-       nfs_sb_deactive(sb);
+       nfs_sb_deactive_async(sb);
        kfree(calldata);
 }
 
@@ -2296,9 +2297,10 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
        if (nfs4_setup_sequence(NFS_SERVER(inode),
                                &calldata->arg.seq_args,
                                &calldata->res.seq_res,
-                               task))
-               goto out;
-       rpc_call_start(task);
+                               task) != 0)
+               nfs_release_seqid(calldata->arg.seqid);
+       else
+               rpc_call_start(task);
 out:
        dprintk("%s: done!\n", __func__);
 }
@@ -4529,6 +4531,7 @@ static void nfs4_locku_done(struct rpc_task *task, void *data)
                        if (nfs4_async_handle_error(task, calldata->server, NULL) == -EAGAIN)
                                rpc_restart_call_prepare(task);
        }
+       nfs_release_seqid(calldata->arg.seqid);
 }
 
 static void nfs4_locku_prepare(struct rpc_task *task, void *data)
@@ -4545,9 +4548,11 @@ static void nfs4_locku_prepare(struct rpc_task *task, void *data)
        calldata->timestamp = jiffies;
        if (nfs4_setup_sequence(calldata->server,
                                &calldata->arg.seq_args,
-                               &calldata->res.seq_res, task))
-               return;
-       rpc_call_start(task);
+                               &calldata->res.seq_res,
+                               task) != 0)
+               nfs_release_seqid(calldata->arg.seqid);
+       else
+               rpc_call_start(task);
 }
 
 static const struct rpc_call_ops nfs4_locku_ops = {
@@ -4692,7 +4697,7 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata)
        /* Do we need to do an open_to_lock_owner? */
        if (!(data->arg.lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED)) {
                if (nfs_wait_on_sequence(data->arg.open_seqid, task) != 0)
-                       return;
+                       goto out_release_lock_seqid;
                data->arg.open_stateid = &state->stateid;
                data->arg.new_lock_owner = 1;
                data->res.open_seqid = data->arg.open_seqid;
@@ -4701,10 +4706,15 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata)
        data->timestamp = jiffies;
        if (nfs4_setup_sequence(data->server,
                                &data->arg.seq_args,
-                               &data->res.seq_res, task))
+                               &data->res.seq_res,
+                               task) == 0) {
+               rpc_call_start(task);
                return;
-       rpc_call_start(task);
-       dprintk("%s: done!, ret = %d\n", __func__, data->rpc_status);
+       }
+       nfs_release_seqid(data->arg.open_seqid);
+out_release_lock_seqid:
+       nfs_release_seqid(data->arg.lock_seqid);
+       dprintk("%s: done!, ret = %d\n", __func__, task->tk_status);
 }
 
 static void nfs4_recover_lock_prepare(struct rpc_task *task, void *calldata)
@@ -5667,7 +5677,7 @@ static void nfs4_add_and_init_slots(struct nfs4_slot_table *tbl,
                tbl->slots = new;
                tbl->max_slots = max_slots;
        }
-       tbl->highest_used_slotid = -1;  /* no slot is currently used */
+       tbl->highest_used_slotid = NFS4_NO_SLOT;
        for (i = 0; i < tbl->max_slots; i++)
                tbl->slots[i].seq_nr = ivalue;
        spin_unlock(&tbl->slot_tbl_lock);
index be731e6b7b9cc1781a0a1776f49f7e5aa8219a89..c6f990656f8905ed4911b471f7334e1a1a40582e 100644 (file)
@@ -369,7 +369,7 @@ void objio_free_result(struct objlayout_io_res *oir)
        kfree(objios);
 }
 
-enum pnfs_osd_errno osd_pri_2_pnfs_err(enum osd_err_priority oep)
+static enum pnfs_osd_errno osd_pri_2_pnfs_err(enum osd_err_priority oep)
 {
        switch (oep) {
        case OSD_ERR_PRI_NO_ERROR:
@@ -574,7 +574,7 @@ static bool objio_pg_test(struct nfs_pageio_descriptor *pgio,
                        (unsigned long)pgio->pg_layout_private;
 }
 
-void objio_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *req)
+static void objio_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *req)
 {
        pnfs_generic_pg_init_read(pgio, req);
        if (unlikely(pgio->pg_lseg == NULL))
@@ -604,7 +604,7 @@ static bool aligned_on_raid_stripe(u64 offset, struct ore_layout *layout,
        return false;
 }
 
-void objio_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *req)
+static void objio_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *req)
 {
        unsigned long stripe_end = 0;
        u64 wb_size;
index fe624c91bd006ef11f839f61cab54f833286edfa..2878f97bd78d5cf5343b88cfcac9b5a48a1abe60 100644 (file)
@@ -925,8 +925,8 @@ pnfs_find_alloc_layout(struct inode *ino,
        if (likely(nfsi->layout == NULL)) {     /* Won the race? */
                nfsi->layout = new;
                return new;
-       }
-       pnfs_free_layout_hdr(new);
+       } else if (new != NULL)
+               pnfs_free_layout_hdr(new);
 out_existing:
        pnfs_get_layout_hdr(nfsi->layout);
        return nfsi->layout;
index 2d722dba111181377e6f599adae06a8d341abe09..dbf7bba52da04086c0c0a2bbb8b4283b309b8758 100644 (file)
@@ -62,6 +62,7 @@ enum {
        NFS_LAYOUT_RW_FAILED,           /* get rw layout failed stop trying */
        NFS_LAYOUT_BULK_RECALL,         /* bulk recall affecting layout */
        NFS_LAYOUT_ROC,                 /* some lseg had roc bit set */
+       NFS_LAYOUT_RETURN,              /* Return this layout ASAP */
 };
 
 enum layoutdriver_policy_flags {
index e831bce497663e809e48bb7cc278f5ad6a74ba7b..652d3f7176a98fcc4e70e6f5e3d812e4b3d90b83 100644 (file)
@@ -54,6 +54,7 @@
 #include <linux/parser.h>
 #include <linux/nsproxy.h>
 #include <linux/rcupdate.h>
+#include <linux/kthread.h>
 
 #include <asm/uaccess.h>
 
@@ -415,6 +416,54 @@ void nfs_sb_deactive(struct super_block *sb)
 }
 EXPORT_SYMBOL_GPL(nfs_sb_deactive);
 
+static int nfs_deactivate_super_async_work(void *ptr)
+{
+       struct super_block *sb = ptr;
+
+       deactivate_super(sb);
+       module_put_and_exit(0);
+       return 0;
+}
+
+/*
+ * same effect as deactivate_super, but will do final unmount in kthread
+ * context
+ */
+static void nfs_deactivate_super_async(struct super_block *sb)
+{
+       struct task_struct *task;
+       char buf[INET6_ADDRSTRLEN + 1];
+       struct nfs_server *server = NFS_SB(sb);
+       struct nfs_client *clp = server->nfs_client;
+
+       if (!atomic_add_unless(&sb->s_active, -1, 1)) {
+               rcu_read_lock();
+               snprintf(buf, sizeof(buf),
+                       rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR));
+               rcu_read_unlock();
+
+               __module_get(THIS_MODULE);
+               task = kthread_run(nfs_deactivate_super_async_work, sb,
+                               "%s-deactivate-super", buf);
+               if (IS_ERR(task)) {
+                       pr_err("%s: kthread_run: %ld\n",
+                               __func__, PTR_ERR(task));
+                       /* make synchronous call and hope for the best */
+                       deactivate_super(sb);
+                       module_put(THIS_MODULE);
+               }
+       }
+}
+
+void nfs_sb_deactive_async(struct super_block *sb)
+{
+       struct nfs_server *server = NFS_SB(sb);
+
+       if (atomic_dec_and_test(&server->active))
+               nfs_deactivate_super_async(sb);
+}
+EXPORT_SYMBOL_GPL(nfs_sb_deactive_async);
+
 /*
  * Deliver file system statistics to userspace
  */
@@ -771,7 +820,7 @@ int nfs_show_devname(struct seq_file *m, struct dentry *root)
        int err = 0;
        if (!page)
                return -ENOMEM;
-       devname = nfs_path(&dummy, root, page, PAGE_SIZE);
+       devname = nfs_path(&dummy, root, page, PAGE_SIZE, 0);
        if (IS_ERR(devname))
                err = PTR_ERR(devname);
        else
index 13cea637eff82288f2f5508023a592e60db3fa7a..3f79c77153b8fe827cd24310209301e0132b96ad 100644 (file)
@@ -95,7 +95,7 @@ static void nfs_async_unlink_release(void *calldata)
 
        nfs_dec_sillycount(data->dir);
        nfs_free_unlinkdata(data);
-       nfs_sb_deactive(sb);
+       nfs_sb_deactive_async(sb);
 }
 
 static void nfs_unlink_prepare(struct rpc_task *task, void *calldata)
index f35794b97e8e5cb5cc396af28206d69ca1202935..a50636025364214176fe7cec0cb80757ddc27171 100644 (file)
@@ -21,6 +21,7 @@ static bool should_merge(struct fsnotify_event *old, struct fsnotify_event *new)
                        if ((old->path.mnt == new->path.mnt) &&
                            (old->path.dentry == new->path.dentry))
                                return true;
+                       break;
                case (FSNOTIFY_EVENT_NONE):
                        return true;
                default:
index 721d692fa8d4a20dd5bf593d3f732d8b3f913261..6fcaeb8c902e4c3bc862c6c81db0a884068274b7 100644 (file)
@@ -258,7 +258,8 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group,
        if (ret)
                goto out_close_fd;
 
-       fd_install(fd, f);
+       if (fd != FAN_NOFD)
+               fd_install(fd, f);
        return fanotify_event_metadata.event_len;
 
 out_close_fd:
index 144a96732dd7d602df0d5f8a504e435cfdb07229..3c231adf845088ee51517c1f7fd0745284d88be2 100644 (file)
@@ -873,6 +873,113 @@ static const struct file_operations proc_environ_operations = {
        .release        = mem_release,
 };
 
+static ssize_t oom_adj_read(struct file *file, char __user *buf, size_t count,
+                           loff_t *ppos)
+{
+       struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode);
+       char buffer[PROC_NUMBUF];
+       int oom_adj = OOM_ADJUST_MIN;
+       size_t len;
+       unsigned long flags;
+
+       if (!task)
+               return -ESRCH;
+       if (lock_task_sighand(task, &flags)) {
+               if (task->signal->oom_score_adj == OOM_SCORE_ADJ_MAX)
+                       oom_adj = OOM_ADJUST_MAX;
+               else
+                       oom_adj = (task->signal->oom_score_adj * -OOM_DISABLE) /
+                                 OOM_SCORE_ADJ_MAX;
+               unlock_task_sighand(task, &flags);
+       }
+       put_task_struct(task);
+       len = snprintf(buffer, sizeof(buffer), "%d\n", oom_adj);
+       return simple_read_from_buffer(buf, count, ppos, buffer, len);
+}
+
+static ssize_t oom_adj_write(struct file *file, const char __user *buf,
+                            size_t count, loff_t *ppos)
+{
+       struct task_struct *task;
+       char buffer[PROC_NUMBUF];
+       int oom_adj;
+       unsigned long flags;
+       int err;
+
+       memset(buffer, 0, sizeof(buffer));
+       if (count > sizeof(buffer) - 1)
+               count = sizeof(buffer) - 1;
+       if (copy_from_user(buffer, buf, count)) {
+               err = -EFAULT;
+               goto out;
+       }
+
+       err = kstrtoint(strstrip(buffer), 0, &oom_adj);
+       if (err)
+               goto out;
+       if ((oom_adj < OOM_ADJUST_MIN || oom_adj > OOM_ADJUST_MAX) &&
+            oom_adj != OOM_DISABLE) {
+               err = -EINVAL;
+               goto out;
+       }
+
+       task = get_proc_task(file->f_path.dentry->d_inode);
+       if (!task) {
+               err = -ESRCH;
+               goto out;
+       }
+
+       task_lock(task);
+       if (!task->mm) {
+               err = -EINVAL;
+               goto err_task_lock;
+       }
+
+       if (!lock_task_sighand(task, &flags)) {
+               err = -ESRCH;
+               goto err_task_lock;
+       }
+
+       /*
+        * Scale /proc/pid/oom_score_adj appropriately ensuring that a maximum
+        * value is always attainable.
+        */
+       if (oom_adj == OOM_ADJUST_MAX)
+               oom_adj = OOM_SCORE_ADJ_MAX;
+       else
+               oom_adj = (oom_adj * OOM_SCORE_ADJ_MAX) / -OOM_DISABLE;
+
+       if (oom_adj < task->signal->oom_score_adj &&
+           !capable(CAP_SYS_RESOURCE)) {
+               err = -EACCES;
+               goto err_sighand;
+       }
+
+       /*
+        * /proc/pid/oom_adj is provided for legacy purposes, ask users to use
+        * /proc/pid/oom_score_adj instead.
+        */
+       printk_once(KERN_WARNING "%s (%d): /proc/%d/oom_adj is deprecated, please use /proc/%d/oom_score_adj instead.\n",
+                 current->comm, task_pid_nr(current), task_pid_nr(task),
+                 task_pid_nr(task));
+
+       task->signal->oom_score_adj = oom_adj;
+       trace_oom_score_adj_update(task);
+err_sighand:
+       unlock_task_sighand(task, &flags);
+err_task_lock:
+       task_unlock(task);
+       put_task_struct(task);
+out:
+       return err < 0 ? err : count;
+}
+
+static const struct file_operations proc_oom_adj_operations = {
+       .read           = oom_adj_read,
+       .write          = oom_adj_write,
+       .llseek         = generic_file_llseek,
+};
+
 static ssize_t oom_score_adj_read(struct file *file, char __user *buf,
                                        size_t count, loff_t *ppos)
 {
@@ -2598,6 +2705,7 @@ static const struct pid_entry tgid_base_stuff[] = {
        REG("cgroup",  S_IRUGO, proc_cgroup_operations),
 #endif
        INF("oom_score",  S_IRUGO, proc_oom_score),
+       REG("oom_adj",    S_IRUGO|S_IWUSR, proc_oom_adj_operations),
        REG("oom_score_adj", S_IRUGO|S_IWUSR, proc_oom_score_adj_operations),
 #ifdef CONFIG_AUDITSYSCALL
        REG("loginuid",   S_IWUSR|S_IRUGO, proc_loginuid_operations),
@@ -2964,6 +3072,7 @@ static const struct pid_entry tid_base_stuff[] = {
        REG("cgroup",  S_IRUGO, proc_cgroup_operations),
 #endif
        INF("oom_score", S_IRUGO, proc_oom_score),
+       REG("oom_adj",   S_IRUGO|S_IWUSR, proc_oom_adj_operations),
        REG("oom_score_adj", S_IRUGO|S_IWUSR, proc_oom_score_adj_operations),
 #ifdef CONFIG_AUDITSYSCALL
        REG("loginuid",  S_IWUSR|S_IRUGO, proc_loginuid_operations),
index 64c3b3172367abbd1c1464b9372f33ee4efa7acb..e296572c73ed651dd7d81cc33eb3dd1b64de5d0d 100644 (file)
@@ -45,10 +45,13 @@ static cputime64_t get_iowait_time(int cpu)
 
 static u64 get_idle_time(int cpu)
 {
-       u64 idle, idle_time = get_cpu_idle_time_us(cpu, NULL);
+       u64 idle, idle_time = -1ULL;
+
+       if (cpu_online(cpu))
+               idle_time = get_cpu_idle_time_us(cpu, NULL);
 
        if (idle_time == -1ULL)
-               /* !NO_HZ so we can rely on cpustat.idle */
+               /* !NO_HZ or cpu offline so we can rely on cpustat.idle */
                idle = kcpustat_cpu(cpu).cpustat[CPUTIME_IDLE];
        else
                idle = usecs_to_cputime64(idle_time);
@@ -58,10 +61,13 @@ static u64 get_idle_time(int cpu)
 
 static u64 get_iowait_time(int cpu)
 {
-       u64 iowait, iowait_time = get_cpu_iowait_time_us(cpu, NULL);
+       u64 iowait, iowait_time = -1ULL;
+
+       if (cpu_online(cpu))
+               iowait_time = get_cpu_iowait_time_us(cpu, NULL);
 
        if (iowait_time == -1ULL)
-               /* !NO_HZ so we can rely on cpustat.iowait */
+               /* !NO_HZ or cpu offline so we can rely on cpustat.iowait */
                iowait = kcpustat_cpu(cpu).cpustat[CPUTIME_IOWAIT];
        else
                iowait = usecs_to_cputime64(iowait_time);
index a40da07e93d68a88e670b5256a1c22c4badeb634..947fbe06c3b1f2ed0948b8fb050b43f2c48ff591 100644 (file)
@@ -161,6 +161,7 @@ static void pstore_console_write(struct console *con, const char *s, unsigned c)
 
        while (s < e) {
                unsigned long flags;
+               u64 id;
 
                if (c > psinfo->bufsize)
                        c = psinfo->bufsize;
@@ -172,7 +173,7 @@ static void pstore_console_write(struct console *con, const char *s, unsigned c)
                        spin_lock_irqsave(&psinfo->buf_lock, flags);
                }
                memcpy(psinfo->buf, s, c);
-               psinfo->write(PSTORE_TYPE_CONSOLE, 0, NULL, 0, c, psinfo);
+               psinfo->write(PSTORE_TYPE_CONSOLE, 0, &id, 0, c, psinfo);
                spin_unlock_irqrestore(&psinfo->buf_lock, flags);
                s += c;
                c = e - s;
index f27f01a98aa2c9573c6cc61fe093c821ce6e107c..d83736fbc26cb4679cf074ee33263f125f13afa7 100644 (file)
@@ -1782,8 +1782,9 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
 
        BUG_ON(!th->t_trans_id);
 
-       dquot_initialize(inode);
+       reiserfs_write_unlock(inode->i_sb);
        err = dquot_alloc_inode(inode);
+       reiserfs_write_lock(inode->i_sb);
        if (err)
                goto out_end_trans;
        if (!dir->i_nlink) {
@@ -1979,8 +1980,10 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
 
       out_end_trans:
        journal_end(th, th->t_super, th->t_blocks_allocated);
+       reiserfs_write_unlock(inode->i_sb);
        /* Drop can be outside and it needs more credits so it's better to have it outside */
        dquot_drop(inode);
+       reiserfs_write_lock(inode->i_sb);
        inode->i_flags |= S_NOQUOTA;
        make_bad_inode(inode);
 
@@ -3103,10 +3106,9 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
        /* must be turned off for recursive notify_change calls */
        ia_valid = attr->ia_valid &= ~(ATTR_KILL_SUID|ATTR_KILL_SGID);
 
-       depth = reiserfs_write_lock_once(inode->i_sb);
        if (is_quota_modification(inode, attr))
                dquot_initialize(inode);
-
+       depth = reiserfs_write_lock_once(inode->i_sb);
        if (attr->ia_valid & ATTR_SIZE) {
                /* version 2 items will be caught by the s_maxbytes check
                 ** done for us in vmtruncate
@@ -3170,7 +3172,9 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
                error = journal_begin(&th, inode->i_sb, jbegin_count);
                if (error)
                        goto out;
+               reiserfs_write_unlock_once(inode->i_sb, depth);
                error = dquot_transfer(inode, attr);
+               depth = reiserfs_write_lock_once(inode->i_sb);
                if (error) {
                        journal_end(&th, inode->i_sb, jbegin_count);
                        goto out;
index f8afa4b162b8f026da18b1cf2364e7d1cd6f5116..2f40a4c70a4d9667ca34e00ef2b31888255276c2 100644 (file)
@@ -1968,7 +1968,9 @@ int reiserfs_paste_into_item(struct reiserfs_transaction_handle *th, struct tree
                       key2type(&(key->on_disk_key)));
 #endif
 
+       reiserfs_write_unlock(inode->i_sb);
        retval = dquot_alloc_space_nodirty(inode, pasted_size);
+       reiserfs_write_lock(inode->i_sb);
        if (retval) {
                pathrelse(search_path);
                return retval;
@@ -2061,9 +2063,11 @@ int reiserfs_insert_item(struct reiserfs_transaction_handle *th,
                               "reiserquota insert_item(): allocating %u id=%u type=%c",
                               quota_bytes, inode->i_uid, head2type(ih));
 #endif
+               reiserfs_write_unlock(inode->i_sb);
                /* We can't dirty inode here. It would be immediately written but
                 * appropriate stat item isn't inserted yet... */
                retval = dquot_alloc_space_nodirty(inode, quota_bytes);
+               reiserfs_write_lock(inode->i_sb);
                if (retval) {
                        pathrelse(path);
                        return retval;
index 1078ae179993bb12f105d39fb1d847eb84c12414..418bdc3a57da4e11092477fa1b3cbf2e37f71422 100644 (file)
@@ -298,7 +298,9 @@ static int finish_unfinished(struct super_block *s)
                        retval = remove_save_link_only(s, &save_link_key, 0);
                        continue;
                }
+               reiserfs_write_unlock(s);
                dquot_initialize(inode);
+               reiserfs_write_lock(s);
 
                if (truncate && S_ISDIR(inode->i_mode)) {
                        /* We got a truncate request for a dir which is impossible.
@@ -1335,7 +1337,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
                                kfree(qf_names[i]);
 #endif
                err = -EINVAL;
-               goto out_err;
+               goto out_unlock;
        }
 #ifdef CONFIG_QUOTA
        handle_quota_files(s, qf_names, &qfmt);
@@ -1379,7 +1381,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
        if (blocks) {
                err = reiserfs_resize(s, blocks);
                if (err != 0)
-                       goto out_err;
+                       goto out_unlock;
        }
 
        if (*mount_flags & MS_RDONLY) {
@@ -1389,9 +1391,15 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
                        /* it is read-only already */
                        goto out_ok;
 
+               /*
+                * Drop write lock. Quota will retake it when needed and lock
+                * ordering requires calling dquot_suspend() without it.
+                */
+               reiserfs_write_unlock(s);
                err = dquot_suspend(s, -1);
                if (err < 0)
                        goto out_err;
+               reiserfs_write_lock(s);
 
                /* try to remount file system with read-only permissions */
                if (sb_umount_state(rs) == REISERFS_VALID_FS
@@ -1401,7 +1409,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
 
                err = journal_begin(&th, s, 10);
                if (err)
-                       goto out_err;
+                       goto out_unlock;
 
                /* Mounting a rw partition read-only. */
                reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1);
@@ -1416,7 +1424,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
 
                if (reiserfs_is_journal_aborted(journal)) {
                        err = journal->j_errno;
-                       goto out_err;
+                       goto out_unlock;
                }
 
                handle_data_mode(s, mount_options);
@@ -1425,7 +1433,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
                s->s_flags &= ~MS_RDONLY;       /* now it is safe to call journal_begin */
                err = journal_begin(&th, s, 10);
                if (err)
-                       goto out_err;
+                       goto out_unlock;
 
                /* Mount a partition which is read-only, read-write */
                reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1);
@@ -1442,10 +1450,16 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
        SB_JOURNAL(s)->j_must_wait = 1;
        err = journal_end(&th, s, 10);
        if (err)
-               goto out_err;
+               goto out_unlock;
 
        if (!(*mount_flags & MS_RDONLY)) {
+               /*
+                * Drop write lock. Quota will retake it when needed and lock
+                * ordering requires calling dquot_resume() without it.
+                */
+               reiserfs_write_unlock(s);
                dquot_resume(s, -1);
+               reiserfs_write_lock(s);
                finish_unfinished(s);
                reiserfs_xattr_init(s, *mount_flags);
        }
@@ -1455,9 +1469,10 @@ out_ok:
        reiserfs_write_unlock(s);
        return 0;
 
+out_unlock:
+       reiserfs_write_unlock(s);
 out_err:
        kfree(new_opts);
-       reiserfs_write_unlock(s);
        return err;
 }
 
@@ -2095,13 +2110,15 @@ static int reiserfs_write_dquot(struct dquot *dquot)
                          REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb));
        if (ret)
                goto out;
+       reiserfs_write_unlock(dquot->dq_sb);
        ret = dquot_commit(dquot);
+       reiserfs_write_lock(dquot->dq_sb);
        err =
            journal_end(&th, dquot->dq_sb,
                        REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb));
        if (!ret && err)
                ret = err;
-      out:
+out:
        reiserfs_write_unlock(dquot->dq_sb);
        return ret;
 }
@@ -2117,13 +2134,15 @@ static int reiserfs_acquire_dquot(struct dquot *dquot)
                          REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb));
        if (ret)
                goto out;
+       reiserfs_write_unlock(dquot->dq_sb);
        ret = dquot_acquire(dquot);
+       reiserfs_write_lock(dquot->dq_sb);
        err =
            journal_end(&th, dquot->dq_sb,
                        REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb));
        if (!ret && err)
                ret = err;
-      out:
+out:
        reiserfs_write_unlock(dquot->dq_sb);
        return ret;
 }
@@ -2137,19 +2156,21 @@ static int reiserfs_release_dquot(struct dquot *dquot)
        ret =
            journal_begin(&th, dquot->dq_sb,
                          REISERFS_QUOTA_DEL_BLOCKS(dquot->dq_sb));
+       reiserfs_write_unlock(dquot->dq_sb);
        if (ret) {
                /* Release dquot anyway to avoid endless cycle in dqput() */
                dquot_release(dquot);
                goto out;
        }
        ret = dquot_release(dquot);
+       reiserfs_write_lock(dquot->dq_sb);
        err =
            journal_end(&th, dquot->dq_sb,
                        REISERFS_QUOTA_DEL_BLOCKS(dquot->dq_sb));
        if (!ret && err)
                ret = err;
-      out:
        reiserfs_write_unlock(dquot->dq_sb);
+out:
        return ret;
 }
 
@@ -2174,11 +2195,13 @@ static int reiserfs_write_info(struct super_block *sb, int type)
        ret = journal_begin(&th, sb, 2);
        if (ret)
                goto out;
+       reiserfs_write_unlock(sb);
        ret = dquot_commit_info(sb, type);
+       reiserfs_write_lock(sb);
        err = journal_end(&th, sb, 2);
        if (!ret && err)
                ret = err;
-      out:
+out:
        reiserfs_write_unlock(sb);
        return ret;
 }
@@ -2203,8 +2226,11 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id,
        struct reiserfs_transaction_handle th;
        int opt = type == USRQUOTA ? REISERFS_USRQUOTA : REISERFS_GRPQUOTA;
 
-       if (!(REISERFS_SB(sb)->s_mount_opt & (1 << opt)))
-               return -EINVAL;
+       reiserfs_write_lock(sb);
+       if (!(REISERFS_SB(sb)->s_mount_opt & (1 << opt))) {
+               err = -EINVAL;
+               goto out;
+       }
 
        /* Quotafile not on the same filesystem? */
        if (path->dentry->d_sb != sb) {
@@ -2246,8 +2272,10 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id,
                if (err)
                        goto out;
        }
-       err = dquot_quota_on(sb, type, format_id, path);
+       reiserfs_write_unlock(sb);
+       return dquot_quota_on(sb, type, format_id, path);
 out:
+       reiserfs_write_unlock(sb);
        return err;
 }
 
@@ -2320,7 +2348,9 @@ static ssize_t reiserfs_quota_write(struct super_block *sb, int type,
                tocopy = sb->s_blocksize - offset < towrite ?
                    sb->s_blocksize - offset : towrite;
                tmp_bh.b_state = 0;
+               reiserfs_write_lock(sb);
                err = reiserfs_get_block(inode, blk, &tmp_bh, GET_BLOCK_CREATE);
+               reiserfs_write_unlock(sb);
                if (err)
                        goto out;
                if (offset || tocopy != sb->s_blocksize)
@@ -2336,10 +2366,12 @@ static ssize_t reiserfs_quota_write(struct super_block *sb, int type,
                flush_dcache_page(bh->b_page);
                set_buffer_uptodate(bh);
                unlock_buffer(bh);
+               reiserfs_write_lock(sb);
                reiserfs_prepare_for_journal(sb, bh, 1);
                journal_mark_dirty(current->journal_info, sb, bh);
                if (!journal_quota)
                        reiserfs_add_ordered_list(inode, bh);
+               reiserfs_write_unlock(sb);
                brelse(bh);
                offset = 0;
                towrite -= tocopy;
index 6b0bb00d4d2b6061add5a1f266371df257e5c4a9..2fbdff6be25ce3d546e17fa4e72783e9d3f03637 100644 (file)
@@ -485,20 +485,18 @@ int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
 /**
  *     sysfs_pathname - return full path to sysfs dirent
  *     @sd: sysfs_dirent whose path we want
- *     @path: caller allocated buffer
+ *     @path: caller allocated buffer of size PATH_MAX
  *
  *     Gives the name "/" to the sysfs_root entry; any path returned
  *     is relative to wherever sysfs is mounted.
- *
- *     XXX: does no error checking on @path size
  */
 static char *sysfs_pathname(struct sysfs_dirent *sd, char *path)
 {
        if (sd->s_parent) {
                sysfs_pathname(sd->s_parent, path);
-               strcat(path, "/");
+               strlcat(path, "/", PATH_MAX);
        }
-       strcat(path, sd->s_name);
+       strlcat(path, sd->s_name, PATH_MAX);
        return path;
 }
 
@@ -531,9 +529,11 @@ int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
                char *path = kzalloc(PATH_MAX, GFP_KERNEL);
                WARN(1, KERN_WARNING
                     "sysfs: cannot create duplicate filename '%s'\n",
-                    (path == NULL) ? sd->s_name :
-                    strcat(strcat(sysfs_pathname(acxt->parent_sd, path), "/"),
-                           sd->s_name));
+                    (path == NULL) ? sd->s_name
+                                   : (sysfs_pathname(acxt->parent_sd, path),
+                                      strlcat(path, "/", PATH_MAX),
+                                      strlcat(path, sd->s_name, PATH_MAX),
+                                      path));
                kfree(path);
        }
 
index 28ec13af28d91c360c89c68f7af0f1957e79477a..2dcf3d473fec1d406bf0fc2d14d73828ff81f662 100644 (file)
@@ -681,8 +681,16 @@ int ubifs_find_free_leb_for_idx(struct ubifs_info *c)
        if (!lprops) {
                lprops = ubifs_fast_find_freeable(c);
                if (!lprops) {
-                       ubifs_assert(c->freeable_cnt == 0);
-                       if (c->lst.empty_lebs - c->lst.taken_empty_lebs > 0) {
+                       /*
+                        * The first condition means the following: go scan the
+                        * LPT if there are uncategorized lprops, which means
+                        * there may be freeable LEBs there (UBIFS does not
+                        * store the information about freeable LEBs in the
+                        * master node).
+                        */
+                       if (c->in_a_category_cnt != c->main_lebs ||
+                           c->lst.empty_lebs - c->lst.taken_empty_lebs > 0) {
+                               ubifs_assert(c->freeable_cnt == 0);
                                lprops = scan_for_leb_for_idx(c);
                                if (IS_ERR(lprops)) {
                                        err = PTR_ERR(lprops);
index e5a2a35a46dcc1fc3fb9178704cec947458bda2e..46190a7c42a6c113bcffe4f170800b98a22eaf01 100644 (file)
@@ -300,8 +300,11 @@ void ubifs_add_to_cat(struct ubifs_info *c, struct ubifs_lprops *lprops,
        default:
                ubifs_assert(0);
        }
+
        lprops->flags &= ~LPROPS_CAT_MASK;
        lprops->flags |= cat;
+       c->in_a_category_cnt += 1;
+       ubifs_assert(c->in_a_category_cnt <= c->main_lebs);
 }
 
 /**
@@ -334,6 +337,9 @@ static void ubifs_remove_from_cat(struct ubifs_info *c,
        default:
                ubifs_assert(0);
        }
+
+       c->in_a_category_cnt -= 1;
+       ubifs_assert(c->in_a_category_cnt >= 0);
 }
 
 /**
index 5486346d0a3f9ec63ce10f9296ee0fbdec8732f1..d133c276fe05d526c647756c704ef37a8438612e 100644 (file)
@@ -1183,6 +1183,8 @@ struct ubifs_debug_info;
  * @freeable_list: list of freeable non-index LEBs (free + dirty == @leb_size)
  * @frdi_idx_list: list of freeable index LEBs (free + dirty == @leb_size)
  * @freeable_cnt: number of freeable LEBs in @freeable_list
+ * @in_a_category_cnt: count of lprops which are in a certain category, which
+ *                     basically meants that they were loaded from the flash
  *
  * @ltab_lnum: LEB number of LPT's own lprops table
  * @ltab_offs: offset of LPT's own lprops table
@@ -1412,6 +1414,7 @@ struct ubifs_info {
        struct list_head freeable_list;
        struct list_head frdi_idx_list;
        int freeable_cnt;
+       int in_a_category_cnt;
 
        int ltab_lnum;
        int ltab_offs;
index 4f33c32affe3d2eb4bec9c5ca8d71a33bbc5032a..335206a9c6985fde106d164543efee515bba1433 100644 (file)
@@ -1866,6 +1866,7 @@ xfs_alloc_fix_freelist(
        /*
         * Initialize the args structure.
         */
+       memset(&targs, 0, sizeof(targs));
        targs.tp = tp;
        targs.mp = mp;
        targs.agbp = agbp;
@@ -2207,7 +2208,7 @@ xfs_alloc_read_agf(
  * group or loop over the allocation groups to find the result.
  */
 int                            /* error */
-__xfs_alloc_vextent(
+xfs_alloc_vextent(
        xfs_alloc_arg_t *args)  /* allocation argument structure */
 {
        xfs_agblock_t   agsize; /* allocation group size */
@@ -2417,46 +2418,6 @@ error0:
        return error;
 }
 
-static void
-xfs_alloc_vextent_worker(
-       struct work_struct      *work)
-{
-       struct xfs_alloc_arg    *args = container_of(work,
-                                               struct xfs_alloc_arg, work);
-       unsigned long           pflags;
-
-       /* we are in a transaction context here */
-       current_set_flags_nested(&pflags, PF_FSTRANS);
-
-       args->result = __xfs_alloc_vextent(args);
-       complete(args->done);
-
-       current_restore_flags_nested(&pflags, PF_FSTRANS);
-}
-
-/*
- * Data allocation requests often come in with little stack to work on. Push
- * them off to a worker thread so there is lots of stack to use. Metadata
- * requests, OTOH, are generally from low stack usage paths, so avoid the
- * context switch overhead here.
- */
-int
-xfs_alloc_vextent(
-       struct xfs_alloc_arg    *args)
-{
-       DECLARE_COMPLETION_ONSTACK(done);
-
-       if (!args->userdata)
-               return __xfs_alloc_vextent(args);
-
-
-       args->done = &done;
-       INIT_WORK_ONSTACK(&args->work, xfs_alloc_vextent_worker);
-       queue_work(xfs_alloc_wq, &args->work);
-       wait_for_completion(&done);
-       return args->result;
-}
-
 /*
  * Free an extent.
  * Just break up the extent address and hand off to xfs_free_ag_extent
index 93be4a667ca1692648aec03195b5747bac4239f2..feacb061bab78bb3492ee0ff37eed5cc0fb95894 100644 (file)
@@ -120,9 +120,6 @@ typedef struct xfs_alloc_arg {
        char            isfl;           /* set if is freelist blocks - !acctg */
        char            userdata;       /* set if this is user data */
        xfs_fsblock_t   firstblock;     /* io first block allocated */
-       struct completion *done;
-       struct work_struct work;
-       int             result;
 } xfs_alloc_arg_t;
 
 /*
index f1647caace8fe66eeda2bd51cf5e679028d7b50e..f7876c6d616553d222295624a20f4c168c4c021d 100644 (file)
@@ -121,6 +121,8 @@ xfs_allocbt_free_block(
        xfs_extent_busy_insert(cur->bc_tp, be32_to_cpu(agf->agf_seqno), bno, 1,
                              XFS_EXTENT_BUSY_SKIP_DISCARD);
        xfs_trans_agbtree_delta(cur->bc_tp, -1);
+
+       xfs_trans_binval(cur->bc_tp, bp);
        return 0;
 }
 
index e562dd43f41fe762eb4d49c7814f1f002fe965c9..e57e2daa357c34fc9634871a1d41dd76569cf871 100644 (file)
@@ -481,11 +481,17 @@ static inline int bio_add_buffer(struct bio *bio, struct buffer_head *bh)
  *
  * The fix is two passes across the ioend list - one to start writeback on the
  * buffer_heads, and then submit them for I/O on the second pass.
+ *
+ * If @fail is non-zero, it means that we have a situation where some part of
+ * the submission process has failed after we have marked paged for writeback
+ * and unlocked them. In this situation, we need to fail the ioend chain rather
+ * than submit it to IO. This typically only happens on a filesystem shutdown.
  */
 STATIC void
 xfs_submit_ioend(
        struct writeback_control *wbc,
-       xfs_ioend_t             *ioend)
+       xfs_ioend_t             *ioend,
+       int                     fail)
 {
        xfs_ioend_t             *head = ioend;
        xfs_ioend_t             *next;
@@ -506,6 +512,18 @@ xfs_submit_ioend(
                next = ioend->io_list;
                bio = NULL;
 
+               /*
+                * If we are failing the IO now, just mark the ioend with an
+                * error and finish it. This will run IO completion immediately
+                * as there is only one reference to the ioend at this point in
+                * time.
+                */
+               if (fail) {
+                       ioend->io_error = -fail;
+                       xfs_finish_ioend(ioend);
+                       continue;
+               }
+
                for (bh = ioend->io_buffer_head; bh; bh = bh->b_private) {
 
                        if (!bio) {
@@ -1060,7 +1078,18 @@ xfs_vm_writepage(
 
        xfs_start_page_writeback(page, 1, count);
 
-       if (ioend && imap_valid) {
+       /* if there is no IO to be submitted for this page, we are done */
+       if (!ioend)
+               return 0;
+
+       ASSERT(iohead);
+
+       /*
+        * Any errors from this point onwards need tobe reported through the IO
+        * completion path as we have marked the initial page as under writeback
+        * and unlocked it.
+        */
+       if (imap_valid) {
                xfs_off_t               end_index;
 
                end_index = imap.br_startoff + imap.br_blockcount;
@@ -1079,20 +1108,15 @@ xfs_vm_writepage(
                                  wbc, end_index);
        }
 
-       if (iohead) {
-               /*
-                * Reserve log space if we might write beyond the on-disk
-                * inode size.
-                */
-               if (ioend->io_type != XFS_IO_UNWRITTEN &&
-                   xfs_ioend_is_append(ioend)) {
-                       err = xfs_setfilesize_trans_alloc(ioend);
-                       if (err)
-                               goto error;
-               }
 
-               xfs_submit_ioend(wbc, iohead);
-       }
+       /*
+        * Reserve log space if we might write beyond the on-disk inode size.
+        */
+       err = 0;
+       if (ioend->io_type != XFS_IO_UNWRITTEN && xfs_ioend_is_append(ioend))
+               err = xfs_setfilesize_trans_alloc(ioend);
+
+       xfs_submit_ioend(wbc, iohead, err);
 
        return 0;
 
index d330111ca738eef9ff86b5fd28723c0b63a9b379..70eec1829776309b3cba83e9a660aa6de5ad9693 100644 (file)
@@ -1291,6 +1291,7 @@ xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1,
        leaf2 = blk2->bp->b_addr;
        ASSERT(leaf1->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
        ASSERT(leaf2->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
+       ASSERT(leaf2->hdr.count == 0);
        args = state->args;
 
        trace_xfs_attr_leaf_rebalance(args);
@@ -1361,6 +1362,7 @@ xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1,
                 * I assert that since all callers pass in an empty
                 * second buffer, this code should never execute.
                 */
+               ASSERT(0);
 
                /*
                 * Figure the total bytes to be added to the destination leaf.
@@ -1422,10 +1424,24 @@ xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1,
                        args->index2 = 0;
                        args->blkno2 = blk2->blkno;
                } else {
+                       /*
+                        * On a double leaf split, the original attr location
+                        * is already stored in blkno2/index2, so don't
+                        * overwrite it overwise we corrupt the tree.
+                        */
                        blk2->index = blk1->index
                                    - be16_to_cpu(leaf1->hdr.count);
-                       args->index = args->index2 = blk2->index;
-                       args->blkno = args->blkno2 = blk2->blkno;
+                       args->index = blk2->index;
+                       args->blkno = blk2->blkno;
+                       if (!state->extravalid) {
+                               /*
+                                * set the new attr location to match the old
+                                * one and let the higher level split code
+                                * decide where in the leaf to place it.
+                                */
+                               args->index2 = blk2->index;
+                               args->blkno2 = blk2->blkno;
+                       }
                }
        } else {
                ASSERT(state->inleaf == 1);
index 848ffa77707b98bf272f61fc162f6e361504926e..83d0cf3df930794c307c4adcb33dceb8a5415f7e 100644 (file)
@@ -2437,6 +2437,7 @@ xfs_bmap_btalloc(
         * Normal allocation, done through xfs_alloc_vextent.
         */
        tryagain = isaligned = 0;
+       memset(&args, 0, sizeof(args));
        args.tp = ap->tp;
        args.mp = mp;
        args.fsbno = ap->blkno;
@@ -3082,6 +3083,7 @@ xfs_bmap_extents_to_btree(
         * Convert to a btree with two levels, one record in root.
         */
        XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_BTREE);
+       memset(&args, 0, sizeof(args));
        args.tp = tp;
        args.mp = mp;
        args.firstblock = *firstblock;
@@ -3237,6 +3239,7 @@ xfs_bmap_local_to_extents(
                xfs_buf_t       *bp;    /* buffer for extent block */
                xfs_bmbt_rec_host_t *ep;/* extent record pointer */
 
+               memset(&args, 0, sizeof(args));
                args.tp = tp;
                args.mp = ip->i_mount;
                args.firstblock = *firstblock;
@@ -4616,12 +4619,11 @@ xfs_bmapi_delay(
 
 
 STATIC int
-xfs_bmapi_allocate(
-       struct xfs_bmalloca     *bma,
-       int                     flags)
+__xfs_bmapi_allocate(
+       struct xfs_bmalloca     *bma)
 {
        struct xfs_mount        *mp = bma->ip->i_mount;
-       int                     whichfork = (flags & XFS_BMAPI_ATTRFORK) ?
+       int                     whichfork = (bma->flags & XFS_BMAPI_ATTRFORK) ?
                                                XFS_ATTR_FORK : XFS_DATA_FORK;
        struct xfs_ifork        *ifp = XFS_IFORK_PTR(bma->ip, whichfork);
        int                     tmp_logflags = 0;
@@ -4654,24 +4656,27 @@ xfs_bmapi_allocate(
         * Indicate if this is the first user data in the file, or just any
         * user data.
         */
-       if (!(flags & XFS_BMAPI_METADATA)) {
+       if (!(bma->flags & XFS_BMAPI_METADATA)) {
                bma->userdata = (bma->offset == 0) ?
                        XFS_ALLOC_INITIAL_USER_DATA : XFS_ALLOC_USERDATA;
        }
 
-       bma->minlen = (flags & XFS_BMAPI_CONTIG) ? bma->length : 1;
+       bma->minlen = (bma->flags & XFS_BMAPI_CONTIG) ? bma->length : 1;
 
        /*
         * Only want to do the alignment at the eof if it is userdata and
         * allocation length is larger than a stripe unit.
         */
        if (mp->m_dalign && bma->length >= mp->m_dalign &&
-           !(flags & XFS_BMAPI_METADATA) && whichfork == XFS_DATA_FORK) {
+           !(bma->flags & XFS_BMAPI_METADATA) && whichfork == XFS_DATA_FORK) {
                error = xfs_bmap_isaeof(bma, whichfork);
                if (error)
                        return error;
        }
 
+       if (bma->flags & XFS_BMAPI_STACK_SWITCH)
+               bma->stack_switch = 1;
+
        error = xfs_bmap_alloc(bma);
        if (error)
                return error;
@@ -4706,7 +4711,7 @@ xfs_bmapi_allocate(
         * A wasdelay extent has been initialized, so shouldn't be flagged
         * as unwritten.
         */
-       if (!bma->wasdel && (flags & XFS_BMAPI_PREALLOC) &&
+       if (!bma->wasdel && (bma->flags & XFS_BMAPI_PREALLOC) &&
            xfs_sb_version_hasextflgbit(&mp->m_sb))
                bma->got.br_state = XFS_EXT_UNWRITTEN;
 
@@ -4734,6 +4739,45 @@ xfs_bmapi_allocate(
        return 0;
 }
 
+static void
+xfs_bmapi_allocate_worker(
+       struct work_struct      *work)
+{
+       struct xfs_bmalloca     *args = container_of(work,
+                                               struct xfs_bmalloca, work);
+       unsigned long           pflags;
+
+       /* we are in a transaction context here */
+       current_set_flags_nested(&pflags, PF_FSTRANS);
+
+       args->result = __xfs_bmapi_allocate(args);
+       complete(args->done);
+
+       current_restore_flags_nested(&pflags, PF_FSTRANS);
+}
+
+/*
+ * Some allocation requests often come in with little stack to work on. Push
+ * them off to a worker thread so there is lots of stack to use. Otherwise just
+ * call directly to avoid the context switch overhead here.
+ */
+int
+xfs_bmapi_allocate(
+       struct xfs_bmalloca     *args)
+{
+       DECLARE_COMPLETION_ONSTACK(done);
+
+       if (!args->stack_switch)
+               return __xfs_bmapi_allocate(args);
+
+
+       args->done = &done;
+       INIT_WORK_ONSTACK(&args->work, xfs_bmapi_allocate_worker);
+       queue_work(xfs_alloc_wq, &args->work);
+       wait_for_completion(&done);
+       return args->result;
+}
+
 STATIC int
 xfs_bmapi_convert_unwritten(
        struct xfs_bmalloca     *bma,
@@ -4919,6 +4963,7 @@ xfs_bmapi_write(
                        bma.conv = !!(flags & XFS_BMAPI_CONVERT);
                        bma.wasdel = wasdelay;
                        bma.offset = bno;
+                       bma.flags = flags;
 
                        /*
                         * There's a 32/64 bit type mismatch between the
@@ -4934,7 +4979,7 @@ xfs_bmapi_write(
 
                        ASSERT(len > 0);
                        ASSERT(bma.length > 0);
-                       error = xfs_bmapi_allocate(&bma, flags);
+                       error = xfs_bmapi_allocate(&bma);
                        if (error)
                                goto error0;
                        if (bma.blkno == NULLFSBLOCK)
index 803b56d7ce16a97b7e5eb8075ba4e7853e4b8d30..5f469c3516ebc28bf836e86c974feb8c61373a4c 100644 (file)
@@ -77,6 +77,7 @@ typedef       struct xfs_bmap_free
  * from written to unwritten, otherwise convert from unwritten to written.
  */
 #define XFS_BMAPI_CONVERT      0x040
+#define XFS_BMAPI_STACK_SWITCH 0x080
 
 #define XFS_BMAPI_FLAGS \
        { XFS_BMAPI_ENTIRE,     "ENTIRE" }, \
@@ -85,7 +86,8 @@ typedef       struct xfs_bmap_free
        { XFS_BMAPI_PREALLOC,   "PREALLOC" }, \
        { XFS_BMAPI_IGSTATE,    "IGSTATE" }, \
        { XFS_BMAPI_CONTIG,     "CONTIG" }, \
-       { XFS_BMAPI_CONVERT,    "CONVERT" }
+       { XFS_BMAPI_CONVERT,    "CONVERT" }, \
+       { XFS_BMAPI_STACK_SWITCH, "STACK_SWITCH" }
 
 
 static inline int xfs_bmapi_aflag(int w)
@@ -133,6 +135,11 @@ typedef struct xfs_bmalloca {
        char                    userdata;/* set if is user data */
        char                    aeof;   /* allocated space at eof */
        char                    conv;   /* overwriting unwritten extents */
+       char                    stack_switch;
+       int                     flags;
+       struct completion       *done;
+       struct work_struct      work;
+       int                     result;
 } xfs_bmalloca_t;
 
 /*
index 933b7930b8636da970a627d571388b11e8dabde7..4b0b8dd1b7b0ea2bbc431ef523ec5412eb4fd584 100644 (file)
@@ -1197,9 +1197,14 @@ xfs_buf_bio_end_io(
 {
        xfs_buf_t               *bp = (xfs_buf_t *)bio->bi_private;
 
-       xfs_buf_ioerror(bp, -error);
+       /*
+        * don't overwrite existing errors - otherwise we can lose errors on
+        * buffers that require multiple bios to complete.
+        */
+       if (!bp->b_error)
+               xfs_buf_ioerror(bp, -error);
 
-       if (!error && xfs_buf_is_vmapped(bp) && (bp->b_flags & XBF_READ))
+       if (!bp->b_error && xfs_buf_is_vmapped(bp) && (bp->b_flags & XBF_READ))
                invalidate_kernel_vmap_range(bp->b_addr, xfs_buf_vmap_len(bp));
 
        _xfs_buf_ioend(bp, 1);
@@ -1279,6 +1284,11 @@ next_chunk:
                if (size)
                        goto next_chunk;
        } else {
+               /*
+                * This is guaranteed not to be the last io reference count
+                * because the caller (xfs_buf_iorequest) holds a count itself.
+                */
+               atomic_dec(&bp->b_io_remaining);
                xfs_buf_ioerror(bp, EIO);
                bio_put(bio);
        }
index a8d0ed911196120a80a26bb7232f79d3a5badee1..becf4a97efc65c95240e45c1b05b751919d51317 100644 (file)
@@ -526,7 +526,25 @@ xfs_buf_item_unpin(
                }
                xfs_buf_relse(bp);
        } else if (freed && remove) {
+               /*
+                * There are currently two references to the buffer - the active
+                * LRU reference and the buf log item. What we are about to do
+                * here - simulate a failed IO completion - requires 3
+                * references.
+                *
+                * The LRU reference is removed by the xfs_buf_stale() call. The
+                * buf item reference is removed by the xfs_buf_iodone()
+                * callback that is run by xfs_buf_do_callbacks() during ioend
+                * processing (via the bp->b_iodone callback), and then finally
+                * the ioend processing will drop the IO reference if the buffer
+                * is marked XBF_ASYNC.
+                *
+                * Hence we need to take an additional reference here so that IO
+                * completion processing doesn't free the buffer prematurely.
+                */
                xfs_buf_lock(bp);
+               xfs_buf_hold(bp);
+               bp->b_flags |= XBF_ASYNC;
                xfs_buf_ioerror(bp, EIO);
                XFS_BUF_UNDONE(bp);
                xfs_buf_stale(bp);
index c25b094efbf715186f39a9b7a44466eb0a910374..4beaede43277b15c8d5a28ffbaadb4b573d7a709 100644 (file)
@@ -399,9 +399,26 @@ xfs_growfs_data_private(
 
        /* update secondary superblocks. */
        for (agno = 1; agno < nagcount; agno++) {
-               error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp,
+               error = 0;
+               /*
+                * new secondary superblocks need to be zeroed, not read from
+                * disk as the contents of the new area we are growing into is
+                * completely unknown.
+                */
+               if (agno < oagcount) {
+                       error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp,
                                  XFS_AGB_TO_DADDR(mp, agno, XFS_SB_BLOCK(mp)),
                                  XFS_FSS_TO_BB(mp, 1), 0, &bp);
+               } else {
+                       bp = xfs_trans_get_buf(NULL, mp->m_ddev_targp,
+                                 XFS_AGB_TO_DADDR(mp, agno, XFS_SB_BLOCK(mp)),
+                                 XFS_FSS_TO_BB(mp, 1), 0);
+                       if (bp)
+                               xfs_buf_zero(bp, 0, BBTOB(bp->b_length));
+                       else
+                               error = ENOMEM;
+               }
+
                if (error) {
                        xfs_warn(mp,
                "error %d reading secondary superblock for ag %d",
@@ -423,7 +440,7 @@ xfs_growfs_data_private(
                        break; /* no point in continuing */
                }
        }
-       return 0;
+       return error;
 
  error0:
        xfs_trans_cancel(tp, XFS_TRANS_ABORT);
index 445bf1aef31c16d9e6bd17a8b91e78d7f1763c05..c5c4ef4f2bdbec16d9eb07ff0188921f677384ff 100644 (file)
@@ -250,6 +250,7 @@ xfs_ialloc_ag_alloc(
                                        /* boundary */
        struct xfs_perag *pag;
 
+       memset(&args, 0, sizeof(args));
        args.tp = tp;
        args.mp = tp->t_mountp;
 
index 2778258fcfa239e07dbc79edf6cb4750b7e13dd8..1938b41ee9f51bfef8f0ffad3e8b83e059ebcf41 100644 (file)
@@ -1509,7 +1509,8 @@ xfs_ifree_cluster(
                 * to mark all the active inodes on the buffer stale.
                 */
                bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, blkno,
-                                       mp->m_bsize * blks_per_cluster, 0);
+                                       mp->m_bsize * blks_per_cluster,
+                                       XBF_UNMAPPED);
 
                if (!bp)
                        return ENOMEM;
index 8305f2ac6773a8ee5efd1b0e24546e4194807187..c1df3c623de203f7d941ef0b706c76de270ada68 100644 (file)
@@ -70,7 +70,7 @@ xfs_find_handle(
        int                     hsize;
        xfs_handle_t            handle;
        struct inode            *inode;
-       struct fd               f;
+       struct fd               f = {0};
        struct path             path;
        int                     error;
        struct xfs_inode        *ip;
index 973dff6ad93526292871d3452d758e86b3f077ac..7f537663365b08436f1ad29015b77df33f691109 100644 (file)
@@ -584,7 +584,9 @@ xfs_iomap_write_allocate(
                         * pointer that the caller gave to us.
                         */
                        error = xfs_bmapi_write(tp, ip, map_start_fsb,
-                                               count_fsb, 0, &first_block, 1,
+                                               count_fsb,
+                                               XFS_BMAPI_STACK_SWITCH,
+                                               &first_block, 1,
                                                imap, &nimaps, &free_list);
                        if (error)
                                goto trans_cancel;
index 7f4f9370d0e7438df3820fab9b0026b37292623b..4dad756962d02e1b29c703b5b54ccee07d91fabf 100644 (file)
@@ -2387,14 +2387,27 @@ xlog_state_do_callback(
 
 
                                /*
-                                * update the last_sync_lsn before we drop the
+                                * Completion of a iclog IO does not imply that
+                                * a transaction has completed, as transactions
+                                * can be large enough to span many iclogs. We
+                                * cannot change the tail of the log half way
+                                * through a transaction as this may be the only
+                                * transaction in the log and moving th etail to
+                                * point to the middle of it will prevent
+                                * recovery from finding the start of the
+                                * transaction. Hence we should only update the
+                                * last_sync_lsn if this iclog contains
+                                * transaction completion callbacks on it.
+                                *
+                                * We have to do this before we drop the
                                 * icloglock to ensure we are the only one that
                                 * can update it.
                                 */
                                ASSERT(XFS_LSN_CMP(atomic64_read(&log->l_last_sync_lsn),
                                        be64_to_cpu(iclog->ic_header.h_lsn)) <= 0);
-                               atomic64_set(&log->l_last_sync_lsn,
-                                       be64_to_cpu(iclog->ic_header.h_lsn));
+                               if (iclog->ic_callback)
+                                       atomic64_set(&log->l_last_sync_lsn,
+                                               be64_to_cpu(iclog->ic_header.h_lsn));
 
                        } else
                                ioerrors++;
index 5da3ace352bffe6ca32d16ae76fc131291914a00..d308749fabf126a5b318c5d55f0e58e5589ef14f 100644 (file)
@@ -3541,7 +3541,7 @@ xlog_do_recovery_pass(
                                 *   - order is important.
                                 */
                                error = xlog_bread_offset(log, 0,
-                                               bblks - split_bblks, hbp,
+                                               bblks - split_bblks, dbp,
                                                offset + BBTOB(split_bblks));
                                if (error)
                                        goto bread_err2;
index c78bb997e2c60846a1f5e261664d96ee1656fe6d..c5c35e629426b506d2e7d00fe876f2e528a48f80 100644 (file)
        {0x1002, 0x6788, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x678A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6790, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x6791, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x6792, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6798, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6799, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x679A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x679B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x679E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x679F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6808, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6809, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6810, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x6811, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6816, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6817, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6818, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
index 4eb31752e2b77592e8a2fdbf3fde779d4851504d..deb0ae58b99bb3724bee4376b0a376b563c29cff 100644 (file)
@@ -5,10 +5,16 @@
 #include <linux/list.h>
 #include <linux/io.h>
 
+struct atmel_ssc_platform_data {
+       int                     use_dma;
+};
+
 struct ssc_device {
        struct list_head        list;
+       resource_size_t         phybase;
        void __iomem            *regs;
        struct platform_device  *pdev;
+       struct atmel_ssc_platform_data *pdata;
        struct clk              *clk;
        int                     user;
        int                     irq;
index c127315829208046fbd9327488dfc258cc1d0372..f9f5e9eeb9dd1f37f59cc95cf1da0cdbd91b7001 100644 (file)
@@ -335,8 +335,8 @@ const char *__clk_get_name(struct clk *clk);
 struct clk_hw *__clk_get_hw(struct clk *clk);
 u8 __clk_get_num_parents(struct clk *clk);
 struct clk *__clk_get_parent(struct clk *clk);
-inline int __clk_get_enable_count(struct clk *clk);
-inline int __clk_get_prepare_count(struct clk *clk);
+int __clk_get_enable_count(struct clk *clk);
+int __clk_get_prepare_count(struct clk *clk);
 unsigned long __clk_get_rate(struct clk *clk);
 unsigned long __clk_get_flags(struct clk *clk);
 int __clk_is_enabled(struct clk *clk);
index c18257b0fa7219df00fb5c991cfcfe7c8f5e135a..6dd4787a798a2a561afefbe39021bea303bd785c 100644 (file)
@@ -61,7 +61,7 @@ int __dynamic_netdev_dbg(struct _ddebug *descriptor,
                         const char *fmt, ...);
 
 #define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt)               \
-       static struct _ddebug __used __aligned(8)               \
+       static struct _ddebug  __aligned(8)                     \
        __attribute__((section("__verbose"))) name = {          \
                .modname = KBUILD_MODNAME,                      \
                .function = __func__,                           \
index 7443a560c9d059d106e7ce18dcf8813b18502c65..2c26c14cd7100d79ff046b9187409e2f430571eb 100644 (file)
@@ -68,7 +68,7 @@ enum extcon_cable_name {
        EXTCON_VIDEO_OUT,
        EXTCON_MECHANICAL,
 };
-extern const char *extcon_cable_name[];
+extern const char extcon_cable_name[][CABLE_NAME_MAX + 1];
 
 struct extcon_cable;
 
diff --git a/include/linux/hashtable.h b/include/linux/hashtable.h
new file mode 100644 (file)
index 0000000..227c624
--- /dev/null
@@ -0,0 +1,192 @@
+/*
+ * Statically sized hash table implementation
+ * (C) 2012  Sasha Levin <levinsasha928@gmail.com>
+ */
+
+#ifndef _LINUX_HASHTABLE_H
+#define _LINUX_HASHTABLE_H
+
+#include <linux/list.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/hash.h>
+#include <linux/rculist.h>
+
+#define DEFINE_HASHTABLE(name, bits)                                           \
+       struct hlist_head name[1 << (bits)] =                                   \
+                       { [0 ... ((1 << (bits)) - 1)] = HLIST_HEAD_INIT }
+
+#define DECLARE_HASHTABLE(name, bits)                                          \
+       struct hlist_head name[1 << (bits)]
+
+#define HASH_SIZE(name) (ARRAY_SIZE(name))
+#define HASH_BITS(name) ilog2(HASH_SIZE(name))
+
+/* Use hash_32 when possible to allow for fast 32bit hashing in 64bit kernels. */
+#define hash_min(val, bits)                                                    \
+       (sizeof(val) <= 4 ? hash_32(val, bits) : hash_long(val, bits))
+
+static inline void __hash_init(struct hlist_head *ht, unsigned int sz)
+{
+       unsigned int i;
+
+       for (i = 0; i < sz; i++)
+               INIT_HLIST_HEAD(&ht[i]);
+}
+
+/**
+ * hash_init - initialize a hash table
+ * @hashtable: hashtable to be initialized
+ *
+ * Calculates the size of the hashtable from the given parameter, otherwise
+ * same as hash_init_size.
+ *
+ * This has to be a macro since HASH_BITS() will not work on pointers since
+ * it calculates the size during preprocessing.
+ */
+#define hash_init(hashtable) __hash_init(hashtable, HASH_SIZE(hashtable))
+
+/**
+ * hash_add - add an object to a hashtable
+ * @hashtable: hashtable to add to
+ * @node: the &struct hlist_node of the object to be added
+ * @key: the key of the object to be added
+ */
+#define hash_add(hashtable, node, key)                                         \
+       hlist_add_head(node, &hashtable[hash_min(key, HASH_BITS(hashtable))])
+
+/**
+ * hash_add_rcu - add an object to a rcu enabled hashtable
+ * @hashtable: hashtable to add to
+ * @node: the &struct hlist_node of the object to be added
+ * @key: the key of the object to be added
+ */
+#define hash_add_rcu(hashtable, node, key)                                     \
+       hlist_add_head_rcu(node, &hashtable[hash_min(key, HASH_BITS(hashtable))])
+
+/**
+ * hash_hashed - check whether an object is in any hashtable
+ * @node: the &struct hlist_node of the object to be checked
+ */
+static inline bool hash_hashed(struct hlist_node *node)
+{
+       return !hlist_unhashed(node);
+}
+
+static inline bool __hash_empty(struct hlist_head *ht, unsigned int sz)
+{
+       unsigned int i;
+
+       for (i = 0; i < sz; i++)
+               if (!hlist_empty(&ht[i]))
+                       return false;
+
+       return true;
+}
+
+/**
+ * hash_empty - check whether a hashtable is empty
+ * @hashtable: hashtable to check
+ *
+ * This has to be a macro since HASH_BITS() will not work on pointers since
+ * it calculates the size during preprocessing.
+ */
+#define hash_empty(hashtable) __hash_empty(hashtable, HASH_SIZE(hashtable))
+
+/**
+ * hash_del - remove an object from a hashtable
+ * @node: &struct hlist_node of the object to remove
+ */
+static inline void hash_del(struct hlist_node *node)
+{
+       hlist_del_init(node);
+}
+
+/**
+ * hash_del_rcu - remove an object from a rcu enabled hashtable
+ * @node: &struct hlist_node of the object to remove
+ */
+static inline void hash_del_rcu(struct hlist_node *node)
+{
+       hlist_del_init_rcu(node);
+}
+
+/**
+ * hash_for_each - iterate over a hashtable
+ * @name: hashtable to iterate
+ * @bkt: integer to use as bucket loop cursor
+ * @node: the &struct list_head to use as a loop cursor for each entry
+ * @obj: the type * to use as a loop cursor for each entry
+ * @member: the name of the hlist_node within the struct
+ */
+#define hash_for_each(name, bkt, node, obj, member)                            \
+       for ((bkt) = 0, node = NULL; node == NULL && (bkt) < HASH_SIZE(name); (bkt)++)\
+               hlist_for_each_entry(obj, node, &name[bkt], member)
+
+/**
+ * hash_for_each_rcu - iterate over a rcu enabled hashtable
+ * @name: hashtable to iterate
+ * @bkt: integer to use as bucket loop cursor
+ * @node: the &struct list_head to use as a loop cursor for each entry
+ * @obj: the type * to use as a loop cursor for each entry
+ * @member: the name of the hlist_node within the struct
+ */
+#define hash_for_each_rcu(name, bkt, node, obj, member)                                \
+       for ((bkt) = 0, node = NULL; node == NULL && (bkt) < HASH_SIZE(name); (bkt)++)\
+               hlist_for_each_entry_rcu(obj, node, &name[bkt], member)
+
+/**
+ * hash_for_each_safe - iterate over a hashtable safe against removal of
+ * hash entry
+ * @name: hashtable to iterate
+ * @bkt: integer to use as bucket loop cursor
+ * @node: the &struct list_head to use as a loop cursor for each entry
+ * @tmp: a &struct used for temporary storage
+ * @obj: the type * to use as a loop cursor for each entry
+ * @member: the name of the hlist_node within the struct
+ */
+#define hash_for_each_safe(name, bkt, node, tmp, obj, member)                  \
+       for ((bkt) = 0, node = NULL; node == NULL && (bkt) < HASH_SIZE(name); (bkt)++)\
+               hlist_for_each_entry_safe(obj, node, tmp, &name[bkt], member)
+
+/**
+ * hash_for_each_possible - iterate over all possible objects hashing to the
+ * same bucket
+ * @name: hashtable to iterate
+ * @obj: the type * to use as a loop cursor for each entry
+ * @node: the &struct list_head to use as a loop cursor for each entry
+ * @member: the name of the hlist_node within the struct
+ * @key: the key of the objects to iterate over
+ */
+#define hash_for_each_possible(name, obj, node, member, key)                   \
+       hlist_for_each_entry(obj, node, &name[hash_min(key, HASH_BITS(name))], member)
+
+/**
+ * hash_for_each_possible_rcu - iterate over all possible objects hashing to the
+ * same bucket in an rcu enabled hashtable
+ * in a rcu enabled hashtable
+ * @name: hashtable to iterate
+ * @obj: the type * to use as a loop cursor for each entry
+ * @node: the &struct list_head to use as a loop cursor for each entry
+ * @member: the name of the hlist_node within the struct
+ * @key: the key of the objects to iterate over
+ */
+#define hash_for_each_possible_rcu(name, obj, node, member, key)               \
+       hlist_for_each_entry_rcu(obj, node, &name[hash_min(key, HASH_BITS(name))], member)
+
+/**
+ * hash_for_each_possible_safe - iterate over all possible objects hashing to the
+ * same bucket safe against removals
+ * @name: hashtable to iterate
+ * @obj: the type * to use as a loop cursor for each entry
+ * @node: the &struct list_head to use as a loop cursor for each entry
+ * @tmp: a &struct used for temporary storage
+ * @member: the name of the hlist_node within the struct
+ * @key: the key of the objects to iterate over
+ */
+#define hash_for_each_possible_safe(name, obj, node, tmp, member, key)         \
+       hlist_for_each_entry_safe(obj, node, tmp,                               \
+               &name[hash_min(key, HASH_BITS(name))], member)
+
+
+#endif
index df804ba73e0b2ae97d935ba2c3797cd36b1499de..92a0dc75bc74661541e5b5c15f4cdd095c922b38 100644 (file)
@@ -34,6 +34,7 @@ struct omap_i2c_bus_platform_data {
        u32             clkrate;
        u32             rev;
        u32             flags;
+       void            (*set_mpu_wkup_lat)(struct device *dev, long set);
 };
 
 #endif
index c0ae76ac4e0b87e905d358e846bd8459f0f10023..7806c24e5bc8173a004597a1dd266f8e14900de6 100644 (file)
@@ -618,4 +618,20 @@ static inline struct dentry *iio_get_debugfs_dentry(struct iio_dev *indio_dev)
 };
 #endif
 
+/**
+ * IIO_DEGREE_TO_RAD() - Convert degree to rad
+ * @deg: A value in degree
+ *
+ * Returns the given value converted from degree to rad
+ */
+#define IIO_DEGREE_TO_RAD(deg) (((deg) * 314159ULL + 9000000ULL) / 18000000ULL)
+
+/**
+ * IIO_G_TO_M_S_2() - Convert g to meter / second**2
+ * @g: A value in g
+ *
+ * Returns the given value converted from g to meter / second**2
+ */
+#define IIO_G_TO_M_S_2(g) ((g) * 980665ULL / 100000ULL)
+
 #endif /* _INDUSTRIAL_IO_H_ */
index 93bfc9f9815c7fa178ad70b555e7a2afb86b3f02..ecc554374e440a73df8aaf5b5787f86705e647b0 100644 (file)
  */
 #define KVM_MEMSLOT_INVALID    (1UL << 16)
 
-/*
- * If we support unaligned MMIO, at most one fragment will be split into two:
- */
-#ifdef KVM_UNALIGNED_MMIO
-#  define KVM_EXTRA_MMIO_FRAGMENTS 1
-#else
-#  define KVM_EXTRA_MMIO_FRAGMENTS 0
-#endif
-
-#define KVM_USER_MMIO_SIZE 8
-
-#define KVM_MAX_MMIO_FRAGMENTS \
-       (KVM_MMIO_SIZE / KVM_USER_MMIO_SIZE + KVM_EXTRA_MMIO_FRAGMENTS)
+/* Two fragments for cross MMIO pages. */
+#define KVM_MAX_MMIO_FRAGMENTS 2
 
 /*
  * For the normal pfn, the highest 12 bits should be zero,
index 569d67d4243ed99c4b896fac81442531b9d05cbc..d452ee191066456278080c92322e093986baa1fb 100644 (file)
@@ -57,6 +57,7 @@ int memblock_add(phys_addr_t base, phys_addr_t size);
 int memblock_remove(phys_addr_t base, phys_addr_t size);
 int memblock_free(phys_addr_t base, phys_addr_t size);
 int memblock_reserve(phys_addr_t base, phys_addr_t size);
+void memblock_trim_memory(phys_addr_t align);
 
 #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
 void __next_mem_pfn_range(int *idx, int nid, unsigned long *out_start_pfn,
index dd231ac0bb1fd8ac678d475404bc95ebaa104cec..a580363a7d29723e6656cbed8d9d94b4b1801bea 100644 (file)
@@ -78,6 +78,8 @@ enum arizona_type {
 
 #define ARIZONA_NUM_IRQ                   50
 
+struct snd_soc_dapm_context;
+
 struct arizona {
        struct regmap *regmap;
        struct device *dev;
@@ -98,6 +100,8 @@ struct arizona {
 
        struct mutex clk_lock;
        int clk32k_ref;
+
+       struct snd_soc_dapm_context *dapm;
 };
 
 int arizona_clk32k_enable(struct arizona *arizona);
index 7ab442905a57b209b10c042cf141ac2b2ba2275e..8b1d1daaae16c27e59d037f46899a1f6c631acc4 100644 (file)
@@ -62,6 +62,9 @@
 
 #define ARIZONA_MAX_OUTPUT 6
 
+#define ARIZONA_HAP_ACT_ERM 0
+#define ARIZONA_HAP_ACT_LRA 2
+
 #define ARIZONA_MAX_PDM_SPK 2
 
 struct regulator_init_data;
@@ -114,6 +117,9 @@ struct arizona_pdata {
 
        /** PDM speaker format */
        unsigned int spk_fmt[ARIZONA_MAX_PDM_SPK];
+
+       /** Haptic actuator type */
+       unsigned int hap_act;
 };
 
 #endif
index 1d28ae90384ed42e9c43a63a01d3a63c91a9c812..fe03b2d35d4f39178a9227a5eeeeeb7355e19192 100644 (file)
 #ifndef __LINUX_MFD_MAX77693_H
 #define __LINUX_MFD_MAX77693_H
 
+struct max77693_reg_data {
+       u8 addr;
+       u8 data;
+};
+
+struct max77693_muic_platform_data {
+       struct max77693_reg_data *init_data;
+       int num_init_data;
+};
+
 struct max77693_platform_data {
        int wakeup;
+
+       /* muic data */
+       struct max77693_muic_platform_data *muic_data;
 };
 #endif /* __LINUX_MFD_MAX77693_H */
index fa068040273893c27d71461e459e2eb268739396..bcaab4e6fe913ac6e3f2ef0a6c83ea24d8972867 100644 (file)
@@ -1684,9 +1684,5 @@ static inline unsigned int debug_guardpage_minorder(void) { return 0; }
 static inline bool page_is_guard(struct page *page) { return false; }
 #endif /* CONFIG_DEBUG_PAGEALLOC */
 
-extern void reset_zone_present_pages(void);
-extern void fixup_zone_present_pages(int nid, unsigned long start_pfn,
-                               unsigned long end_pfn);
-
 #endif /* __KERNEL__ */
 #endif /* _LINUX_MM_H */
index 7c6a1139d8faf9ad54af671c68cd81ea3dcebf2f..96531664a0612dc6bc006cad026cd795cf6a9aea 100644 (file)
@@ -137,7 +137,7 @@ struct dw_mci {
 
        dma_addr_t              sg_dma;
        void                    *sg_cpu;
-       struct dw_mci_dma_ops   *dma_ops;
+       const struct dw_mci_dma_ops     *dma_ops;
 #ifdef CONFIG_MMC_DW_IDMAC
        unsigned int            ring_size;
 #else
@@ -162,7 +162,7 @@ struct dw_mci {
        u16                     data_offset;
        struct device           *dev;
        struct dw_mci_board     *pdata;
-       struct dw_mci_drv_data  *drv_data;
+       const struct dw_mci_drv_data    *drv_data;
        void                    *priv;
        struct clk              *biu_clk;
        struct clk              *ciu_clk;
@@ -186,7 +186,7 @@ struct dw_mci {
 
        struct regulator        *vmmc;  /* Power regulator */
        unsigned long           irq_flags; /* IRQ flags */
-       unsigned int            irq;
+       int                     irq;
 };
 
 /* DMA ops for Internal/External DMAC interface */
index fa8529a859b8b7637a6b25e76e15ba7848cd9f79..1edcb4dad8c464a7910d126ebcf1b36bcefacb36 100644 (file)
@@ -91,6 +91,7 @@ struct sdhci_host {
        unsigned int quirks2;   /* More deviations from spec. */
 
 #define SDHCI_QUIRK2_HOST_OFF_CARD_ON                  (1<<0)
+#define SDHCI_QUIRK2_HOST_NO_CMD23                     (1<<1)
 
        int irq;                /* Device IRQ */
        void __iomem *ioaddr;   /* Mapped address */
index 50aaca81f63d6db3914b7858f0209fed036a5971..a23923ba8263b18dac16ec73971d19bed719d015 100644 (file)
@@ -752,7 +752,7 @@ extern int init_currently_empty_zone(struct zone *zone, unsigned long start_pfn,
                                     unsigned long size,
                                     enum memmap_context context);
 
-extern void lruvec_init(struct lruvec *lruvec, struct zone *zone);
+extern void lruvec_init(struct lruvec *lruvec);
 
 static inline struct zone *lruvec_zone(struct lruvec *lruvec)
 {
index a1984dd037da8c13d11a18336fdff331c356fc97..0506eb53519b635286be2b2c54b8a4c7e524a3d7 100644 (file)
@@ -28,11 +28,13 @@ static inline unsigned long pci_address_to_pio(phys_addr_t addr) { return -1; }
 #endif
 
 #else /* CONFIG_OF_ADDRESS */
+#ifndef of_address_to_resource
 static inline int of_address_to_resource(struct device_node *dev, int index,
                                         struct resource *r)
 {
        return -EINVAL;
 }
+#endif
 static inline struct device_node *of_find_matching_node_by_address(
                                        struct device_node *from,
                                        const struct of_device_id *matches,
@@ -40,10 +42,12 @@ static inline struct device_node *of_find_matching_node_by_address(
 {
        return NULL;
 }
+#ifndef of_iomap
 static inline void __iomem *of_iomap(struct device_node *device, int index)
 {
        return NULL;
 }
+#endif
 static inline const __be32 *of_get_address(struct device_node *dev, int index,
                                        u64 *size, unsigned int *flags)
 {
index cf80f7e5277f14dcce2931232a808e592344e7aa..250a4acddb2b8975a6c8278a3c5b1d803f36b585 100644 (file)
@@ -12,34 +12,27 @@ struct percpu_rw_semaphore {
        struct mutex mtx;
 };
 
+#define light_mb()     barrier()
+#define heavy_mb()     synchronize_sched()
+
 static inline void percpu_down_read(struct percpu_rw_semaphore *p)
 {
-       rcu_read_lock();
+       rcu_read_lock_sched();
        if (unlikely(p->locked)) {
-               rcu_read_unlock();
+               rcu_read_unlock_sched();
                mutex_lock(&p->mtx);
                this_cpu_inc(*p->counters);
                mutex_unlock(&p->mtx);
                return;
        }
        this_cpu_inc(*p->counters);
-       rcu_read_unlock();
+       rcu_read_unlock_sched();
+       light_mb(); /* A, between read of p->locked and read of data, paired with D */
 }
 
 static inline void percpu_up_read(struct percpu_rw_semaphore *p)
 {
-       /*
-        * On X86, write operation in this_cpu_dec serves as a memory unlock
-        * barrier (i.e. memory accesses may be moved before the write, but
-        * no memory accesses are moved past the write).
-        * On other architectures this may not be the case, so we need smp_mb()
-        * there.
-        */
-#if defined(CONFIG_X86) && (!defined(CONFIG_X86_PPRO_FENCE) && !defined(CONFIG_X86_OOSTORE))
-       barrier();
-#else
-       smp_mb();
-#endif
+       light_mb(); /* B, between read of the data and write to p->counter, paired with C */
        this_cpu_dec(*p->counters);
 }
 
@@ -58,14 +51,15 @@ static inline void percpu_down_write(struct percpu_rw_semaphore *p)
 {
        mutex_lock(&p->mtx);
        p->locked = true;
-       synchronize_rcu();
+       synchronize_sched(); /* make sure that all readers exit the rcu_read_lock_sched region */
        while (__percpu_count(p->counters))
                msleep(1);
-       smp_rmb(); /* paired with smp_mb() in percpu_sem_up_read() */
+       heavy_mb(); /* C, between read of p->counter and write to data, paired with B */
 }
 
 static inline void percpu_up_write(struct percpu_rw_semaphore *p)
 {
+       heavy_mb(); /* D, between write to data and write to p->locked, paired with A */
        p->locked = false;
        mutex_unlock(&p->mtx);
 }
index 2e902359aee596f128dee568d06e0e0ab3149dfe..6bfb2faa0b1937555f5ca8fa937c7007bf5b3bc4 100644 (file)
@@ -803,12 +803,16 @@ static inline void perf_event_task_tick(void)                             { }
 do {                                                                   \
        static struct notifier_block fn##_nb __cpuinitdata =            \
                { .notifier_call = fn, .priority = CPU_PRI_PERF };      \
+       unsigned long cpu = smp_processor_id();                         \
+       unsigned long flags;                                            \
        fn(&fn##_nb, (unsigned long)CPU_UP_PREPARE,                     \
-               (void *)(unsigned long)smp_processor_id());             \
+               (void *)(unsigned long)cpu);                            \
+       local_irq_save(flags);                                          \
        fn(&fn##_nb, (unsigned long)CPU_STARTING,                       \
-               (void *)(unsigned long)smp_processor_id());             \
+               (void *)(unsigned long)cpu);                            \
+       local_irq_restore(flags);                                       \
        fn(&fn##_nb, (unsigned long)CPU_ONLINE,                         \
-               (void *)(unsigned long)smp_processor_id());             \
+               (void *)(unsigned long)cpu);                            \
        register_cpu_notifier(&fn##_nb);                                \
 } while (0)
 
index d0c5825876f8a2d1d124a3d51fac880951a63b2f..8db5ae03b6e3f679c16988e492e8241f1567b2f5 100644 (file)
 #ifndef __DAVINCI_ASP_H
 #define __DAVINCI_ASP_H
 
+#include <linux/genalloc.h>
+
 struct snd_platform_data {
        u32 tx_dma_offset;
        u32 rx_dma_offset;
        int asp_chan_q; /* event queue number for ASP channel */
        int ram_chan_q; /* event queue number for RAM channel */
-       unsigned int codec_fmt;
        /*
         * Allowing this is more efficient and eliminates left and right swaps
         * caused by underruns, but will swap the left and right channels
@@ -30,6 +31,7 @@ struct snd_platform_data {
        unsigned enable_channel_combine:1;
        unsigned sram_size_playback;
        unsigned sram_size_capture;
+       struct gen_pool *sram_pool;
 
        /*
         * If McBSP peripheral gets the clock from an external pin,
diff --git a/include/linux/platform_data/omap_ocp2scp.h b/include/linux/platform_data/omap_ocp2scp.h
new file mode 100644 (file)
index 0000000..5c6c393
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * omap_ocp2scp.h -- ocp2scp header file
+ *
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.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.
+ *
+ * Author: Kishon Vijay Abraham I <kishon@ti.com>
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __DRIVERS_OMAP_OCP2SCP_H
+#define __DRIVERS_OMAP_OCP2SCP_H
+
+struct omap_ocp2scp_dev {
+       const char                      *drv_name;
+       struct resource                 *res;
+};
+
+struct omap_ocp2scp_platform_data {
+       int                             dev_cnt;
+       struct omap_ocp2scp_dev         **devices;
+};
+#endif /* __DRIVERS_OMAP_OCP2SCP_H */
index f2dc6d8fc680f7ae02596558ce4571a675fb3bce..38a99350832744231042de3d1d45f0fc11f3471f 100644 (file)
@@ -54,7 +54,8 @@ struct ptp_clock_request {
  * clock operations
  *
  * @adjfreq:  Adjusts the frequency of the hardware clock.
- *            parameter delta: Desired period change in parts per billion.
+ *            parameter delta: Desired frequency offset from nominal frequency
+ *            in parts per billion
  *
  * @adjtime:  Shifts the time of the hardware clock.
  *            parameter delta: Desired change in nanoseconds.
index 2415a64c5e51d937ba0fc7d20cf78011b1b77dd6..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,2 +0,0 @@
-header-y += md_p.h
-header-y += md_u.h
diff --git a/include/linux/raid/md_p.h b/include/linux/raid/md_p.h
deleted file mode 100644 (file)
index ee75353..0000000
+++ /dev/null
@@ -1,301 +0,0 @@
-/*
-   md_p.h : physical layout of Linux RAID devices
-          Copyright (C) 1996-98 Ingo Molnar, Gadi Oxman
-         
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-   
-   You should have received a copy of the GNU General Public License
-   (for example /usr/src/linux/COPYING); if not, write to the Free
-   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
-*/
-
-#ifndef _MD_P_H
-#define _MD_P_H
-
-#include <linux/types.h>
-
-/*
- * RAID superblock.
- *
- * The RAID superblock maintains some statistics on each RAID configuration.
- * Each real device in the RAID set contains it near the end of the device.
- * Some of the ideas are copied from the ext2fs implementation.
- *
- * We currently use 4096 bytes as follows:
- *
- *     word offset     function
- *
- *        0  -    31   Constant generic RAID device information.
- *        32  -    63   Generic state information.
- *       64  -   127   Personality specific information.
- *      128  -   511   12 32-words descriptors of the disks in the raid set.
- *      512  -   911   Reserved.
- *      912  -  1023   Disk specific descriptor.
- */
-
-/*
- * If x is the real device size in bytes, we return an apparent size of:
- *
- *     y = (x & ~(MD_RESERVED_BYTES - 1)) - MD_RESERVED_BYTES
- *
- * and place the 4kB superblock at offset y.
- */
-#define MD_RESERVED_BYTES              (64 * 1024)
-#define MD_RESERVED_SECTORS            (MD_RESERVED_BYTES / 512)
-
-#define MD_NEW_SIZE_SECTORS(x)         ((x & ~(MD_RESERVED_SECTORS - 1)) - MD_RESERVED_SECTORS)
-
-#define MD_SB_BYTES                    4096
-#define MD_SB_WORDS                    (MD_SB_BYTES / 4)
-#define MD_SB_SECTORS                  (MD_SB_BYTES / 512)
-
-/*
- * The following are counted in 32-bit words
- */
-#define        MD_SB_GENERIC_OFFSET            0
-#define MD_SB_PERSONALITY_OFFSET       64
-#define MD_SB_DISKS_OFFSET             128
-#define MD_SB_DESCRIPTOR_OFFSET                992
-
-#define MD_SB_GENERIC_CONSTANT_WORDS   32
-#define MD_SB_GENERIC_STATE_WORDS      32
-#define MD_SB_GENERIC_WORDS            (MD_SB_GENERIC_CONSTANT_WORDS + MD_SB_GENERIC_STATE_WORDS)
-#define MD_SB_PERSONALITY_WORDS                64
-#define MD_SB_DESCRIPTOR_WORDS         32
-#define MD_SB_DISKS                    27
-#define MD_SB_DISKS_WORDS              (MD_SB_DISKS*MD_SB_DESCRIPTOR_WORDS)
-#define MD_SB_RESERVED_WORDS           (1024 - MD_SB_GENERIC_WORDS - MD_SB_PERSONALITY_WORDS - MD_SB_DISKS_WORDS - MD_SB_DESCRIPTOR_WORDS)
-#define MD_SB_EQUAL_WORDS              (MD_SB_GENERIC_WORDS + MD_SB_PERSONALITY_WORDS + MD_SB_DISKS_WORDS)
-
-/*
- * Device "operational" state bits
- */
-#define MD_DISK_FAULTY         0 /* disk is faulty / operational */
-#define MD_DISK_ACTIVE         1 /* disk is running or spare disk */
-#define MD_DISK_SYNC           2 /* disk is in sync with the raid set */
-#define MD_DISK_REMOVED                3 /* disk is in sync with the raid set */
-
-#define        MD_DISK_WRITEMOSTLY     9 /* disk is "write-mostly" is RAID1 config.
-                                  * read requests will only be sent here in
-                                  * dire need
-                                  */
-
-typedef struct mdp_device_descriptor_s {
-       __u32 number;           /* 0 Device number in the entire set          */
-       __u32 major;            /* 1 Device major number                      */
-       __u32 minor;            /* 2 Device minor number                      */
-       __u32 raid_disk;        /* 3 The role of the device in the raid set   */
-       __u32 state;            /* 4 Operational state                        */
-       __u32 reserved[MD_SB_DESCRIPTOR_WORDS - 5];
-} mdp_disk_t;
-
-#define MD_SB_MAGIC            0xa92b4efc
-
-/*
- * Superblock state bits
- */
-#define MD_SB_CLEAN            0
-#define MD_SB_ERRORS           1
-
-#define        MD_SB_BITMAP_PRESENT    8 /* bitmap may be present nearby */
-
-/*
- * Notes:
- * - if an array is being reshaped (restriped) in order to change the
- *   the number of active devices in the array, 'raid_disks' will be
- *   the larger of the old and new numbers.  'delta_disks' will
- *   be the "new - old".  So if +ve, raid_disks is the new value, and
- *   "raid_disks-delta_disks" is the old.  If -ve, raid_disks is the
- *   old value and "raid_disks+delta_disks" is the new (smaller) value.
- */
-
-
-typedef struct mdp_superblock_s {
-       /*
-        * Constant generic information
-        */
-       __u32 md_magic;         /*  0 MD identifier                           */
-       __u32 major_version;    /*  1 major version to which the set conforms */
-       __u32 minor_version;    /*  2 minor version ...                       */
-       __u32 patch_version;    /*  3 patchlevel version ...                  */
-       __u32 gvalid_words;     /*  4 Number of used words in this section    */
-       __u32 set_uuid0;        /*  5 Raid set identifier                     */
-       __u32 ctime;            /*  6 Creation time                           */
-       __u32 level;            /*  7 Raid personality                        */
-       __u32 size;             /*  8 Apparent size of each individual disk   */
-       __u32 nr_disks;         /*  9 total disks in the raid set             */
-       __u32 raid_disks;       /* 10 disks in a fully functional raid set    */
-       __u32 md_minor;         /* 11 preferred MD minor device number        */
-       __u32 not_persistent;   /* 12 does it have a persistent superblock    */
-       __u32 set_uuid1;        /* 13 Raid set identifier #2                  */
-       __u32 set_uuid2;        /* 14 Raid set identifier #3                  */
-       __u32 set_uuid3;        /* 15 Raid set identifier #4                  */
-       __u32 gstate_creserved[MD_SB_GENERIC_CONSTANT_WORDS - 16];
-
-       /*
-        * Generic state information
-        */
-       __u32 utime;            /*  0 Superblock update time                  */
-       __u32 state;            /*  1 State bits (clean, ...)                 */
-       __u32 active_disks;     /*  2 Number of currently active disks        */
-       __u32 working_disks;    /*  3 Number of working disks                 */
-       __u32 failed_disks;     /*  4 Number of failed disks                  */
-       __u32 spare_disks;      /*  5 Number of spare disks                   */
-       __u32 sb_csum;          /*  6 checksum of the whole superblock        */
-#ifdef __BIG_ENDIAN
-       __u32 events_hi;        /*  7 high-order of superblock update count   */
-       __u32 events_lo;        /*  8 low-order of superblock update count    */
-       __u32 cp_events_hi;     /*  9 high-order of checkpoint update count   */
-       __u32 cp_events_lo;     /* 10 low-order of checkpoint update count    */
-#else
-       __u32 events_lo;        /*  7 low-order of superblock update count    */
-       __u32 events_hi;        /*  8 high-order of superblock update count   */
-       __u32 cp_events_lo;     /*  9 low-order of checkpoint update count    */
-       __u32 cp_events_hi;     /* 10 high-order of checkpoint update count   */
-#endif
-       __u32 recovery_cp;      /* 11 recovery checkpoint sector count        */
-       /* There are only valid for minor_version > 90 */
-       __u64 reshape_position; /* 12,13 next address in array-space for reshape */
-       __u32 new_level;        /* 14 new level we are reshaping to           */
-       __u32 delta_disks;      /* 15 change in number of raid_disks          */
-       __u32 new_layout;       /* 16 new layout                              */
-       __u32 new_chunk;        /* 17 new chunk size (bytes)                  */
-       __u32 gstate_sreserved[MD_SB_GENERIC_STATE_WORDS - 18];
-
-       /*
-        * Personality information
-        */
-       __u32 layout;           /*  0 the array's physical layout             */
-       __u32 chunk_size;       /*  1 chunk size in bytes                     */
-       __u32 root_pv;          /*  2 LV root PV */
-       __u32 root_block;       /*  3 LV root block */
-       __u32 pstate_reserved[MD_SB_PERSONALITY_WORDS - 4];
-
-       /*
-        * Disks information
-        */
-       mdp_disk_t disks[MD_SB_DISKS];
-
-       /*
-        * Reserved
-        */
-       __u32 reserved[MD_SB_RESERVED_WORDS];
-
-       /*
-        * Active descriptor
-        */
-       mdp_disk_t this_disk;
-
-} mdp_super_t;
-
-static inline __u64 md_event(mdp_super_t *sb) {
-       __u64 ev = sb->events_hi;
-       return (ev<<32)| sb->events_lo;
-}
-
-#define MD_SUPERBLOCK_1_TIME_SEC_MASK ((1ULL<<40) - 1)
-
-/*
- * The version-1 superblock :
- * All numeric fields are little-endian.
- *
- * total size: 256 bytes plus 2 per device.
- *  1K allows 384 devices.
- */
-struct mdp_superblock_1 {
-       /* constant array information - 128 bytes */
-       __le32  magic;          /* MD_SB_MAGIC: 0xa92b4efc - little endian */
-       __le32  major_version;  /* 1 */
-       __le32  feature_map;    /* bit 0 set if 'bitmap_offset' is meaningful */
-       __le32  pad0;           /* always set to 0 when writing */
-
-       __u8    set_uuid[16];   /* user-space generated. */
-       char    set_name[32];   /* set and interpreted by user-space */
-
-       __le64  ctime;          /* lo 40 bits are seconds, top 24 are microseconds or 0*/
-       __le32  level;          /* -4 (multipath), -1 (linear), 0,1,4,5 */
-       __le32  layout;         /* only for raid5 and raid10 currently */
-       __le64  size;           /* used size of component devices, in 512byte sectors */
-
-       __le32  chunksize;      /* in 512byte sectors */
-       __le32  raid_disks;
-       __le32  bitmap_offset;  /* sectors after start of superblock that bitmap starts
-                                * NOTE: signed, so bitmap can be before superblock
-                                * only meaningful of feature_map[0] is set.
-                                */
-
-       /* These are only valid with feature bit '4' */
-       __le32  new_level;      /* new level we are reshaping to                */
-       __le64  reshape_position;       /* next address in array-space for reshape */
-       __le32  delta_disks;    /* change in number of raid_disks               */
-       __le32  new_layout;     /* new layout                                   */
-       __le32  new_chunk;      /* new chunk size (512byte sectors)             */
-       __le32  new_offset;     /* signed number to add to data_offset in new
-                                * layout.  0 == no-change.  This can be
-                                * different on each device in the array.
-                                */
-
-       /* constant this-device information - 64 bytes */
-       __le64  data_offset;    /* sector start of data, often 0 */
-       __le64  data_size;      /* sectors in this device that can be used for data */
-       __le64  super_offset;   /* sector start of this superblock */
-       __le64  recovery_offset;/* sectors before this offset (from data_offset) have been recovered */
-       __le32  dev_number;     /* permanent identifier of this  device - not role in raid */
-       __le32  cnt_corrected_read; /* number of read errors that were corrected by re-writing */
-       __u8    device_uuid[16]; /* user-space setable, ignored by kernel */
-       __u8    devflags;       /* per-device flags.  Only one defined...*/
-#define        WriteMostly1    1       /* mask for writemostly flag in above */
-       /* Bad block log.  If there are any bad blocks the feature flag is set.
-        * If offset and size are non-zero, that space is reserved and available
-        */
-       __u8    bblog_shift;    /* shift from sectors to block size */
-       __le16  bblog_size;     /* number of sectors reserved for list */
-       __le32  bblog_offset;   /* sector offset from superblock to bblog,
-                                * signed - not unsigned */
-
-       /* array state information - 64 bytes */
-       __le64  utime;          /* 40 bits second, 24 bits microseconds */
-       __le64  events;         /* incremented when superblock updated */
-       __le64  resync_offset;  /* data before this offset (from data_offset) known to be in sync */
-       __le32  sb_csum;        /* checksum up to devs[max_dev] */
-       __le32  max_dev;        /* size of devs[] array to consider */
-       __u8    pad3[64-32];    /* set to 0 when writing */
-
-       /* device state information. Indexed by dev_number.
-        * 2 bytes per device
-        * Note there are no per-device state flags. State information is rolled
-        * into the 'roles' value.  If a device is spare or faulty, then it doesn't
-        * have a meaningful role.
-        */
-       __le16  dev_roles[0];   /* role in array, or 0xffff for a spare, or 0xfffe for faulty */
-};
-
-/* feature_map bits */
-#define MD_FEATURE_BITMAP_OFFSET       1
-#define        MD_FEATURE_RECOVERY_OFFSET      2 /* recovery_offset is present and
-                                          * must be honoured
-                                          */
-#define        MD_FEATURE_RESHAPE_ACTIVE       4
-#define        MD_FEATURE_BAD_BLOCKS           8 /* badblock list is not empty */
-#define        MD_FEATURE_REPLACEMENT          16 /* This device is replacing an
-                                           * active device with same 'role'.
-                                           * 'recovery_offset' is also set.
-                                           */
-#define        MD_FEATURE_RESHAPE_BACKWARDS    32 /* Reshape doesn't change number
-                                           * of devices, but is going
-                                           * backwards anyway.
-                                           */
-#define        MD_FEATURE_NEW_OFFSET           64 /* new_offset must be honoured */
-#define        MD_FEATURE_ALL                  (MD_FEATURE_BITMAP_OFFSET       \
-                                       |MD_FEATURE_RECOVERY_OFFSET     \
-                                       |MD_FEATURE_RESHAPE_ACTIVE      \
-                                       |MD_FEATURE_BAD_BLOCKS          \
-                                       |MD_FEATURE_REPLACEMENT         \
-                                       |MD_FEATURE_RESHAPE_BACKWARDS   \
-                                       |MD_FEATURE_NEW_OFFSET          \
-                                       )
-
-#endif 
index fb1abb3367e9520a7e68cf738709e7510abe80f0..358c04bfbe2ad31c691ac07e87b5988395f2c2f3 100644 (file)
    (for example /usr/src/linux/COPYING); if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
 */
-
 #ifndef _MD_U_H
 #define _MD_U_H
 
-/*
- * Different major versions are not compatible.
- * Different minor versions are only downward compatible.
- * Different patchlevel versions are downward and upward compatible.
- */
-#define MD_MAJOR_VERSION                0
-#define MD_MINOR_VERSION                90
-/*
- * MD_PATCHLEVEL_VERSION indicates kernel functionality.
- * >=1 means different superblock formats are selectable using SET_ARRAY_INFO
- *     and major_version/minor_version accordingly
- * >=2 means that Internal bitmaps are supported by setting MD_SB_BITMAP_PRESENT
- *     in the super status byte
- * >=3 means that bitmap superblock version 4 is supported, which uses
- *     little-ending representation rather than host-endian
- */
-#define MD_PATCHLEVEL_VERSION           3
-
-/* ioctls */
-
-/* status */
-#define RAID_VERSION           _IOR (MD_MAJOR, 0x10, mdu_version_t)
-#define GET_ARRAY_INFO         _IOR (MD_MAJOR, 0x11, mdu_array_info_t)
-#define GET_DISK_INFO          _IOR (MD_MAJOR, 0x12, mdu_disk_info_t)
-#define PRINT_RAID_DEBUG       _IO (MD_MAJOR, 0x13)
-#define RAID_AUTORUN           _IO (MD_MAJOR, 0x14)
-#define GET_BITMAP_FILE                _IOR (MD_MAJOR, 0x15, mdu_bitmap_file_t)
-
-/* configuration */
-#define CLEAR_ARRAY            _IO (MD_MAJOR, 0x20)
-#define ADD_NEW_DISK           _IOW (MD_MAJOR, 0x21, mdu_disk_info_t)
-#define HOT_REMOVE_DISK                _IO (MD_MAJOR, 0x22)
-#define SET_ARRAY_INFO         _IOW (MD_MAJOR, 0x23, mdu_array_info_t)
-#define SET_DISK_INFO          _IO (MD_MAJOR, 0x24)
-#define WRITE_RAID_INFO                _IO (MD_MAJOR, 0x25)
-#define UNPROTECT_ARRAY                _IO (MD_MAJOR, 0x26)
-#define PROTECT_ARRAY          _IO (MD_MAJOR, 0x27)
-#define HOT_ADD_DISK           _IO (MD_MAJOR, 0x28)
-#define SET_DISK_FAULTY                _IO (MD_MAJOR, 0x29)
-#define HOT_GENERATE_ERROR     _IO (MD_MAJOR, 0x2a)
-#define SET_BITMAP_FILE                _IOW (MD_MAJOR, 0x2b, int)
+#include <uapi/linux/raid/md_u.h>
 
-/* usage */
-#define RUN_ARRAY              _IOW (MD_MAJOR, 0x30, mdu_param_t)
-/*  0x31 was START_ARRAY  */
-#define STOP_ARRAY             _IO (MD_MAJOR, 0x32)
-#define STOP_ARRAY_RO          _IO (MD_MAJOR, 0x33)
-#define RESTART_ARRAY_RW       _IO (MD_MAJOR, 0x34)
-
-/* 63 partitions with the alternate major number (mdp) */
-#define MdpMinorShift 6
-#ifdef __KERNEL__
 extern int mdp_major;
-#endif
-
-typedef struct mdu_version_s {
-       int major;
-       int minor;
-       int patchlevel;
-} mdu_version_t;
-
-typedef struct mdu_array_info_s {
-       /*
-        * Generic constant information
-        */
-       int major_version;
-       int minor_version;
-       int patch_version;
-       int ctime;
-       int level;
-       int size;
-       int nr_disks;
-       int raid_disks;
-       int md_minor;
-       int not_persistent;
-
-       /*
-        * Generic state information
-        */
-       int utime;              /*  0 Superblock update time                  */
-       int state;              /*  1 State bits (clean, ...)                 */
-       int active_disks;       /*  2 Number of currently active disks        */
-       int working_disks;      /*  3 Number of working disks                 */
-       int failed_disks;       /*  4 Number of failed disks                  */
-       int spare_disks;        /*  5 Number of spare disks                   */
-
-       /*
-        * Personality information
-        */
-       int layout;             /*  0 the array's physical layout             */
-       int chunk_size; /*  1 chunk size in bytes                     */
-
-} mdu_array_info_t;
-
-/* non-obvious values for 'level' */
-#define        LEVEL_MULTIPATH         (-4)
-#define        LEVEL_LINEAR            (-1)
-#define        LEVEL_FAULTY            (-5)
-
-/* we need a value for 'no level specified' and 0
- * means 'raid0', so we need something else.  This is
- * for internal use only
- */
-#define        LEVEL_NONE              (-1000000)
-
-typedef struct mdu_disk_info_s {
-       /*
-        * configuration/status of one particular disk
-        */
-       int number;
-       int major;
-       int minor;
-       int raid_disk;
-       int state;
-
-} mdu_disk_info_t;
-
-typedef struct mdu_start_info_s {
-       /*
-        * configuration/status of one particular disk
-        */
-       int major;
-       int minor;
-       int raid_disk;
-       int state;
-
-} mdu_start_info_t;
-
-typedef struct mdu_bitmap_file_s
-{
-       char pathname[4096];
-} mdu_bitmap_file_t;
-
-typedef struct mdu_param_s
-{
-       int                     personality;    /* 1,2,3,4 */
-       int                     chunk_size;     /* in bytes */
-       int                     max_fault;      /* unused for now */
-} mdu_param_t;
-
 #endif 
-
index 214caa33433b9a58d4635d1f3214b099c515c8e5..2ac60c9cf6448fac839074e752d61f2de7b56c0a 100644 (file)
@@ -24,6 +24,7 @@
 #ifndef _LINUX_RBTREE_AUGMENTED_H
 #define _LINUX_RBTREE_AUGMENTED_H
 
+#include <linux/compiler.h>
 #include <linux/rbtree.h>
 
 /*
index 4187da51100631f157d508a1c121609a89204872..a3e7842786679567185ecdbc8835fd5936fb36f4 100644 (file)
@@ -275,9 +275,11 @@ struct rio_id_table {
  * struct rio_net - RIO network info
  * @node: Node in global list of RIO networks
  * @devices: List of devices in this network
+ * @switches: List of switches in this netowrk
  * @mports: List of master ports accessing this network
  * @hport: Default port for accessing this network
  * @id: RIO network ID
+ * @destid_table: destID allocation table
  */
 struct rio_net {
        struct list_head node;  /* node in list of networks */
index c64de9dd7631bb44232eeca7d8080c62521c5b1e..2f694f3846a9ad1a5d052e96d5f68cd9a152c313 100644 (file)
@@ -46,8 +46,9 @@ struct ads7846_platform_data {
        u16     debounce_rep;           /* additional consecutive good readings
                                         * required after the first two */
        int     gpio_pendown;           /* the GPIO used to decide the pendown
-                                        * state if get_pendown_state == NULL
-                                        */
+                                        * state if get_pendown_state == NULL */
+       int     gpio_pendown_debounce;  /* platform specific debounce time for
+                                        * the gpio_pendown */
        int     (*get_pendown_state)(void);
        int     (*filter_init)  (const struct ads7846_platform_data *pdata,
                                 void **filter_data);
index d9b0c84220c73897630f7cc7d35864c4eeeadb69..8f721e465e05b968ed1b5223c4b1e7eb61be78e2 100644 (file)
@@ -3,8 +3,6 @@
  *
  * Copyright (C) 2009-2010 Nokia Corporation
  *
- * Contact: Aaro Koskinen <aaro.koskinen@nokia.com>
- *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
index 8a7fc4be2d75f11d0ff774e727940dd16a2c64aa..60b7aac15e0e436b9b6451321d421a286fa9a40b 100644 (file)
@@ -191,7 +191,8 @@ struct tcp_sock {
        u8      do_early_retrans:1,/* Enable RFC5827 early-retransmit  */
                early_retrans_delayed:1, /* Delayed ER timer installed */
                syn_data:1,     /* SYN includes data */
-               syn_fastopen:1; /* SYN includes Fast Open option */
+               syn_fastopen:1, /* SYN includes Fast Open option */
+               syn_data_acked:1;/* data in SYN is acked by SYN-ACK */
 
 /* RTT measurement */
        u32     srtt;           /* smoothed round trip time << 3        */
index e6f0331e3d456281c87370e8c0275961c04ca084..24594571c5a3aa8a094d9cca3795420e32cb4ce0 100644 (file)
@@ -35,16 +35,6 @@ struct inode;
 # include <asm/uprobes.h>
 #endif
 
-/* flags that denote/change uprobes behaviour */
-
-/* Have a copy of original instruction */
-#define UPROBE_COPY_INSN       0x1
-
-/* Dont run handlers when first register/ last unregister in progress*/
-#define UPROBE_RUN_HANDLER     0x2
-/* Can skip singlestep */
-#define UPROBE_SKIP_SSTEP      0x4
-
 struct uprobe_consumer {
        int (*handler)(struct uprobe_consumer *self, struct pt_regs *regs);
        /*
@@ -59,7 +49,6 @@ struct uprobe_consumer {
 #ifdef CONFIG_UPROBES
 enum uprobe_task_state {
        UTASK_RUNNING,
-       UTASK_BP_HIT,
        UTASK_SSTEP,
        UTASK_SSTEP_ACK,
        UTASK_SSTEP_TRAPPED,
index 1b49890822449df661d576219181b10c64d57a6c..7d5b6000378bbbdaf8a4fe7316ab93786429cf3a 100644 (file)
@@ -1218,6 +1218,7 @@ struct cfg80211_deauth_request {
        const u8 *ie;
        size_t ie_len;
        u16 reason_code;
+       bool local_state_change;
 };
 
 /**
@@ -2650,6 +2651,15 @@ unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb);
  */
 unsigned int __attribute_const__ ieee80211_hdrlen(__le16 fc);
 
+/**
+ * ieee80211_get_mesh_hdrlen - get mesh extension header length
+ * @meshhdr: the mesh extension header, only the flags field
+ *     (first byte) will be accessed
+ * Returns the length of the extension header, which is always at
+ * least 6 bytes and at most 18 if address 5 and 6 are present.
+ */
+unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr);
+
 /**
  * DOC: Data path helpers
  *
index 6f0ba01afe7315d443a0aad152a9df2d5a22abf6..63445ede48bb7fd04b175c111935fb77464568b6 100644 (file)
@@ -1351,7 +1351,7 @@ struct xfrm6_tunnel {
 };
 
 extern void xfrm_init(void);
-extern void xfrm4_init(int rt_hash_size);
+extern void xfrm4_init(void);
 extern int xfrm_state_init(struct net *net);
 extern void xfrm_state_fini(struct net *net);
 extern void xfrm4_state_init(void);
index 88fae8d2015471885972da8407d0077106b527cc..55367b04dc9445e142369e98d2134d459eb5ef83 100644 (file)
@@ -135,6 +135,8 @@ struct scsi_device {
                                     * because we did a bus reset. */
        unsigned use_10_for_rw:1; /* first try 10-byte read / write */
        unsigned use_10_for_ms:1; /* first try 10-byte mode sense/select */
+       unsigned no_report_opcodes:1;   /* no REPORT SUPPORTED OPERATION CODES */
+       unsigned no_write_same:1;       /* no WRITE SAME command */
        unsigned skip_ms_page_8:1;      /* do not use MODE SENSE page 0x08 */
        unsigned skip_ms_page_3f:1;     /* do not use MODE SENSE page 0x3f */
        unsigned skip_vpd_pages:1;      /* do not read VPD pages */
@@ -362,6 +364,8 @@ extern int scsi_test_unit_ready(struct scsi_device *sdev, int timeout,
                                int retries, struct scsi_sense_hdr *sshdr);
 extern int scsi_get_vpd_page(struct scsi_device *, u8 page, unsigned char *buf,
                             int buf_len);
+extern int scsi_report_opcode(struct scsi_device *sdev, unsigned char *buffer,
+                             unsigned int len, unsigned char opcode);
 extern int scsi_device_set_state(struct scsi_device *sdev,
                                 enum scsi_device_state state);
 extern struct scsi_event *sdev_evt_alloc(enum scsi_device_event evt_type,
index bc056687f647f7aa9965d5ec4b297bbe9459e557..93896ad1fcdd70164c4254bd792d9b10da992b68 100644 (file)
@@ -132,6 +132,7 @@ struct snd_card {
        int shutdown;                   /* this card is going down */
        int free_on_last_close;         /* free in context of file_release */
        wait_queue_head_t shutdown_sleep;
+       atomic_t refcount;              /* refcount for disconnection */
        struct device *dev;             /* device assigned to this card */
        struct device *card_dev;        /* cardX object for sysfs */
 
@@ -189,6 +190,7 @@ struct snd_minor {
        const struct file_operations *f_ops;    /* file operations */
        void *private_data;             /* private data for f_ops->open */
        struct device *dev;             /* device for sysfs */
+       struct snd_card *card_ptr;      /* assigned card instance */
 };
 
 /* return a device pointer linked to each sound device as a parent */
@@ -295,6 +297,7 @@ int snd_card_info_done(void);
 int snd_component_add(struct snd_card *card, const char *component);
 int snd_card_file_add(struct snd_card *card, struct file *file);
 int snd_card_file_remove(struct snd_card *card, struct file *file);
+void snd_card_unref(struct snd_card *card);
 
 #define snd_card_set_dev(card, devptr) ((card)->dev = (devptr))
 
index 50a059e7d11616d4eb836cf7f0cc738cc0eaed3f..6d9e15ed1dcf0cb2875a10ca6795b14f3d4e0c51 100644 (file)
@@ -19,6 +19,7 @@
 
 struct cs4271_platform_data {
        int gpio_nreset;        /* GPIO driving Reset pin, if any */
+       int amutec_eq_bmutec:1; /* flag to enable AMUTEC=BMUTEC */
 };
 
 #endif /* __CS4271_H */
index 906010344dd7e0a227449f674d64b00a07dc1e86..cc1c919c64365898c47f7f6871b906dce0e5e1d4 100644 (file)
@@ -26,6 +26,7 @@
  * A:  inversion
  * B:  format mode
  * C:  chip specific
+ * D:  clock selecter if master mode
  */
 
 /* A: clock inversion */
 #define SH_FSI_OPTION_MASK     0x00000F00
 #define SH_FSI_ENABLE_STREAM_MODE      (1 << 8) /* for 16bit data */
 
+/* D:  clock selecter if master mode */
+#define SH_FSI_CLK_MASK                0x0000F000
+#define SH_FSI_CLK_EXTERNAL    (0 << 12)
+#define SH_FSI_CLK_CPG         (1 << 12) /* FSIxCK + FSI-DIV */
+
 /*
  * set_rate return value
  *
index 15ba03bdd7c69e9b4426aa3396ac772512b3e163..d06b6da5c1e3e146d500bae9b012b809d831cb25 100644 (file)
@@ -377,6 +377,14 @@ DECLARE_EVENT_CLASS(xen_mmu_pgd,
 DEFINE_XEN_MMU_PGD_EVENT(xen_mmu_pgd_pin);
 DEFINE_XEN_MMU_PGD_EVENT(xen_mmu_pgd_unpin);
 
+TRACE_EVENT(xen_mmu_flush_tlb_all,
+           TP_PROTO(int x),
+           TP_ARGS(x),
+           TP_STRUCT__entry(__array(char, x, 0)),
+           TP_fast_assign((void)x),
+           TP_printk("%s", "")
+       );
+
 TRACE_EVENT(xen_mmu_flush_tlb,
            TP_PROTO(int x),
            TP_ARGS(x),
index 8c99ce7202c53bcd93887c93dd8d8e75ebcd8aa2..2c267bcbb85c1c4e31b676127db7686d8d027e09 100644 (file)
@@ -25,7 +25,6 @@
 #define EPOLL_CTL_ADD 1
 #define EPOLL_CTL_DEL 2
 #define EPOLL_CTL_MOD 3
-#define EPOLL_CTL_DISABLE 4
 
 /*
  * Request the handling of system wakeup events so as to prevent system suspends
index a49c4afc70600d22ff904586cd41098a9e360e2d..b29272d621ce21162dc148217e4b6e89f72304b1 100644 (file)
@@ -8,4 +8,13 @@
 #define OOM_SCORE_ADJ_MIN      (-1000)
 #define OOM_SCORE_ADJ_MAX      1000
 
+/*
+ * /proc/<pid>/oom_adj set to -17 protects from the oom killer for legacy
+ * purposes.
+ */
+#define OOM_DISABLE (-17)
+/* inclusive */
+#define OOM_ADJUST_MIN (-16)
+#define OOM_ADJUST_MAX 15
+
 #endif /* _UAPI__INCLUDE_LINUX_OOM_H */
index aafaa5aa54d46bb9a93a8137a22344408298223f..e2c3d25405d7e20de2dc708088b0399350bd861f 100644 (file)
@@ -1 +1,3 @@
 # UAPI Header export list
+header-y += md_p.h
+header-y += md_u.h
diff --git a/include/uapi/linux/raid/md_p.h b/include/uapi/linux/raid/md_p.h
new file mode 100644 (file)
index 0000000..ee75353
--- /dev/null
@@ -0,0 +1,301 @@
+/*
+   md_p.h : physical layout of Linux RAID devices
+          Copyright (C) 1996-98 Ingo Molnar, Gadi Oxman
+         
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+   
+   You should have received a copy of the GNU General Public License
+   (for example /usr/src/linux/COPYING); if not, write to the Free
+   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
+*/
+
+#ifndef _MD_P_H
+#define _MD_P_H
+
+#include <linux/types.h>
+
+/*
+ * RAID superblock.
+ *
+ * The RAID superblock maintains some statistics on each RAID configuration.
+ * Each real device in the RAID set contains it near the end of the device.
+ * Some of the ideas are copied from the ext2fs implementation.
+ *
+ * We currently use 4096 bytes as follows:
+ *
+ *     word offset     function
+ *
+ *        0  -    31   Constant generic RAID device information.
+ *        32  -    63   Generic state information.
+ *       64  -   127   Personality specific information.
+ *      128  -   511   12 32-words descriptors of the disks in the raid set.
+ *      512  -   911   Reserved.
+ *      912  -  1023   Disk specific descriptor.
+ */
+
+/*
+ * If x is the real device size in bytes, we return an apparent size of:
+ *
+ *     y = (x & ~(MD_RESERVED_BYTES - 1)) - MD_RESERVED_BYTES
+ *
+ * and place the 4kB superblock at offset y.
+ */
+#define MD_RESERVED_BYTES              (64 * 1024)
+#define MD_RESERVED_SECTORS            (MD_RESERVED_BYTES / 512)
+
+#define MD_NEW_SIZE_SECTORS(x)         ((x & ~(MD_RESERVED_SECTORS - 1)) - MD_RESERVED_SECTORS)
+
+#define MD_SB_BYTES                    4096
+#define MD_SB_WORDS                    (MD_SB_BYTES / 4)
+#define MD_SB_SECTORS                  (MD_SB_BYTES / 512)
+
+/*
+ * The following are counted in 32-bit words
+ */
+#define        MD_SB_GENERIC_OFFSET            0
+#define MD_SB_PERSONALITY_OFFSET       64
+#define MD_SB_DISKS_OFFSET             128
+#define MD_SB_DESCRIPTOR_OFFSET                992
+
+#define MD_SB_GENERIC_CONSTANT_WORDS   32
+#define MD_SB_GENERIC_STATE_WORDS      32
+#define MD_SB_GENERIC_WORDS            (MD_SB_GENERIC_CONSTANT_WORDS + MD_SB_GENERIC_STATE_WORDS)
+#define MD_SB_PERSONALITY_WORDS                64
+#define MD_SB_DESCRIPTOR_WORDS         32
+#define MD_SB_DISKS                    27
+#define MD_SB_DISKS_WORDS              (MD_SB_DISKS*MD_SB_DESCRIPTOR_WORDS)
+#define MD_SB_RESERVED_WORDS           (1024 - MD_SB_GENERIC_WORDS - MD_SB_PERSONALITY_WORDS - MD_SB_DISKS_WORDS - MD_SB_DESCRIPTOR_WORDS)
+#define MD_SB_EQUAL_WORDS              (MD_SB_GENERIC_WORDS + MD_SB_PERSONALITY_WORDS + MD_SB_DISKS_WORDS)
+
+/*
+ * Device "operational" state bits
+ */
+#define MD_DISK_FAULTY         0 /* disk is faulty / operational */
+#define MD_DISK_ACTIVE         1 /* disk is running or spare disk */
+#define MD_DISK_SYNC           2 /* disk is in sync with the raid set */
+#define MD_DISK_REMOVED                3 /* disk is in sync with the raid set */
+
+#define        MD_DISK_WRITEMOSTLY     9 /* disk is "write-mostly" is RAID1 config.
+                                  * read requests will only be sent here in
+                                  * dire need
+                                  */
+
+typedef struct mdp_device_descriptor_s {
+       __u32 number;           /* 0 Device number in the entire set          */
+       __u32 major;            /* 1 Device major number                      */
+       __u32 minor;            /* 2 Device minor number                      */
+       __u32 raid_disk;        /* 3 The role of the device in the raid set   */
+       __u32 state;            /* 4 Operational state                        */
+       __u32 reserved[MD_SB_DESCRIPTOR_WORDS - 5];
+} mdp_disk_t;
+
+#define MD_SB_MAGIC            0xa92b4efc
+
+/*
+ * Superblock state bits
+ */
+#define MD_SB_CLEAN            0
+#define MD_SB_ERRORS           1
+
+#define        MD_SB_BITMAP_PRESENT    8 /* bitmap may be present nearby */
+
+/*
+ * Notes:
+ * - if an array is being reshaped (restriped) in order to change the
+ *   the number of active devices in the array, 'raid_disks' will be
+ *   the larger of the old and new numbers.  'delta_disks' will
+ *   be the "new - old".  So if +ve, raid_disks is the new value, and
+ *   "raid_disks-delta_disks" is the old.  If -ve, raid_disks is the
+ *   old value and "raid_disks+delta_disks" is the new (smaller) value.
+ */
+
+
+typedef struct mdp_superblock_s {
+       /*
+        * Constant generic information
+        */
+       __u32 md_magic;         /*  0 MD identifier                           */
+       __u32 major_version;    /*  1 major version to which the set conforms */
+       __u32 minor_version;    /*  2 minor version ...                       */
+       __u32 patch_version;    /*  3 patchlevel version ...                  */
+       __u32 gvalid_words;     /*  4 Number of used words in this section    */
+       __u32 set_uuid0;        /*  5 Raid set identifier                     */
+       __u32 ctime;            /*  6 Creation time                           */
+       __u32 level;            /*  7 Raid personality                        */
+       __u32 size;             /*  8 Apparent size of each individual disk   */
+       __u32 nr_disks;         /*  9 total disks in the raid set             */
+       __u32 raid_disks;       /* 10 disks in a fully functional raid set    */
+       __u32 md_minor;         /* 11 preferred MD minor device number        */
+       __u32 not_persistent;   /* 12 does it have a persistent superblock    */
+       __u32 set_uuid1;        /* 13 Raid set identifier #2                  */
+       __u32 set_uuid2;        /* 14 Raid set identifier #3                  */
+       __u32 set_uuid3;        /* 15 Raid set identifier #4                  */
+       __u32 gstate_creserved[MD_SB_GENERIC_CONSTANT_WORDS - 16];
+
+       /*
+        * Generic state information
+        */
+       __u32 utime;            /*  0 Superblock update time                  */
+       __u32 state;            /*  1 State bits (clean, ...)                 */
+       __u32 active_disks;     /*  2 Number of currently active disks        */
+       __u32 working_disks;    /*  3 Number of working disks                 */
+       __u32 failed_disks;     /*  4 Number of failed disks                  */
+       __u32 spare_disks;      /*  5 Number of spare disks                   */
+       __u32 sb_csum;          /*  6 checksum of the whole superblock        */
+#ifdef __BIG_ENDIAN
+       __u32 events_hi;        /*  7 high-order of superblock update count   */
+       __u32 events_lo;        /*  8 low-order of superblock update count    */
+       __u32 cp_events_hi;     /*  9 high-order of checkpoint update count   */
+       __u32 cp_events_lo;     /* 10 low-order of checkpoint update count    */
+#else
+       __u32 events_lo;        /*  7 low-order of superblock update count    */
+       __u32 events_hi;        /*  8 high-order of superblock update count   */
+       __u32 cp_events_lo;     /*  9 low-order of checkpoint update count    */
+       __u32 cp_events_hi;     /* 10 high-order of checkpoint update count   */
+#endif
+       __u32 recovery_cp;      /* 11 recovery checkpoint sector count        */
+       /* There are only valid for minor_version > 90 */
+       __u64 reshape_position; /* 12,13 next address in array-space for reshape */
+       __u32 new_level;        /* 14 new level we are reshaping to           */
+       __u32 delta_disks;      /* 15 change in number of raid_disks          */
+       __u32 new_layout;       /* 16 new layout                              */
+       __u32 new_chunk;        /* 17 new chunk size (bytes)                  */
+       __u32 gstate_sreserved[MD_SB_GENERIC_STATE_WORDS - 18];
+
+       /*
+        * Personality information
+        */
+       __u32 layout;           /*  0 the array's physical layout             */
+       __u32 chunk_size;       /*  1 chunk size in bytes                     */
+       __u32 root_pv;          /*  2 LV root PV */
+       __u32 root_block;       /*  3 LV root block */
+       __u32 pstate_reserved[MD_SB_PERSONALITY_WORDS - 4];
+
+       /*
+        * Disks information
+        */
+       mdp_disk_t disks[MD_SB_DISKS];
+
+       /*
+        * Reserved
+        */
+       __u32 reserved[MD_SB_RESERVED_WORDS];
+
+       /*
+        * Active descriptor
+        */
+       mdp_disk_t this_disk;
+
+} mdp_super_t;
+
+static inline __u64 md_event(mdp_super_t *sb) {
+       __u64 ev = sb->events_hi;
+       return (ev<<32)| sb->events_lo;
+}
+
+#define MD_SUPERBLOCK_1_TIME_SEC_MASK ((1ULL<<40) - 1)
+
+/*
+ * The version-1 superblock :
+ * All numeric fields are little-endian.
+ *
+ * total size: 256 bytes plus 2 per device.
+ *  1K allows 384 devices.
+ */
+struct mdp_superblock_1 {
+       /* constant array information - 128 bytes */
+       __le32  magic;          /* MD_SB_MAGIC: 0xa92b4efc - little endian */
+       __le32  major_version;  /* 1 */
+       __le32  feature_map;    /* bit 0 set if 'bitmap_offset' is meaningful */
+       __le32  pad0;           /* always set to 0 when writing */
+
+       __u8    set_uuid[16];   /* user-space generated. */
+       char    set_name[32];   /* set and interpreted by user-space */
+
+       __le64  ctime;          /* lo 40 bits are seconds, top 24 are microseconds or 0*/
+       __le32  level;          /* -4 (multipath), -1 (linear), 0,1,4,5 */
+       __le32  layout;         /* only for raid5 and raid10 currently */
+       __le64  size;           /* used size of component devices, in 512byte sectors */
+
+       __le32  chunksize;      /* in 512byte sectors */
+       __le32  raid_disks;
+       __le32  bitmap_offset;  /* sectors after start of superblock that bitmap starts
+                                * NOTE: signed, so bitmap can be before superblock
+                                * only meaningful of feature_map[0] is set.
+                                */
+
+       /* These are only valid with feature bit '4' */
+       __le32  new_level;      /* new level we are reshaping to                */
+       __le64  reshape_position;       /* next address in array-space for reshape */
+       __le32  delta_disks;    /* change in number of raid_disks               */
+       __le32  new_layout;     /* new layout                                   */
+       __le32  new_chunk;      /* new chunk size (512byte sectors)             */
+       __le32  new_offset;     /* signed number to add to data_offset in new
+                                * layout.  0 == no-change.  This can be
+                                * different on each device in the array.
+                                */
+
+       /* constant this-device information - 64 bytes */
+       __le64  data_offset;    /* sector start of data, often 0 */
+       __le64  data_size;      /* sectors in this device that can be used for data */
+       __le64  super_offset;   /* sector start of this superblock */
+       __le64  recovery_offset;/* sectors before this offset (from data_offset) have been recovered */
+       __le32  dev_number;     /* permanent identifier of this  device - not role in raid */
+       __le32  cnt_corrected_read; /* number of read errors that were corrected by re-writing */
+       __u8    device_uuid[16]; /* user-space setable, ignored by kernel */
+       __u8    devflags;       /* per-device flags.  Only one defined...*/
+#define        WriteMostly1    1       /* mask for writemostly flag in above */
+       /* Bad block log.  If there are any bad blocks the feature flag is set.
+        * If offset and size are non-zero, that space is reserved and available
+        */
+       __u8    bblog_shift;    /* shift from sectors to block size */
+       __le16  bblog_size;     /* number of sectors reserved for list */
+       __le32  bblog_offset;   /* sector offset from superblock to bblog,
+                                * signed - not unsigned */
+
+       /* array state information - 64 bytes */
+       __le64  utime;          /* 40 bits second, 24 bits microseconds */
+       __le64  events;         /* incremented when superblock updated */
+       __le64  resync_offset;  /* data before this offset (from data_offset) known to be in sync */
+       __le32  sb_csum;        /* checksum up to devs[max_dev] */
+       __le32  max_dev;        /* size of devs[] array to consider */
+       __u8    pad3[64-32];    /* set to 0 when writing */
+
+       /* device state information. Indexed by dev_number.
+        * 2 bytes per device
+        * Note there are no per-device state flags. State information is rolled
+        * into the 'roles' value.  If a device is spare or faulty, then it doesn't
+        * have a meaningful role.
+        */
+       __le16  dev_roles[0];   /* role in array, or 0xffff for a spare, or 0xfffe for faulty */
+};
+
+/* feature_map bits */
+#define MD_FEATURE_BITMAP_OFFSET       1
+#define        MD_FEATURE_RECOVERY_OFFSET      2 /* recovery_offset is present and
+                                          * must be honoured
+                                          */
+#define        MD_FEATURE_RESHAPE_ACTIVE       4
+#define        MD_FEATURE_BAD_BLOCKS           8 /* badblock list is not empty */
+#define        MD_FEATURE_REPLACEMENT          16 /* This device is replacing an
+                                           * active device with same 'role'.
+                                           * 'recovery_offset' is also set.
+                                           */
+#define        MD_FEATURE_RESHAPE_BACKWARDS    32 /* Reshape doesn't change number
+                                           * of devices, but is going
+                                           * backwards anyway.
+                                           */
+#define        MD_FEATURE_NEW_OFFSET           64 /* new_offset must be honoured */
+#define        MD_FEATURE_ALL                  (MD_FEATURE_BITMAP_OFFSET       \
+                                       |MD_FEATURE_RECOVERY_OFFSET     \
+                                       |MD_FEATURE_RESHAPE_ACTIVE      \
+                                       |MD_FEATURE_BAD_BLOCKS          \
+                                       |MD_FEATURE_REPLACEMENT         \
+                                       |MD_FEATURE_RESHAPE_BACKWARDS   \
+                                       |MD_FEATURE_NEW_OFFSET          \
+                                       )
+
+#endif 
diff --git a/include/uapi/linux/raid/md_u.h b/include/uapi/linux/raid/md_u.h
new file mode 100644 (file)
index 0000000..4133e74
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+   md_u.h : user <=> kernel API between Linux raidtools and RAID drivers
+          Copyright (C) 1998 Ingo Molnar
+         
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+   
+   You should have received a copy of the GNU General Public License
+   (for example /usr/src/linux/COPYING); if not, write to the Free
+   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
+*/
+
+#ifndef _UAPI_MD_U_H
+#define _UAPI_MD_U_H
+
+/*
+ * Different major versions are not compatible.
+ * Different minor versions are only downward compatible.
+ * Different patchlevel versions are downward and upward compatible.
+ */
+#define MD_MAJOR_VERSION                0
+#define MD_MINOR_VERSION                90
+/*
+ * MD_PATCHLEVEL_VERSION indicates kernel functionality.
+ * >=1 means different superblock formats are selectable using SET_ARRAY_INFO
+ *     and major_version/minor_version accordingly
+ * >=2 means that Internal bitmaps are supported by setting MD_SB_BITMAP_PRESENT
+ *     in the super status byte
+ * >=3 means that bitmap superblock version 4 is supported, which uses
+ *     little-ending representation rather than host-endian
+ */
+#define MD_PATCHLEVEL_VERSION           3
+
+/* ioctls */
+
+/* status */
+#define RAID_VERSION           _IOR (MD_MAJOR, 0x10, mdu_version_t)
+#define GET_ARRAY_INFO         _IOR (MD_MAJOR, 0x11, mdu_array_info_t)
+#define GET_DISK_INFO          _IOR (MD_MAJOR, 0x12, mdu_disk_info_t)
+#define PRINT_RAID_DEBUG       _IO (MD_MAJOR, 0x13)
+#define RAID_AUTORUN           _IO (MD_MAJOR, 0x14)
+#define GET_BITMAP_FILE                _IOR (MD_MAJOR, 0x15, mdu_bitmap_file_t)
+
+/* configuration */
+#define CLEAR_ARRAY            _IO (MD_MAJOR, 0x20)
+#define ADD_NEW_DISK           _IOW (MD_MAJOR, 0x21, mdu_disk_info_t)
+#define HOT_REMOVE_DISK                _IO (MD_MAJOR, 0x22)
+#define SET_ARRAY_INFO         _IOW (MD_MAJOR, 0x23, mdu_array_info_t)
+#define SET_DISK_INFO          _IO (MD_MAJOR, 0x24)
+#define WRITE_RAID_INFO                _IO (MD_MAJOR, 0x25)
+#define UNPROTECT_ARRAY                _IO (MD_MAJOR, 0x26)
+#define PROTECT_ARRAY          _IO (MD_MAJOR, 0x27)
+#define HOT_ADD_DISK           _IO (MD_MAJOR, 0x28)
+#define SET_DISK_FAULTY                _IO (MD_MAJOR, 0x29)
+#define HOT_GENERATE_ERROR     _IO (MD_MAJOR, 0x2a)
+#define SET_BITMAP_FILE                _IOW (MD_MAJOR, 0x2b, int)
+
+/* usage */
+#define RUN_ARRAY              _IOW (MD_MAJOR, 0x30, mdu_param_t)
+/*  0x31 was START_ARRAY  */
+#define STOP_ARRAY             _IO (MD_MAJOR, 0x32)
+#define STOP_ARRAY_RO          _IO (MD_MAJOR, 0x33)
+#define RESTART_ARRAY_RW       _IO (MD_MAJOR, 0x34)
+
+/* 63 partitions with the alternate major number (mdp) */
+#define MdpMinorShift 6
+
+typedef struct mdu_version_s {
+       int major;
+       int minor;
+       int patchlevel;
+} mdu_version_t;
+
+typedef struct mdu_array_info_s {
+       /*
+        * Generic constant information
+        */
+       int major_version;
+       int minor_version;
+       int patch_version;
+       int ctime;
+       int level;
+       int size;
+       int nr_disks;
+       int raid_disks;
+       int md_minor;
+       int not_persistent;
+
+       /*
+        * Generic state information
+        */
+       int utime;              /*  0 Superblock update time                  */
+       int state;              /*  1 State bits (clean, ...)                 */
+       int active_disks;       /*  2 Number of currently active disks        */
+       int working_disks;      /*  3 Number of working disks                 */
+       int failed_disks;       /*  4 Number of failed disks                  */
+       int spare_disks;        /*  5 Number of spare disks                   */
+
+       /*
+        * Personality information
+        */
+       int layout;             /*  0 the array's physical layout             */
+       int chunk_size; /*  1 chunk size in bytes                     */
+
+} mdu_array_info_t;
+
+/* non-obvious values for 'level' */
+#define        LEVEL_MULTIPATH         (-4)
+#define        LEVEL_LINEAR            (-1)
+#define        LEVEL_FAULTY            (-5)
+
+/* we need a value for 'no level specified' and 0
+ * means 'raid0', so we need something else.  This is
+ * for internal use only
+ */
+#define        LEVEL_NONE              (-1000000)
+
+typedef struct mdu_disk_info_s {
+       /*
+        * configuration/status of one particular disk
+        */
+       int number;
+       int major;
+       int minor;
+       int raid_disk;
+       int state;
+
+} mdu_disk_info_t;
+
+typedef struct mdu_start_info_s {
+       /*
+        * configuration/status of one particular disk
+        */
+       int major;
+       int minor;
+       int raid_disk;
+       int state;
+
+} mdu_start_info_t;
+
+typedef struct mdu_bitmap_file_s
+{
+       char pathname[4096];
+} mdu_bitmap_file_t;
+
+typedef struct mdu_param_s
+{
+       int                     personality;    /* 1,2,3,4 */
+       int                     chunk_size;     /* in bytes */
+       int                     max_fault;      /* unused for now */
+} mdu_param_t;
+
+#endif /* _UAPI_MD_U_H */
index c4b89a5cb7df4ffa3f93a0206e1f03bf19829d31..e962faa5ab0dcf9d58909b0256a78f51029e290b 100644 (file)
@@ -130,6 +130,7 @@ enum {
 #define TCPI_OPT_WSCALE                4
 #define TCPI_OPT_ECN           8 /* ECN was negociated at TCP session init */
 #define TCPI_OPT_ECN_SEEN      16 /* we received at least one packet with ECT */
+#define TCPI_OPT_SYN_DATA      32 /* SYN-ACK acked data in SYN sent or rcvd */
 
 enum tcp_ca_state {
        TCP_CA_Open = 0,
index aecee9d112cbe6aea2532652c8c3f768bb829cce..694dcaf266e635335dfdaf22994624d3d5e3d9d4 100644 (file)
@@ -170,7 +170,7 @@ gnttab_set_unmap_op(struct gnttab_unmap_grant_ref *unmap, phys_addr_t addr,
        unmap->dev_bus_addr = 0;
 }
 
-int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes,
+int arch_gnttab_map_shared(xen_pfn_t *frames, unsigned long nr_gframes,
                           unsigned long max_nr_gframes,
                           void **__shared);
 int arch_gnttab_map_status(uint64_t *frames, unsigned long nr_gframes,
index b193fa2f9fddb2ef6670a7e1aa7f27ef4b60edbe..13e43e41637dad471aa9c7033474c57596260371 100644 (file)
@@ -5,6 +5,36 @@
 #include <xen/interface/hvm/params.h>
 #include <asm/xen/hypercall.h>
 
+static const char *param_name(int op)
+{
+#define PARAM(x) [HVM_PARAM_##x] = #x
+       static const char *const names[] = {
+               PARAM(CALLBACK_IRQ),
+               PARAM(STORE_PFN),
+               PARAM(STORE_EVTCHN),
+               PARAM(PAE_ENABLED),
+               PARAM(IOREQ_PFN),
+               PARAM(BUFIOREQ_PFN),
+               PARAM(TIMER_MODE),
+               PARAM(HPET_ENABLED),
+               PARAM(IDENT_PT),
+               PARAM(DM_DOMAIN),
+               PARAM(ACPI_S_STATE),
+               PARAM(VM86_TSS),
+               PARAM(VPT_ALIGN),
+               PARAM(CONSOLE_PFN),
+               PARAM(CONSOLE_EVTCHN),
+       };
+#undef PARAM
+
+       if (op >= ARRAY_SIZE(names))
+               return "unknown";
+
+       if (!names[op])
+               return "reserved";
+
+       return names[op];
+}
 static inline int hvm_get_parameter(int idx, uint64_t *value)
 {
        struct xen_hvm_param xhv;
@@ -14,8 +44,8 @@ static inline int hvm_get_parameter(int idx, uint64_t *value)
        xhv.index = idx;
        r = HYPERVISOR_hvm_op(HVMOP_get_param, &xhv);
        if (r < 0) {
-               printk(KERN_ERR "Cannot get hvm parameter %d: %d!\n",
-                       idx, r);
+               printk(KERN_ERR "Cannot get hvm parameter %s (%d): %d!\n",
+                       param_name(idx), idx, r);
                return r;
        }
        *value = xhv.value;
index f9f8b975ae7448bfdae47100ad7da63a34fbe39b..e40fae9bf11acd67b64ece81bae1d04efefc44fd 100644 (file)
@@ -310,7 +310,7 @@ struct gnttab_setup_table {
     uint32_t nr_frames;
     /* OUT parameters. */
     int16_t  status;              /* GNTST_* */
-    GUEST_HANDLE(ulong) frame_list;
+    GUEST_HANDLE(xen_pfn_t) frame_list;
 };
 DEFINE_GUEST_HANDLE_STRUCT(gnttab_setup_table);
 
index b66d04ce6957549a1097c532bc483e5ee6ab38d8..90712e2072d57ba6c6154549352266d253ab3615 100644 (file)
@@ -179,28 +179,8 @@ struct xen_add_to_physmap {
 };
 DEFINE_GUEST_HANDLE_STRUCT(xen_add_to_physmap);
 
-/*
- * Translates a list of domain-specific GPFNs into MFNs. Returns a -ve error
- * code on failure. This call only works for auto-translated guests.
- */
-#define XENMEM_translate_gpfn_list  8
-struct xen_translate_gpfn_list {
-    /* Which domain to translate for? */
-    domid_t domid;
-
-    /* Length of list. */
-    xen_ulong_t nr_gpfns;
-
-    /* List of GPFNs to translate. */
-    GUEST_HANDLE(ulong) gpfn_list;
-
-    /*
-     * Output list to contain MFN translations. May be the same as the input
-     * list (in which case each input GPFN is overwritten with the output MFN).
-     */
-    GUEST_HANDLE(ulong) mfn_list;
-};
-DEFINE_GUEST_HANDLE_STRUCT(xen_translate_gpfn_list);
+/*** REMOVED ***/
+/*#define XENMEM_translate_gpfn_list  8*/
 
 /*
  * Returns the pseudo-physical memory map as it was when the domain
index 9cf77ab138a68738bb6926b8b31aaf6ba8cd4f6e..e33e09df3cbc61ad11736776ef4138010df1de8e 100644 (file)
@@ -442,9 +442,11 @@ void __init __weak smp_setup_processor_id(void)
 {
 }
 
+# if THREAD_SIZE >= PAGE_SIZE
 void __init __weak thread_info_cache_init(void)
 {
 }
+#endif
 
 /*
  * Set up kernel memory allocators
index 0dfeca4324ee06dbb6566db568b9874758344232..86e3285ae7e5b48fd9b123291da2d8dbfe0d7460 100644 (file)
@@ -174,10 +174,8 @@ signing_key.priv signing_key.x509: x509.genkey
        @echo "###"
        @echo "### If this takes a long time, you might wish to run rngd in the"
        @echo "### background to keep the supply of entropy topped up.  It"
-       @echo "### needs to be run as root, and should use a hardware random"
-       @echo "### number generator if one is available, eg:"
-       @echo "###"
-       @echo "###     rngd -r /dev/hwrandom"
+       @echo "### needs to be run as root, and uses a hardware random"
+       @echo "### number generator if one is available."
        @echo "###"
        openssl req -new -nodes -utf8 $(sign_key_with_hash) -days 36500 -batch \
                -x509 -config x509.genkey \
index 13774b3b39aac9b73e25ba34a366d5402b70df00..f24f724620dd8489fc2e3cb9781433df84096c96 100644 (file)
@@ -1962,9 +1962,8 @@ static void cgroup_task_migrate(struct cgroup *cgrp, struct cgroup *oldcgrp,
         * trading it for newcg is protected by cgroup_mutex, we're safe to drop
         * it here; it will be freed under RCU.
         */
-       put_css_set(oldcg);
-
        set_bit(CGRP_RELEASABLE, &oldcgrp->flags);
+       put_css_set(oldcg);
 }
 
 /**
@@ -4815,31 +4814,20 @@ static const struct file_operations proc_cgroupstats_operations = {
  *
  * A pointer to the shared css_set was automatically copied in
  * fork.c by dup_task_struct().  However, we ignore that copy, since
- * it was not made under the protection of RCU, cgroup_mutex or
- * threadgroup_change_begin(), so it might no longer be a valid
- * cgroup pointer.  cgroup_attach_task() might have already changed
- * current->cgroups, allowing the previously referenced cgroup
- * group to be removed and freed.
- *
- * Outside the pointer validity we also need to process the css_set
- * inheritance between threadgoup_change_begin() and
- * threadgoup_change_end(), this way there is no leak in any process
- * wide migration performed by cgroup_attach_proc() that could otherwise
- * miss a thread because it is too early or too late in the fork stage.
+ * it was not made under the protection of RCU or cgroup_mutex, so
+ * might no longer be a valid cgroup pointer.  cgroup_attach_task() might
+ * have already changed current->cgroups, allowing the previously
+ * referenced cgroup group to be removed and freed.
  *
  * At the point that cgroup_fork() is called, 'current' is the parent
  * task, and the passed argument 'child' points to the child task.
  */
 void cgroup_fork(struct task_struct *child)
 {
-       /*
-        * We don't need to task_lock() current because current->cgroups
-        * can't be changed concurrently here. The parent obviously hasn't
-        * exited and called cgroup_exit(), and we are synchronized against
-        * cgroup migration through threadgroup_change_begin().
-        */
+       task_lock(current);
        child->cgroups = current->cgroups;
        get_css_set(child->cgroups);
+       task_unlock(current);
        INIT_LIST_HEAD(&child->cg_list);
 }
 
@@ -4895,19 +4883,10 @@ void cgroup_post_fork(struct task_struct *child)
         */
        if (use_task_css_set_links) {
                write_lock(&css_set_lock);
-               if (list_empty(&child->cg_list)) {
-                       /*
-                        * It's safe to use child->cgroups without task_lock()
-                        * here because we are protected through
-                        * threadgroup_change_begin() against concurrent
-                        * css_set change in cgroup_task_migrate(). Also
-                        * the task can't exit at that point until
-                        * wake_up_new_task() is called, so we are protected
-                        * against cgroup_exit() setting child->cgroup to
-                        * init_css_set.
-                        */
+               task_lock(child);
+               if (list_empty(&child->cg_list))
                        list_add(&child->cg_list, &child->cgroups->tasks);
-               }
+               task_unlock(child);
                write_unlock(&css_set_lock);
        }
 }
index 98256bc71ee136915b126b81dd1e61b8990a8ce3..5cc4e7e42e689a7076ece7eb252f5a1f3a1eb5b6 100644 (file)
@@ -78,15 +78,23 @@ static struct mutex uprobes_mmap_mutex[UPROBES_HASH_SZ];
  */
 static atomic_t uprobe_events = ATOMIC_INIT(0);
 
+/* Have a copy of original instruction */
+#define UPROBE_COPY_INSN       0
+/* Dont run handlers when first register/ last unregister in progress*/
+#define UPROBE_RUN_HANDLER     1
+/* Can skip singlestep */
+#define UPROBE_SKIP_SSTEP      2
+
 struct uprobe {
        struct rb_node          rb_node;        /* node in the rb tree */
        atomic_t                ref;
        struct rw_semaphore     consumer_rwsem;
+       struct mutex            copy_mutex;     /* TODO: kill me and UPROBE_COPY_INSN */
        struct list_head        pending_list;
        struct uprobe_consumer  *consumers;
        struct inode            *inode;         /* Also hold a ref to inode */
        loff_t                  offset;
-       int                     flags;
+       unsigned long           flags;
        struct arch_uprobe      arch;
 };
 
@@ -100,17 +108,12 @@ struct uprobe {
  */
 static bool valid_vma(struct vm_area_struct *vma, bool is_register)
 {
-       if (!vma->vm_file)
-               return false;
-
-       if (!is_register)
-               return true;
+       vm_flags_t flags = VM_HUGETLB | VM_MAYEXEC | VM_SHARED;
 
-       if ((vma->vm_flags & (VM_HUGETLB|VM_READ|VM_WRITE|VM_EXEC|VM_SHARED))
-                               == (VM_READ|VM_EXEC))
-               return true;
+       if (is_register)
+               flags |= VM_WRITE;
 
-       return false;
+       return vma->vm_file && (vma->vm_flags & flags) == VM_MAYEXEC;
 }
 
 static unsigned long offset_to_vaddr(struct vm_area_struct *vma, loff_t offset)
@@ -193,19 +196,44 @@ bool __weak is_swbp_insn(uprobe_opcode_t *insn)
        return *insn == UPROBE_SWBP_INSN;
 }
 
+static void copy_opcode(struct page *page, unsigned long vaddr, uprobe_opcode_t *opcode)
+{
+       void *kaddr = kmap_atomic(page);
+       memcpy(opcode, kaddr + (vaddr & ~PAGE_MASK), UPROBE_SWBP_INSN_SIZE);
+       kunmap_atomic(kaddr);
+}
+
+static int verify_opcode(struct page *page, unsigned long vaddr, uprobe_opcode_t *new_opcode)
+{
+       uprobe_opcode_t old_opcode;
+       bool is_swbp;
+
+       copy_opcode(page, vaddr, &old_opcode);
+       is_swbp = is_swbp_insn(&old_opcode);
+
+       if (is_swbp_insn(new_opcode)) {
+               if (is_swbp)            /* register: already installed? */
+                       return 0;
+       } else {
+               if (!is_swbp)           /* unregister: was it changed by us? */
+                       return 0;
+       }
+
+       return 1;
+}
+
 /*
  * NOTE:
  * Expect the breakpoint instruction to be the smallest size instruction for
  * the architecture. If an arch has variable length instruction and the
  * breakpoint instruction is not of the smallest length instruction
- * supported by that architecture then we need to modify read_opcode /
+ * supported by that architecture then we need to modify is_swbp_at_addr and
  * write_opcode accordingly. This would never be a problem for archs that
  * have fixed length instructions.
  */
 
 /*
  * write_opcode - write the opcode at a given virtual address.
- * @auprobe: arch breakpointing information.
  * @mm: the probed process address space.
  * @vaddr: the virtual address to store the opcode.
  * @opcode: opcode to be written at @vaddr.
@@ -216,8 +244,8 @@ bool __weak is_swbp_insn(uprobe_opcode_t *insn)
  * For mm @mm, write the opcode at @vaddr.
  * Return 0 (success) or a negative errno.
  */
-static int write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm,
-                       unsigned long vaddr, uprobe_opcode_t opcode)
+static int write_opcode(struct mm_struct *mm, unsigned long vaddr,
+                       uprobe_opcode_t opcode)
 {
        struct page *old_page, *new_page;
        void *vaddr_old, *vaddr_new;
@@ -226,10 +254,14 @@ static int write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm,
 
 retry:
        /* Read the page with vaddr into memory */
-       ret = get_user_pages(NULL, mm, vaddr, 1, 0, 0, &old_page, &vma);
+       ret = get_user_pages(NULL, mm, vaddr, 1, 0, 1, &old_page, &vma);
        if (ret <= 0)
                return ret;
 
+       ret = verify_opcode(old_page, vaddr, &opcode);
+       if (ret <= 0)
+               goto put_old;
+
        ret = -ENOMEM;
        new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, vaddr);
        if (!new_page)
@@ -263,63 +295,6 @@ put_old:
        return ret;
 }
 
-/**
- * read_opcode - read the opcode at a given virtual address.
- * @mm: the probed process address space.
- * @vaddr: the virtual address to read the opcode.
- * @opcode: location to store the read opcode.
- *
- * Called with mm->mmap_sem held (for read and with a reference to
- * mm.
- *
- * For mm @mm, read the opcode at @vaddr and store it in @opcode.
- * Return 0 (success) or a negative errno.
- */
-static int read_opcode(struct mm_struct *mm, unsigned long vaddr, uprobe_opcode_t *opcode)
-{
-       struct page *page;
-       void *vaddr_new;
-       int ret;
-
-       ret = get_user_pages(NULL, mm, vaddr, 1, 0, 1, &page, NULL);
-       if (ret <= 0)
-               return ret;
-
-       vaddr_new = kmap_atomic(page);
-       vaddr &= ~PAGE_MASK;
-       memcpy(opcode, vaddr_new + vaddr, UPROBE_SWBP_INSN_SIZE);
-       kunmap_atomic(vaddr_new);
-
-       put_page(page);
-
-       return 0;
-}
-
-static int is_swbp_at_addr(struct mm_struct *mm, unsigned long vaddr)
-{
-       uprobe_opcode_t opcode;
-       int result;
-
-       if (current->mm == mm) {
-               pagefault_disable();
-               result = __copy_from_user_inatomic(&opcode, (void __user*)vaddr,
-                                                               sizeof(opcode));
-               pagefault_enable();
-
-               if (likely(result == 0))
-                       goto out;
-       }
-
-       result = read_opcode(mm, vaddr, &opcode);
-       if (result)
-               return result;
-out:
-       if (is_swbp_insn(&opcode))
-               return 1;
-
-       return 0;
-}
-
 /**
  * set_swbp - store breakpoint at a given address.
  * @auprobe: arch specific probepoint information.
@@ -331,18 +306,7 @@ out:
  */
 int __weak set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr)
 {
-       int result;
-       /*
-        * See the comment near uprobes_hash().
-        */
-       result = is_swbp_at_addr(mm, vaddr);
-       if (result == 1)
-               return 0;
-
-       if (result)
-               return result;
-
-       return write_opcode(auprobe, mm, vaddr, UPROBE_SWBP_INSN);
+       return write_opcode(mm, vaddr, UPROBE_SWBP_INSN);
 }
 
 /**
@@ -357,16 +321,7 @@ int __weak set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned
 int __weak
 set_orig_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr)
 {
-       int result;
-
-       result = is_swbp_at_addr(mm, vaddr);
-       if (!result)
-               return -EINVAL;
-
-       if (result != 1)
-               return result;
-
-       return write_opcode(auprobe, mm, vaddr, *(uprobe_opcode_t *)auprobe->insn);
+       return write_opcode(mm, vaddr, *(uprobe_opcode_t *)auprobe->insn);
 }
 
 static int match_uprobe(struct uprobe *l, struct uprobe *r)
@@ -473,7 +428,7 @@ static struct uprobe *insert_uprobe(struct uprobe *uprobe)
        spin_unlock(&uprobes_treelock);
 
        /* For now assume that the instruction need not be single-stepped */
-       uprobe->flags |= UPROBE_SKIP_SSTEP;
+       __set_bit(UPROBE_SKIP_SSTEP, &uprobe->flags);
 
        return u;
 }
@@ -495,6 +450,7 @@ static struct uprobe *alloc_uprobe(struct inode *inode, loff_t offset)
        uprobe->inode = igrab(inode);
        uprobe->offset = offset;
        init_rwsem(&uprobe->consumer_rwsem);
+       mutex_init(&uprobe->copy_mutex);
 
        /* add to uprobes_tree, sorted on inode:offset */
        cur_uprobe = insert_uprobe(uprobe);
@@ -515,7 +471,7 @@ static void handler_chain(struct uprobe *uprobe, struct pt_regs *regs)
 {
        struct uprobe_consumer *uc;
 
-       if (!(uprobe->flags & UPROBE_RUN_HANDLER))
+       if (!test_bit(UPROBE_RUN_HANDLER, &uprobe->flags))
                return;
 
        down_read(&uprobe->consumer_rwsem);
@@ -621,29 +577,43 @@ static int copy_insn(struct uprobe *uprobe, struct file *filp)
        return __copy_insn(mapping, filp, uprobe->arch.insn, bytes, uprobe->offset);
 }
 
-/*
- * How mm->uprobes_state.count gets updated
- * uprobe_mmap() increments the count if
- *     - it successfully adds a breakpoint.
- *     - it cannot add a breakpoint, but sees that there is a underlying
- *       breakpoint (via a is_swbp_at_addr()).
- *
- * uprobe_munmap() decrements the count if
- *     - it sees a underlying breakpoint, (via is_swbp_at_addr)
- *       (Subsequent uprobe_unregister wouldnt find the breakpoint
- *       unless a uprobe_mmap kicks in, since the old vma would be
- *       dropped just after uprobe_munmap.)
- *
- * uprobe_register increments the count if:
- *     - it successfully adds a breakpoint.
- *
- * uprobe_unregister decrements the count if:
- *     - it sees a underlying breakpoint and removes successfully.
- *       (via is_swbp_at_addr)
- *       (Subsequent uprobe_munmap wouldnt find the breakpoint
- *       since there is no underlying breakpoint after the
- *       breakpoint removal.)
- */
+static int prepare_uprobe(struct uprobe *uprobe, struct file *file,
+                               struct mm_struct *mm, unsigned long vaddr)
+{
+       int ret = 0;
+
+       if (test_bit(UPROBE_COPY_INSN, &uprobe->flags))
+               return ret;
+
+       mutex_lock(&uprobe->copy_mutex);
+       if (test_bit(UPROBE_COPY_INSN, &uprobe->flags))
+               goto out;
+
+       ret = copy_insn(uprobe, file);
+       if (ret)
+               goto out;
+
+       ret = -ENOTSUPP;
+       if (is_swbp_insn((uprobe_opcode_t *)uprobe->arch.insn))
+               goto out;
+
+       ret = arch_uprobe_analyze_insn(&uprobe->arch, mm, vaddr);
+       if (ret)
+               goto out;
+
+       /* write_opcode() assumes we don't cross page boundary */
+       BUG_ON((uprobe->offset & ~PAGE_MASK) +
+                       UPROBE_SWBP_INSN_SIZE > PAGE_SIZE);
+
+       smp_wmb(); /* pairs with rmb() in find_active_uprobe() */
+       set_bit(UPROBE_COPY_INSN, &uprobe->flags);
+
+ out:
+       mutex_unlock(&uprobe->copy_mutex);
+
+       return ret;
+}
+
 static int
 install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm,
                        struct vm_area_struct *vma, unsigned long vaddr)
@@ -661,24 +631,9 @@ install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm,
        if (!uprobe->consumers)
                return 0;
 
-       if (!(uprobe->flags & UPROBE_COPY_INSN)) {
-               ret = copy_insn(uprobe, vma->vm_file);
-               if (ret)
-                       return ret;
-
-               if (is_swbp_insn((uprobe_opcode_t *)uprobe->arch.insn))
-                       return -ENOTSUPP;
-
-               ret = arch_uprobe_analyze_insn(&uprobe->arch, mm, vaddr);
-               if (ret)
-                       return ret;
-
-               /* write_opcode() assumes we don't cross page boundary */
-               BUG_ON((uprobe->offset & ~PAGE_MASK) +
-                               UPROBE_SWBP_INSN_SIZE > PAGE_SIZE);
-
-               uprobe->flags |= UPROBE_COPY_INSN;
-       }
+       ret = prepare_uprobe(uprobe, vma->vm_file, mm, vaddr);
+       if (ret)
+               return ret;
 
        /*
         * set MMF_HAS_UPROBES in advance for uprobe_pre_sstep_notifier(),
@@ -697,15 +652,15 @@ install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm,
        return ret;
 }
 
-static void
+static int
 remove_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, unsigned long vaddr)
 {
        /* can happen if uprobe_register() fails */
        if (!test_bit(MMF_HAS_UPROBES, &mm->flags))
-               return;
+               return 0;
 
        set_bit(MMF_RECALC_UPROBES, &mm->flags);
-       set_orig_insn(&uprobe->arch, mm, vaddr);
+       return set_orig_insn(&uprobe->arch, mm, vaddr);
 }
 
 /*
@@ -820,7 +775,7 @@ static int register_for_each_vma(struct uprobe *uprobe, bool is_register)
                struct mm_struct *mm = info->mm;
                struct vm_area_struct *vma;
 
-               if (err)
+               if (err && is_register)
                        goto free;
 
                down_write(&mm->mmap_sem);
@@ -836,7 +791,7 @@ static int register_for_each_vma(struct uprobe *uprobe, bool is_register)
                if (is_register)
                        err = install_breakpoint(uprobe, mm, vma, info->vaddr);
                else
-                       remove_breakpoint(uprobe, mm, info->vaddr);
+                       err |= remove_breakpoint(uprobe, mm, info->vaddr);
 
  unlock:
                up_write(&mm->mmap_sem);
@@ -893,13 +848,15 @@ int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *
        mutex_lock(uprobes_hash(inode));
        uprobe = alloc_uprobe(inode, offset);
 
-       if (uprobe && !consumer_add(uprobe, uc)) {
+       if (!uprobe) {
+               ret = -ENOMEM;
+       } else if (!consumer_add(uprobe, uc)) {
                ret = __uprobe_register(uprobe);
                if (ret) {
                        uprobe->consumers = NULL;
                        __uprobe_unregister(uprobe);
                } else {
-                       uprobe->flags |= UPROBE_RUN_HANDLER;
+                       set_bit(UPROBE_RUN_HANDLER, &uprobe->flags);
                }
        }
 
@@ -932,7 +889,7 @@ void uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consume
        if (consumer_del(uprobe, uc)) {
                if (!uprobe->consumers) {
                        __uprobe_unregister(uprobe);
-                       uprobe->flags &= ~UPROBE_RUN_HANDLER;
+                       clear_bit(UPROBE_RUN_HANDLER, &uprobe->flags);
                }
        }
 
@@ -1393,10 +1350,11 @@ bool uprobe_deny_signal(void)
  */
 static bool can_skip_sstep(struct uprobe *uprobe, struct pt_regs *regs)
 {
-       if (arch_uprobe_skip_sstep(&uprobe->arch, regs))
-               return true;
-
-       uprobe->flags &= ~UPROBE_SKIP_SSTEP;
+       if (test_bit(UPROBE_SKIP_SSTEP, &uprobe->flags)) {
+               if (arch_uprobe_skip_sstep(&uprobe->arch, regs))
+                       return true;
+               clear_bit(UPROBE_SKIP_SSTEP, &uprobe->flags);
+       }
        return false;
 }
 
@@ -1419,6 +1377,30 @@ static void mmf_recalc_uprobes(struct mm_struct *mm)
        clear_bit(MMF_HAS_UPROBES, &mm->flags);
 }
 
+static int is_swbp_at_addr(struct mm_struct *mm, unsigned long vaddr)
+{
+       struct page *page;
+       uprobe_opcode_t opcode;
+       int result;
+
+       pagefault_disable();
+       result = __copy_from_user_inatomic(&opcode, (void __user*)vaddr,
+                                                       sizeof(opcode));
+       pagefault_enable();
+
+       if (likely(result == 0))
+               goto out;
+
+       result = get_user_pages(NULL, mm, vaddr, 1, 0, 1, &page, NULL);
+       if (result < 0)
+               return result;
+
+       copy_opcode(page, vaddr, &opcode);
+       put_page(page);
+ out:
+       return is_swbp_insn(&opcode);
+}
+
 static struct uprobe *find_active_uprobe(unsigned long bp_vaddr, int *is_swbp)
 {
        struct mm_struct *mm = current->mm;
@@ -1489,38 +1471,41 @@ static void handle_swbp(struct pt_regs *regs)
                }
                return;
        }
+       /*
+        * TODO: move copy_insn/etc into _register and remove this hack.
+        * After we hit the bp, _unregister + _register can install the
+        * new and not-yet-analyzed uprobe at the same address, restart.
+        */
+       smp_rmb(); /* pairs with wmb() in install_breakpoint() */
+       if (unlikely(!test_bit(UPROBE_COPY_INSN, &uprobe->flags)))
+               goto restart;
 
        utask = current->utask;
        if (!utask) {
                utask = add_utask();
                /* Cannot allocate; re-execute the instruction. */
                if (!utask)
-                       goto cleanup_ret;
+                       goto restart;
        }
-       utask->active_uprobe = uprobe;
+
        handler_chain(uprobe, regs);
-       if (uprobe->flags & UPROBE_SKIP_SSTEP && can_skip_sstep(uprobe, regs))
-               goto cleanup_ret;
+       if (can_skip_sstep(uprobe, regs))
+               goto out;
 
-       utask->state = UTASK_SSTEP;
        if (!pre_ssout(uprobe, regs, bp_vaddr)) {
                arch_uprobe_enable_step(&uprobe->arch);
+               utask->active_uprobe = uprobe;
+               utask->state = UTASK_SSTEP;
                return;
        }
 
-cleanup_ret:
-       if (utask) {
-               utask->active_uprobe = NULL;
-               utask->state = UTASK_RUNNING;
-       }
-       if (!(uprobe->flags & UPROBE_SKIP_SSTEP))
-
-               /*
-                * cannot singlestep; cannot skip instruction;
-                * re-execute the instruction.
-                */
-               instruction_pointer_set(regs, bp_vaddr);
-
+restart:
+       /*
+        * cannot singlestep; cannot skip instruction;
+        * re-execute the instruction.
+        */
+       instruction_pointer_set(regs, bp_vaddr);
+out:
        put_uprobe(uprobe);
 }
 
@@ -1552,13 +1537,12 @@ static void handle_singlestep(struct uprobe_task *utask, struct pt_regs *regs)
 }
 
 /*
- * On breakpoint hit, breakpoint notifier sets the TIF_UPROBE flag.  (and on
- * subsequent probe hits on the thread sets the state to UTASK_BP_HIT) and
- * allows the thread to return from interrupt.
+ * On breakpoint hit, breakpoint notifier sets the TIF_UPROBE flag and
+ * allows the thread to return from interrupt. After that handle_swbp()
+ * sets utask->active_uprobe.
  *
- * On singlestep exception, singlestep notifier sets the TIF_UPROBE flag and
- * also sets the state to UTASK_SSTEP_ACK and allows the thread to return from
- * interrupt.
+ * On singlestep exception, singlestep notifier sets the TIF_UPROBE flag
+ * and allows the thread to return from interrupt.
  *
  * While returning to userspace, thread notices the TIF_UPROBE flag and calls
  * uprobe_notify_resume().
@@ -1567,11 +1551,13 @@ void uprobe_notify_resume(struct pt_regs *regs)
 {
        struct uprobe_task *utask;
 
+       clear_thread_flag(TIF_UPROBE);
+
        utask = current->utask;
-       if (!utask || utask->state == UTASK_BP_HIT)
-               handle_swbp(regs);
-       else
+       if (utask && utask->active_uprobe)
                handle_singlestep(utask, regs);
+       else
+               handle_swbp(regs);
 }
 
 /*
@@ -1580,17 +1566,10 @@ void uprobe_notify_resume(struct pt_regs *regs)
  */
 int uprobe_pre_sstep_notifier(struct pt_regs *regs)
 {
-       struct uprobe_task *utask;
-
        if (!current->mm || !test_bit(MMF_HAS_UPROBES, &current->mm->flags))
                return 0;
 
-       utask = current->utask;
-       if (utask)
-               utask->state = UTASK_BP_HIT;
-
        set_thread_flag(TIF_UPROBE);
-
        return 1;
 }
 
index 3717e7b306e08c0e8c2d3a66219c3cae13176d99..20ef219bbe9b76b3d54e6b501366f15cd97c464a 100644 (file)
@@ -716,7 +716,7 @@ static int futex_lock_pi_atomic(u32 __user *uaddr, struct futex_hash_bucket *hb,
                                struct futex_pi_state **ps,
                                struct task_struct *task, int set_waiters)
 {
-       int lock_taken, ret, ownerdied = 0;
+       int lock_taken, ret, force_take = 0;
        u32 uval, newval, curval, vpid = task_pid_vnr(task);
 
 retry:
@@ -755,17 +755,15 @@ retry:
        newval = curval | FUTEX_WAITERS;
 
        /*
-        * There are two cases, where a futex might have no owner (the
-        * owner TID is 0): OWNER_DIED. We take over the futex in this
-        * case. We also do an unconditional take over, when the owner
-        * of the futex died.
-        *
-        * This is safe as we are protected by the hash bucket lock !
+        * Should we force take the futex? See below.
         */
-       if (unlikely(ownerdied || !(curval & FUTEX_TID_MASK))) {
-               /* Keep the OWNER_DIED bit */
+       if (unlikely(force_take)) {
+               /*
+                * Keep the OWNER_DIED and the WAITERS bit and set the
+                * new TID value.
+                */
                newval = (curval & ~FUTEX_TID_MASK) | vpid;
-               ownerdied = 0;
+               force_take = 0;
                lock_taken = 1;
        }
 
@@ -775,7 +773,7 @@ retry:
                goto retry;
 
        /*
-        * We took the lock due to owner died take over.
+        * We took the lock due to forced take over.
         */
        if (unlikely(lock_taken))
                return 1;
@@ -790,20 +788,25 @@ retry:
                switch (ret) {
                case -ESRCH:
                        /*
-                        * No owner found for this futex. Check if the
-                        * OWNER_DIED bit is set to figure out whether
-                        * this is a robust futex or not.
+                        * We failed to find an owner for this
+                        * futex. So we have no pi_state to block
+                        * on. This can happen in two cases:
+                        *
+                        * 1) The owner died
+                        * 2) A stale FUTEX_WAITERS bit
+                        *
+                        * Re-read the futex value.
                         */
                        if (get_futex_value_locked(&curval, uaddr))
                                return -EFAULT;
 
                        /*
-                        * We simply start over in case of a robust
-                        * futex. The code above will take the futex
-                        * and return happy.
+                        * If the owner died or we have a stale
+                        * WAITERS bit the owner TID in the user space
+                        * futex is 0.
                         */
-                       if (curval & FUTEX_OWNER_DIED) {
-                               ownerdied = 1;
+                       if (!(curval & FUTEX_TID_MASK)) {
+                               force_take = 1;
                                goto retry;
                        }
                default:
index 6085f5ef88eaf1fd95159f3db724b16cf43b54d3..6e48c3a43599b6f5d5ce074ec2fbbf8778680ee4 100644 (file)
@@ -2293,12 +2293,17 @@ static void layout_symtab(struct module *mod, struct load_info *info)
        src = (void *)info->hdr + symsect->sh_offset;
        nsrc = symsect->sh_size / sizeof(*src);
 
+       /* strtab always starts with a nul, so offset 0 is the empty string. */
+       strtab_size = 1;
+
        /* Compute total space required for the core symbols' strtab. */
-       for (ndst = i = strtab_size = 1; i < nsrc; ++i, ++src)
-               if (is_core_symbol(src, info->sechdrs, info->hdr->e_shnum)) {
-                       strtab_size += strlen(&info->strtab[src->st_name]) + 1;
+       for (ndst = i = 0; i < nsrc; i++) {
+               if (i == 0 ||
+                   is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum)) {
+                       strtab_size += strlen(&info->strtab[src[i].st_name])+1;
                        ndst++;
                }
+       }
 
        /* Append room for core symbols at end of core part. */
        info->symoffs = ALIGN(mod->core_size, symsect->sh_addralign ?: 1);
@@ -2332,15 +2337,15 @@ static void add_kallsyms(struct module *mod, const struct load_info *info)
        mod->core_symtab = dst = mod->module_core + info->symoffs;
        mod->core_strtab = s = mod->module_core + info->stroffs;
        src = mod->symtab;
-       *dst = *src;
        *s++ = 0;
-       for (ndst = i = 1; i < mod->num_symtab; ++i, ++src) {
-               if (!is_core_symbol(src, info->sechdrs, info->hdr->e_shnum))
-                       continue;
-
-               dst[ndst] = *src;
-               dst[ndst++].st_name = s - mod->core_strtab;
-               s += strlcpy(s, &mod->strtab[src->st_name], KSYM_NAME_LEN) + 1;
+       for (ndst = i = 0; i < mod->num_symtab; i++) {
+               if (i == 0 ||
+                   is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum)) {
+                       dst[ndst] = src[i];
+                       dst[ndst++].st_name = s - mod->core_strtab;
+                       s += strlcpy(s, &mod->strtab[src[i].st_name],
+                                    KSYM_NAME_LEN) + 1;
+               }
        }
        mod->core_num_syms = ndst;
 }
index d492a23df99c8a4fa99527b89c1223941229cb41..ea1b1df5dbb0077a167caaf8e013b8baf765e902 100644 (file)
@@ -192,7 +192,7 @@ int mod_verify_sig(const void *mod, unsigned long *_modlen)
        size_t modlen = *_modlen, sig_len;
        int ret;
 
-       pr_devel("==>%s(,%lu)\n", __func__, modlen);
+       pr_devel("==>%s(,%zu)\n", __func__, modlen);
 
        if (modlen <= sizeof(ms))
                return -EBADMSG;
index eb00be205811959c708fe2bf5e3aee0547dcfa36..7b07cc0dfb75fb6b2f2f802178abf82565d9c1a4 100644 (file)
@@ -71,12 +71,22 @@ err_alloc:
        return NULL;
 }
 
+/* MAX_PID_NS_LEVEL is needed for limiting size of 'struct pid' */
+#define MAX_PID_NS_LEVEL 32
+
 static struct pid_namespace *create_pid_namespace(struct pid_namespace *parent_pid_ns)
 {
        struct pid_namespace *ns;
        unsigned int level = parent_pid_ns->level + 1;
-       int i, err = -ENOMEM;
+       int i;
+       int err;
+
+       if (level > MAX_PID_NS_LEVEL) {
+               err = -EINVAL;
+               goto out;
+       }
 
+       err = -ENOMEM;
        ns = kmem_cache_zalloc(pid_ns_cachep, GFP_KERNEL);
        if (ns == NULL)
                goto out;
index b32ed0e385a59b40b971bd04e0e374d333992749..b979426d16c6efc48e743b6a9df48a78bcaa9f4b 100644 (file)
@@ -1567,6 +1567,10 @@ int ring_buffer_resize(struct ring_buffer *buffer, unsigned long size,
 
                put_online_cpus();
        } else {
+               /* Make sure this CPU has been intitialized */
+               if (!cpumask_test_cpu(cpu_id, buffer->cpumask))
+                       goto out;
+
                cpu_buffer = buffer->buffers[cpu_id];
 
                if (nr_pages == cpu_buffer->nr_pages)
index d951daa0ca9a81b21f6b1387b140f537b53c27c1..042d221d33cc1675fadf7ee291e86717f2c8f6c9 100644 (file)
@@ -2982,7 +2982,7 @@ bool cancel_delayed_work(struct delayed_work *dwork)
 
        set_work_cpu_and_clear_pending(&dwork->work, work_cpu(&dwork->work));
        local_irq_restore(flags);
-       return true;
+       return ret;
 }
 EXPORT_SYMBOL(cancel_delayed_work);
 
index ca208a92628c1b49a6f5c1fece1a81592a65ecaa..54920433705adbff385b319574a9f04b50d8ca77 100644 (file)
@@ -178,7 +178,7 @@ int gen_pool_add_virt(struct gen_pool *pool, unsigned long virt, phys_addr_t phy
        struct gen_pool_chunk *chunk;
        int nbits = size >> pool->min_alloc_order;
        int nbytes = sizeof(struct gen_pool_chunk) +
-                               (nbits + BITS_PER_BYTE - 1) / BITS_PER_BYTE;
+                               BITS_TO_LONGS(nbits) * sizeof(long);
 
        chunk = kmalloc_node(nbytes, GFP_KERNEL | __GFP_ZERO, nid);
        if (unlikely(chunk == NULL))
index 678ce4f1e124b4be4c255f297cef1e29477e7ce0..095ab157a5215a800d01585bbb50b0d6b6a88a17 100644 (file)
@@ -641,7 +641,14 @@ do { \
        **************  MIPS  *****************
        ***************************************/
 #if defined(__mips__) && W_TYPE_SIZE == 32
-#if __GNUC__ > 2 || __GNUC_MINOR__ >= 7
+#if __GNUC__ >= 4 && __GNUC_MINOR__ >= 4
+#define umul_ppmm(w1, w0, u, v)                        \
+do {                                           \
+       UDItype __ll = (UDItype)(u) * (v);      \
+       w1 = __ll >> 32;                        \
+       w0 = __ll;                              \
+} while (0)
+#elif __GNUC__ > 2 || __GNUC_MINOR__ >= 7
 #define umul_ppmm(w1, w0, u, v) \
        __asm__ ("multu %2,%3" \
        : "=l" ((USItype)(w0)), \
@@ -666,7 +673,15 @@ do { \
        **************  MIPS/64  **************
        ***************************************/
 #if (defined(__mips) && __mips >= 3) && W_TYPE_SIZE == 64
-#if __GNUC__ > 2 || __GNUC_MINOR__ >= 7
+#if __GNUC__ >= 4 && __GNUC_MINOR__ >= 4
+#define umul_ppmm(w1, w0, u, v) \
+do {                                                                   \
+       typedef unsigned int __ll_UTItype __attribute__((mode(TI)));    \
+       __ll_UTItype __ll = (__ll_UTItype)(u) * (v);                    \
+       w1 = __ll >> 64;                                                \
+       w0 = __ll;                                                      \
+} while (0)
+#elif __GNUC__ > 2 || __GNUC_MINOR__ >= 7
 #define umul_ppmm(w1, w0, u, v) \
        __asm__ ("dmultu %2,%3" \
        : "=l" ((UDItype)(w0)), \
index 434be4ae7a0495817267e5e100c68f47c2006415..f468185b3b28a517aaceb79b80e7f799df0dfc6f 100644 (file)
@@ -198,8 +198,6 @@ static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata)
                        int order = ilog2(BITS_PER_LONG);
 
                        __free_pages_bootmem(pfn_to_page(start), order);
-                       fixup_zone_present_pages(page_to_nid(pfn_to_page(start)),
-                                       start, start + BITS_PER_LONG);
                        count += BITS_PER_LONG;
                        start += BITS_PER_LONG;
                } else {
@@ -210,9 +208,6 @@ static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata)
                                if (vec & 1) {
                                        page = pfn_to_page(start + off);
                                        __free_pages_bootmem(page, 0);
-                                       fixup_zone_present_pages(
-                                               page_to_nid(page),
-                                               start + off, start + off + 1);
                                        count++;
                                }
                                vec >>= 1;
@@ -226,11 +221,8 @@ static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata)
        pages = bdata->node_low_pfn - bdata->node_min_pfn;
        pages = bootmem_bootmap_pages(pages);
        count += pages;
-       while (pages--) {
-               fixup_zone_present_pages(page_to_nid(page),
-                               page_to_pfn(page), page_to_pfn(page) + 1);
+       while (pages--)
                __free_pages_bootmem(page++, 0);
-       }
 
        bdebug("nid=%td released=%lx\n", bdata - bootmem_node_data, count);
 
index d517cd16a6eb91e8df18f3cbd79cd67621b27d3f..2da13a5c50e2b48e8fe8dea34d4bd4835c127da9 100644 (file)
@@ -98,7 +98,7 @@ struct page *kmap_to_page(void *vaddr)
 {
        unsigned long addr = (unsigned long)vaddr;
 
-       if (addr >= PKMAP_ADDR(0) && addr <= PKMAP_ADDR(LAST_PKMAP)) {
+       if (addr >= PKMAP_ADDR(0) && addr < PKMAP_ADDR(LAST_PKMAP)) {
                int i = (addr - PKMAP_ADDR(0)) >> PAGE_SHIFT;
                return pte_page(pkmap_page_table[i]);
        }
index 931eef145af5eed370ed6f2b0c9dc577295be6ff..625905523c2a1592f539c46f6721723d62376648 100644 (file)
@@ -930,6 +930,30 @@ int __init_memblock memblock_is_region_reserved(phys_addr_t base, phys_addr_t si
        return memblock_overlaps_region(&memblock.reserved, base, size) >= 0;
 }
 
+void __init_memblock memblock_trim_memory(phys_addr_t align)
+{
+       int i;
+       phys_addr_t start, end, orig_start, orig_end;
+       struct memblock_type *mem = &memblock.memory;
+
+       for (i = 0; i < mem->cnt; i++) {
+               orig_start = mem->regions[i].base;
+               orig_end = mem->regions[i].base + mem->regions[i].size;
+               start = round_up(orig_start, align);
+               end = round_down(orig_end, align);
+
+               if (start == orig_start && end == orig_end)
+                       continue;
+
+               if (start < end) {
+                       mem->regions[i].base = start;
+                       mem->regions[i].size = end - start;
+               } else {
+                       memblock_remove_region(mem, i);
+                       i--;
+               }
+       }
+}
 
 void __init_memblock memblock_set_current_limit(phys_addr_t limit)
 {
index 7acf43bf04a270cf2bf90f342c66142d1c5cf675..dd39ba000b31f98730c6fd6d22bdf695ced3bedf 100644 (file)
@@ -1055,12 +1055,24 @@ struct lruvec *mem_cgroup_zone_lruvec(struct zone *zone,
                                      struct mem_cgroup *memcg)
 {
        struct mem_cgroup_per_zone *mz;
+       struct lruvec *lruvec;
 
-       if (mem_cgroup_disabled())
-               return &zone->lruvec;
+       if (mem_cgroup_disabled()) {
+               lruvec = &zone->lruvec;
+               goto out;
+       }
 
        mz = mem_cgroup_zoneinfo(memcg, zone_to_nid(zone), zone_idx(zone));
-       return &mz->lruvec;
+       lruvec = &mz->lruvec;
+out:
+       /*
+        * Since a node can be onlined after the mem_cgroup was created,
+        * we have to be prepared to initialize lruvec->zone here;
+        * and if offlined then reonlined, we need to reinitialize it.
+        */
+       if (unlikely(lruvec->zone != zone))
+               lruvec->zone = zone;
+       return lruvec;
 }
 
 /*
@@ -1087,9 +1099,12 @@ struct lruvec *mem_cgroup_page_lruvec(struct page *page, struct zone *zone)
        struct mem_cgroup_per_zone *mz;
        struct mem_cgroup *memcg;
        struct page_cgroup *pc;
+       struct lruvec *lruvec;
 
-       if (mem_cgroup_disabled())
-               return &zone->lruvec;
+       if (mem_cgroup_disabled()) {
+               lruvec = &zone->lruvec;
+               goto out;
+       }
 
        pc = lookup_page_cgroup(page);
        memcg = pc->mem_cgroup;
@@ -1107,7 +1122,16 @@ struct lruvec *mem_cgroup_page_lruvec(struct page *page, struct zone *zone)
                pc->mem_cgroup = memcg = root_mem_cgroup;
 
        mz = page_cgroup_zoneinfo(memcg, page);
-       return &mz->lruvec;
+       lruvec = &mz->lruvec;
+out:
+       /*
+        * Since a node can be onlined after the mem_cgroup was created,
+        * we have to be prepared to initialize lruvec->zone here;
+        * and if offlined then reonlined, we need to reinitialize it.
+        */
+       if (unlikely(lruvec->zone != zone))
+               lruvec->zone = zone;
+       return lruvec;
 }
 
 /**
@@ -1452,17 +1476,26 @@ static int mem_cgroup_count_children(struct mem_cgroup *memcg)
 static u64 mem_cgroup_get_limit(struct mem_cgroup *memcg)
 {
        u64 limit;
-       u64 memsw;
 
        limit = res_counter_read_u64(&memcg->res, RES_LIMIT);
-       limit += total_swap_pages << PAGE_SHIFT;
 
-       memsw = res_counter_read_u64(&memcg->memsw, RES_LIMIT);
        /*
-        * If memsw is finite and limits the amount of swap space available
-        * to this memcg, return that limit.
+        * Do not consider swap space if we cannot swap due to swappiness
         */
-       return min(limit, memsw);
+       if (mem_cgroup_swappiness(memcg)) {
+               u64 memsw;
+
+               limit += total_swap_pages << PAGE_SHIFT;
+               memsw = res_counter_read_u64(&memcg->memsw, RES_LIMIT);
+
+               /*
+                * If memsw is finite and limits the amount of swap space
+                * available to this memcg, return that limit.
+                */
+               limit = min(limit, memsw);
+       }
+
+       return limit;
 }
 
 void mem_cgroup_out_of_memory(struct mem_cgroup *memcg, gfp_t gfp_mask,
@@ -3688,17 +3721,17 @@ unsigned long mem_cgroup_soft_limit_reclaim(struct zone *zone, int order,
 static bool mem_cgroup_force_empty_list(struct mem_cgroup *memcg,
                                int node, int zid, enum lru_list lru)
 {
-       struct mem_cgroup_per_zone *mz;
+       struct lruvec *lruvec;
        unsigned long flags, loop;
        struct list_head *list;
        struct page *busy;
        struct zone *zone;
 
        zone = &NODE_DATA(node)->node_zones[zid];
-       mz = mem_cgroup_zoneinfo(memcg, node, zid);
-       list = &mz->lruvec.lists[lru];
+       lruvec = mem_cgroup_zone_lruvec(zone, memcg);
+       list = &lruvec->lists[lru];
 
-       loop = mz->lru_size[lru];
+       loop = mem_cgroup_get_lru_size(lruvec, lru);
        /* give some margin against EBUSY etc...*/
        loop += 256;
        busy = NULL;
@@ -4736,7 +4769,7 @@ static int alloc_mem_cgroup_per_zone_info(struct mem_cgroup *memcg, int node)
 
        for (zone = 0; zone < MAX_NR_ZONES; zone++) {
                mz = &pn->zoneinfo[zone];
-               lruvec_init(&mz->lruvec, &NODE_DATA(node)->node_zones[zone]);
+               lruvec_init(&mz->lruvec);
                mz->usage_in_excess = 0;
                mz->on_tree = false;
                mz->memcg = memcg;
index fb135ba4aba90349e58c79d49838860cb7db8105..221fc9ffcab1da33eb15947776975730b5058b67 100644 (file)
@@ -2527,9 +2527,8 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma,
        int ret = 0;
        int page_mkwrite = 0;
        struct page *dirty_page = NULL;
-       unsigned long mmun_start;       /* For mmu_notifiers */
-       unsigned long mmun_end;         /* For mmu_notifiers */
-       bool mmun_called = false;       /* For mmu_notifiers */
+       unsigned long mmun_start = 0;   /* For mmu_notifiers */
+       unsigned long mmun_end = 0;     /* For mmu_notifiers */
 
        old_page = vm_normal_page(vma, address, orig_pte);
        if (!old_page) {
@@ -2708,8 +2707,7 @@ gotten:
                goto oom_free_new;
 
        mmun_start  = address & PAGE_MASK;
-       mmun_end    = (address & PAGE_MASK) + PAGE_SIZE;
-       mmun_called = true;
+       mmun_end    = mmun_start + PAGE_SIZE;
        mmu_notifier_invalidate_range_start(mm, mmun_start, mmun_end);
 
        /*
@@ -2778,7 +2776,7 @@ gotten:
                page_cache_release(new_page);
 unlock:
        pte_unmap_unlock(page_table, ptl);
-       if (mmun_called)
+       if (mmun_end > mmun_start)
                mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end);
        if (old_page) {
                /*
index 56b758ae57d2eeb2230bbcaf3f8e8d4538a15a9d..e4eeacae2b91199142776390bdaef73241416b47 100644 (file)
@@ -106,7 +106,6 @@ static void get_page_bootmem(unsigned long info,  struct page *page,
 void __ref put_page_bootmem(struct page *page)
 {
        unsigned long type;
-       struct zone *zone;
 
        type = (unsigned long) page->lru.next;
        BUG_ON(type < MEMORY_HOTPLUG_MIN_BOOTMEM_TYPE ||
@@ -117,12 +116,6 @@ void __ref put_page_bootmem(struct page *page)
                set_page_private(page, 0);
                INIT_LIST_HEAD(&page->lru);
                __free_pages_bootmem(page, 0);
-
-               zone = page_zone(page);
-               zone_span_writelock(zone);
-               zone->present_pages++;
-               zone_span_writeunlock(zone);
-               totalram_pages++;
        }
 
 }
index 2d942353d681a8b4f08155eebdcfb20b088093e7..9a796c41e7d9ecf8d474089df2d1b2235451ce3c 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -334,8 +334,10 @@ void validate_mm(struct mm_struct *mm)
        struct vm_area_struct *vma = mm->mmap;
        while (vma) {
                struct anon_vma_chain *avc;
+               vma_lock_anon_vma(vma);
                list_for_each_entry(avc, &vma->anon_vma_chain, same_vma)
                        anon_vma_interval_tree_verify(avc);
+               vma_unlock_anon_vma(vma);
                vma = vma->vm_next;
                i++;
        }
index 479a1e751a73fb4781e1b856db60b2381909c9e6..8a5ac8c686b03480fae7d5b193a5c714c7c2397b 100644 (file)
@@ -196,28 +196,28 @@ static int do_mmu_notifier_register(struct mmu_notifier *mn,
        BUG_ON(atomic_read(&mm->mm_users) <= 0);
 
        /*
-       * Verify that mmu_notifier_init() already run and the global srcu is
-       * initialized.
-       */
+        * Verify that mmu_notifier_init() already run and the global srcu is
+        * initialized.
+        */
        BUG_ON(!srcu.per_cpu_ref);
 
+       ret = -ENOMEM;
+       mmu_notifier_mm = kmalloc(sizeof(struct mmu_notifier_mm), GFP_KERNEL);
+       if (unlikely(!mmu_notifier_mm))
+               goto out;
+
        if (take_mmap_sem)
                down_write(&mm->mmap_sem);
        ret = mm_take_all_locks(mm);
        if (unlikely(ret))
-               goto out;
+               goto out_clean;
 
        if (!mm_has_notifiers(mm)) {
-               mmu_notifier_mm = kmalloc(sizeof(struct mmu_notifier_mm),
-                                       GFP_KERNEL);
-               if (unlikely(!mmu_notifier_mm)) {
-                       ret = -ENOMEM;
-                       goto out_of_mem;
-               }
                INIT_HLIST_HEAD(&mmu_notifier_mm->list);
                spin_lock_init(&mmu_notifier_mm->lock);
 
                mm->mmu_notifier_mm = mmu_notifier_mm;
+               mmu_notifier_mm = NULL;
        }
        atomic_inc(&mm->mm_count);
 
@@ -233,12 +233,12 @@ static int do_mmu_notifier_register(struct mmu_notifier *mn,
        hlist_add_head(&mn->hlist, &mm->mmu_notifier_mm->list);
        spin_unlock(&mm->mmu_notifier_mm->lock);
 
-out_of_mem:
        mm_drop_all_locks(mm);
-out:
+out_clean:
        if (take_mmap_sem)
                up_write(&mm->mmap_sem);
-
+       kfree(mmu_notifier_mm);
+out:
        BUG_ON(atomic_read(&mm->mm_users) <= 0);
        return ret;
 }
index 3cef80f6ac79ff2e8b5fef7bcd373679e91df2c1..4596d81b89b16280b4768e83df3290d674aaf005 100644 (file)
@@ -87,7 +87,7 @@ int memmap_valid_within(unsigned long pfn,
 }
 #endif /* CONFIG_ARCH_HAS_HOLES_MEMORYMODEL */
 
-void lruvec_init(struct lruvec *lruvec, struct zone *zone)
+void lruvec_init(struct lruvec *lruvec)
 {
        enum lru_list lru;
 
@@ -95,8 +95,4 @@ void lruvec_init(struct lruvec *lruvec, struct zone *zone)
 
        for_each_lru(lru)
                INIT_LIST_HEAD(&lruvec->lists[lru]);
-
-#ifdef CONFIG_MEMCG
-       lruvec->zone = zone;
-#endif
 }
index 714d5d6504708c83c64365618749a84b1da4cd66..bd82f6b314114dc937bea707a70072b299860a08 100644 (file)
@@ -116,8 +116,6 @@ static unsigned long __init __free_memory_core(phys_addr_t start,
                return 0;
 
        __free_pages_memory(start_pfn, end_pfn);
-       fixup_zone_present_pages(pfn_to_nid(start >> PAGE_SHIFT),
-                       start_pfn, end_pfn);
 
        return end_pfn - start_pfn;
 }
@@ -128,7 +126,6 @@ unsigned long __init free_low_memory_core_early(int nodeid)
        phys_addr_t start, end, size;
        u64 i;
 
-       reset_zone_present_pages();
        for_each_free_mem_range(i, MAX_NUMNODES, &start, &end, NULL)
                count += __free_memory_core(start, end);
 
index bb90971182bd8c833e40f508e3c8b8677d6913c8..bcb72c6e2b2d8b5ec498c5250d11a58f71e2f06a 100644 (file)
@@ -1405,7 +1405,7 @@ int capture_free_page(struct page *page, int alloc_order, int migratetype)
 
        mt = get_pageblock_migratetype(page);
        if (unlikely(mt != MIGRATE_ISOLATE))
-               __mod_zone_freepage_state(zone, -(1UL << order), mt);
+               __mod_zone_freepage_state(zone, -(1UL << alloc_order), mt);
 
        if (alloc_order != order)
                expand(zone, page, alloc_order, order,
@@ -1809,10 +1809,10 @@ static void __paginginit init_zone_allows_reclaim(int nid)
        int i;
 
        for_each_online_node(i)
-               if (node_distance(nid, i) <= RECLAIM_DISTANCE) {
+               if (node_distance(nid, i) <= RECLAIM_DISTANCE)
                        node_set(i, NODE_DATA(nid)->reclaim_nodes);
+               else
                        zone_reclaim_mode = 1;
-               }
 }
 
 #else  /* CONFIG_NUMA */
@@ -4505,7 +4505,7 @@ static void __paginginit free_area_init_core(struct pglist_data *pgdat,
                zone->zone_pgdat = pgdat;
 
                zone_pcp_init(zone);
-               lruvec_init(&zone->lruvec, zone);
+               lruvec_init(&zone->lruvec);
                if (!size)
                        continue;
 
@@ -5825,7 +5825,7 @@ int alloc_contig_range(unsigned long start, unsigned long end,
        ret = start_isolate_page_range(pfn_max_align_down(start),
                                       pfn_max_align_up(end), migratetype);
        if (ret)
-               goto done;
+               return ret;
 
        ret = __alloc_contig_migrate_range(&cc, start, end);
        if (ret)
@@ -6098,37 +6098,3 @@ void dump_page(struct page *page)
        dump_page_flags(page->flags);
        mem_cgroup_print_bad_page(page);
 }
-
-/* reset zone->present_pages */
-void reset_zone_present_pages(void)
-{
-       struct zone *z;
-       int i, nid;
-
-       for_each_node_state(nid, N_HIGH_MEMORY) {
-               for (i = 0; i < MAX_NR_ZONES; i++) {
-                       z = NODE_DATA(nid)->node_zones + i;
-                       z->present_pages = 0;
-               }
-       }
-}
-
-/* calculate zone's present pages in buddy system */
-void fixup_zone_present_pages(int nid, unsigned long start_pfn,
-                               unsigned long end_pfn)
-{
-       struct zone *z;
-       unsigned long zone_start_pfn, zone_end_pfn;
-       int i;
-
-       for (i = 0; i < MAX_NR_ZONES; i++) {
-               z = NODE_DATA(nid)->node_zones + i;
-               zone_start_pfn = z->zone_start_pfn;
-               zone_end_pfn = zone_start_pfn + z->spanned_pages;
-
-               /* if the two regions intersect */
-               if (!(zone_start_pfn >= end_pfn || zone_end_pfn <= start_pfn))
-                       z->present_pages += min(end_pfn, zone_end_pfn) -
-                                           max(start_pfn, zone_start_pfn);
-       }
-}
index 7df7984d476c8661b900725c0e2c3f33c883a32d..2ee1ef0f317b7487bfb21b7a6717b1e12d1f7ef4 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -56,6 +56,7 @@
 #include <linux/mmu_notifier.h>
 #include <linux/migrate.h>
 #include <linux/hugetlb.h>
+#include <linux/backing-dev.h>
 
 #include <asm/tlbflush.h>
 
@@ -926,11 +927,8 @@ int page_mkclean(struct page *page)
 
        if (page_mapped(page)) {
                struct address_space *mapping = page_mapping(page);
-               if (mapping) {
+               if (mapping)
                        ret = page_mkclean_file(mapping, page);
-                       if (page_test_and_clear_dirty(page_to_pfn(page), 1))
-                               ret = 1;
-               }
        }
 
        return ret;
@@ -1116,6 +1114,7 @@ void page_add_file_rmap(struct page *page)
  */
 void page_remove_rmap(struct page *page)
 {
+       struct address_space *mapping = page_mapping(page);
        bool anon = PageAnon(page);
        bool locked;
        unsigned long flags;
@@ -1138,8 +1137,19 @@ void page_remove_rmap(struct page *page)
         * this if the page is anon, so about to be freed; but perhaps
         * not if it's in swapcache - there might be another pte slot
         * containing the swap entry, but page not yet written to swap.
+        *
+        * And we can skip it on file pages, so long as the filesystem
+        * participates in dirty tracking; but need to catch shm and tmpfs
+        * and ramfs pages which have been modified since creation by read
+        * fault.
+        *
+        * Note that mapping must be decided above, before decrementing
+        * mapcount (which luckily provides a barrier): once page is unmapped,
+        * it could be truncated and page->mapping reset to NULL at any moment.
+        * Note also that we are relying on page_mapping(page) to set mapping
+        * to &swapper_space when PageSwapCache(page).
         */
-       if ((!anon || PageSwapCache(page)) &&
+       if (mapping && !mapping_cap_account_dirty(mapping) &&
            page_test_and_clear_dirty(page_to_pfn(page), 1))
                set_page_dirty(page);
        /*
index 67afba5117f2ebe80ef54e487d068fdf99e986bb..89341b658bd06b05d908f8becfef7fe0d904b808 100644 (file)
@@ -643,7 +643,7 @@ static void shmem_evict_inode(struct inode *inode)
                kfree(info->symlink);
 
        simple_xattrs_free(&info->xattrs);
-       BUG_ON(inode->i_blocks);
+       WARN_ON(inode->i_blocks);
        shmem_free_inode(inode->i_sb);
        clear_inode(inode);
 }
@@ -1145,8 +1145,20 @@ repeat:
                if (!error) {
                        error = shmem_add_to_page_cache(page, mapping, index,
                                                gfp, swp_to_radix_entry(swap));
-                       /* We already confirmed swap, and make no allocation */
-                       VM_BUG_ON(error);
+                       /*
+                        * We already confirmed swap under page lock, and make
+                        * no memory allocation here, so usually no possibility
+                        * of error; but free_swap_and_cache() only trylocks a
+                        * page, so it is just possible that the entry has been
+                        * truncated or holepunched since swap was confirmed.
+                        * shmem_undo_range() will have done some of the
+                        * unaccounting, now delete_from_swap_cache() will do
+                        * the rest (including mem_cgroup_uncharge_swapcache).
+                        * Reset swap.val? No, leave it so "failed" goes back to
+                        * "repeat": reading a hole and writing should succeed.
+                        */
+                       if (error)
+                               delete_from_swap_cache(page);
                }
                if (error)
                        goto failed;
index 71cd288b200179d4962222337f3947342fcebe57..f91a25547ffe1f2febdfb0a526ee296996da171b 100644 (file)
@@ -1494,9 +1494,8 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
        BUG_ON(!current->mm);
 
        pathname = getname(specialfile);
-       err = PTR_ERR(pathname);
        if (IS_ERR(pathname))
-               goto out;
+               return PTR_ERR(pathname);
 
        victim = file_open_name(pathname, O_RDWR|O_LARGEFILE, 0);
        err = PTR_ERR(victim);
@@ -1608,6 +1607,7 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
 out_dput:
        filp_close(victim, NULL);
 out:
+       putname(pathname);
        return err;
 }
 
index 2624edcfb42095d6e91ae79c7ca30e0e4838a0fd..48550c66f1f21d4fdff9afd38f6c1fa97f56ef49 100644 (file)
@@ -1760,28 +1760,6 @@ static bool in_reclaim_compaction(struct scan_control *sc)
        return false;
 }
 
-#ifdef CONFIG_COMPACTION
-/*
- * If compaction is deferred for sc->order then scale the number of pages
- * reclaimed based on the number of consecutive allocation failures
- */
-static unsigned long scale_for_compaction(unsigned long pages_for_compaction,
-                       struct lruvec *lruvec, struct scan_control *sc)
-{
-       struct zone *zone = lruvec_zone(lruvec);
-
-       if (zone->compact_order_failed <= sc->order)
-               pages_for_compaction <<= zone->compact_defer_shift;
-       return pages_for_compaction;
-}
-#else
-static unsigned long scale_for_compaction(unsigned long pages_for_compaction,
-                       struct lruvec *lruvec, struct scan_control *sc)
-{
-       return pages_for_compaction;
-}
-#endif
-
 /*
  * Reclaim/compaction is used for high-order allocation requests. It reclaims
  * order-0 pages before compacting the zone. should_continue_reclaim() returns
@@ -1829,9 +1807,6 @@ static inline bool should_continue_reclaim(struct lruvec *lruvec,
         * inactive lists are large enough, continue reclaiming
         */
        pages_for_compaction = (2UL << sc->order);
-
-       pages_for_compaction = scale_for_compaction(pages_for_compaction,
-                                                   lruvec, sc);
        inactive_lru_pages = get_lru_size(lruvec, LRU_INACTIVE_FILE);
        if (nr_swap_pages > 0)
                inactive_lru_pages += get_lru_size(lruvec, LRU_INACTIVE_ANON);
@@ -3017,6 +2992,8 @@ static int kswapd(void *p)
                                                &balanced_classzone_idx);
                }
        }
+
+       current->reclaim_state = NULL;
        return 0;
 }
 
index 9096bcb081326c92bb64b6dedb11033073998ca5..ee070722a3a36f1916b385e8872ea505105d06bb 100644 (file)
@@ -463,7 +463,9 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
 
        case NETDEV_PRE_TYPE_CHANGE:
                /* Forbid underlaying device to change its type. */
-               return NOTIFY_BAD;
+               if (vlan_uses_dev(dev))
+                       return NOTIFY_BAD;
+               break;
 
        case NETDEV_NOTIFY_PEERS:
        case NETDEV_BONDING_FAILOVER:
index 0a9084ad19a60f71a2f9f70a8879e7ada24ccf6c..fd8d5afec0ddb372d514367df3a6a81996eeac49 100644 (file)
@@ -1167,6 +1167,8 @@ int batadv_bla_init(struct batadv_priv *bat_priv)
        uint16_t crc;
        unsigned long entrytime;
 
+       spin_lock_init(&bat_priv->bla.bcast_duplist_lock);
+
        batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla hash registering\n");
 
        /* setting claim destination address */
@@ -1210,8 +1212,8 @@ int batadv_bla_init(struct batadv_priv *bat_priv)
 /**
  * batadv_bla_check_bcast_duplist
  * @bat_priv: the bat priv with all the soft interface information
- * @bcast_packet: originator mac address
- * @hdr_size: maximum length of the frame
+ * @bcast_packet: encapsulated broadcast frame plus batman header
+ * @bcast_packet_len: length of encapsulated broadcast frame plus batman header
  *
  * check if it is on our broadcast list. Another gateway might
  * have sent the same packet because it is connected to the same backbone,
@@ -1224,20 +1226,22 @@ int batadv_bla_init(struct batadv_priv *bat_priv)
  */
 int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
                                   struct batadv_bcast_packet *bcast_packet,
-                                  int hdr_size)
+                                  int bcast_packet_len)
 {
-       int i, length, curr;
+       int i, length, curr, ret = 0;
        uint8_t *content;
        uint16_t crc;
        struct batadv_bcast_duplist_entry *entry;
 
-       length = hdr_size - sizeof(*bcast_packet);
+       length = bcast_packet_len - sizeof(*bcast_packet);
        content = (uint8_t *)bcast_packet;
        content += sizeof(*bcast_packet);
 
        /* calculate the crc ... */
        crc = crc16(0, content, length);
 
+       spin_lock_bh(&bat_priv->bla.bcast_duplist_lock);
+
        for (i = 0; i < BATADV_DUPLIST_SIZE; i++) {
                curr = (bat_priv->bla.bcast_duplist_curr + i);
                curr %= BATADV_DUPLIST_SIZE;
@@ -1259,9 +1263,12 @@ int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
                /* this entry seems to match: same crc, not too old,
                 * and from another gw. therefore return 1 to forbid it.
                 */
-               return 1;
+               ret = 1;
+               goto out;
        }
-       /* not found, add a new entry (overwrite the oldest entry) */
+       /* not found, add a new entry (overwrite the oldest entry)
+        * and allow it, its the first occurence.
+        */
        curr = (bat_priv->bla.bcast_duplist_curr + BATADV_DUPLIST_SIZE - 1);
        curr %= BATADV_DUPLIST_SIZE;
        entry = &bat_priv->bla.bcast_duplist[curr];
@@ -1270,8 +1277,10 @@ int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
        memcpy(entry->orig, bcast_packet->orig, ETH_ALEN);
        bat_priv->bla.bcast_duplist_curr = curr;
 
-       /* allow it, its the first occurence. */
-       return 0;
+out:
+       spin_unlock_bh(&bat_priv->bla.bcast_duplist_lock);
+
+       return ret;
 }
 
 
index 939fc01371dff0c209665b297b69ec6502887b1a..376b4cc6ca821ffb4279e2b4df81e61899be038f 100644 (file)
@@ -1124,8 +1124,14 @@ int batadv_recv_bcast_packet(struct sk_buff *skb,
 
        spin_unlock_bh(&orig_node->bcast_seqno_lock);
 
+       /* keep skb linear for crc calculation */
+       if (skb_linearize(skb) < 0)
+               goto out;
+
+       bcast_packet = (struct batadv_bcast_packet *)skb->data;
+
        /* check whether this has been sent by another originator before */
-       if (batadv_bla_check_bcast_duplist(bat_priv, bcast_packet, hdr_size))
+       if (batadv_bla_check_bcast_duplist(bat_priv, bcast_packet, skb->len))
                goto out;
 
        /* rebroadcast packet */
index b9a28d2dd3e8d907526ebd51dfedba9e993fd526..ce0684a1fc836f6713ce7cf1e1164e39b4cf0fd2 100644 (file)
@@ -325,6 +325,12 @@ void batadv_interface_rx(struct net_device *soft_iface,
 
        soft_iface->last_rx = jiffies;
 
+       /* Let the bridge loop avoidance check the packet. If will
+        * not handle it, we can safely push it up.
+        */
+       if (batadv_bla_rx(bat_priv, skb, vid, is_bcast))
+               goto out;
+
        if (orig_node)
                batadv_tt_add_temporary_global_entry(bat_priv, orig_node,
                                                     ethhdr->h_source);
@@ -332,12 +338,6 @@ void batadv_interface_rx(struct net_device *soft_iface,
        if (batadv_is_ap_isolated(bat_priv, ethhdr->h_source, ethhdr->h_dest))
                goto dropped;
 
-       /* Let the bridge loop avoidance check the packet. If will
-        * not handle it, we can safely push it up.
-        */
-       if (batadv_bla_rx(bat_priv, skb, vid, is_bcast))
-               goto out;
-
        netif_rx(skb);
        goto out;
 
index 112edd371b2f81c79f431c6e99402165405c1b10..baae71585804313ff406aad0ab7f04b0b7daa189 100644 (file)
@@ -769,6 +769,12 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv,
                 */
                tt_global_entry->common.flags &= ~BATADV_TT_CLIENT_TEMP;
 
+               /* the change can carry possible "attribute" flags like the
+                * TT_CLIENT_WIFI, therefore they have to be copied in the
+                * client entry
+                */
+               tt_global_entry->common.flags |= flags;
+
                /* If there is the BATADV_TT_CLIENT_ROAM flag set, there is only
                 * one originator left in the list and we previously received a
                 * delete + roaming change for this originator.
@@ -1496,7 +1502,7 @@ batadv_tt_response_fill_table(uint16_t tt_len, uint8_t ttvn,
 
                        memcpy(tt_change->addr, tt_common_entry->addr,
                               ETH_ALEN);
-                       tt_change->flags = BATADV_NO_FLAGS;
+                       tt_change->flags = tt_common_entry->flags;
 
                        tt_count++;
                        tt_change++;
@@ -2450,6 +2456,13 @@ bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv,
 {
        bool ret = false;
 
+       /* if the originator is a backbone node (meaning it belongs to the same
+        * LAN of this node) the temporary client must not be added because to
+        * reach such destination the node must use the LAN instead of the mesh
+        */
+       if (batadv_bla_is_backbone_gw_orig(bat_priv, orig_node->orig))
+               goto out;
+
        if (!batadv_tt_global_add(bat_priv, orig_node, addr,
                                  BATADV_TT_CLIENT_TEMP,
                                  atomic_read(&orig_node->last_ttvn)))
index 2ed82caacdca4bfa0cf429d74a7311523874b4c2..ac1e07a8045475ed9ce367d39440940f29ab0852 100644 (file)
@@ -205,6 +205,8 @@ struct batadv_priv_bla {
        struct batadv_hashtable *backbone_hash;
        struct batadv_bcast_duplist_entry bcast_duplist[BATADV_DUPLIST_SIZE];
        int bcast_duplist_curr;
+       /* protects bcast_duplist and bcast_duplist_curr */
+       spinlock_t bcast_duplist_lock;
        struct batadv_bla_claim_dst claim_dest;
        struct delayed_work work;
 };
index 8a0ce706aebd624ae7fd1c50b9670780dc4f6761..a0a2f97b9c6207a600a256415ada30d12fa88f9d 100644 (file)
@@ -1754,11 +1754,11 @@ int hci_register_dev(struct hci_dev *hdev)
        if (hdev->dev_type != HCI_AMP)
                set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
 
-       schedule_work(&hdev->power_on);
-
        hci_notify(hdev, HCI_DEV_REG);
        hci_dev_hold(hdev);
 
+       schedule_work(&hdev->power_on);
+
        return id;
 
 err_wqueue:
index aa2ea0a8142cc0d6c7378ced06be1257b2f846d7..91de4239da6621d6e5b7a2989beb5bd5b883ff8c 100644 (file)
@@ -326,7 +326,7 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
        struct hci_dev *d;
        size_t rp_len;
        u16 count;
-       int i, err;
+       int err;
 
        BT_DBG("sock %p", sk);
 
@@ -347,9 +347,7 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
                return -ENOMEM;
        }
 
-       rp->num_controllers = cpu_to_le16(count);
-
-       i = 0;
+       count = 0;
        list_for_each_entry(d, &hci_dev_list, list) {
                if (test_bit(HCI_SETUP, &d->dev_flags))
                        continue;
@@ -357,10 +355,13 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
                if (!mgmt_valid_hdev(d))
                        continue;
 
-               rp->index[i++] = cpu_to_le16(d->id);
+               rp->index[count++] = cpu_to_le16(d->id);
                BT_DBG("Added hci%u", d->id);
        }
 
+       rp->num_controllers = cpu_to_le16(count);
+       rp_len = sizeof(*rp) + (2 * count);
+
        read_unlock(&hci_dev_list_lock);
 
        err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST, 0, rp,
@@ -1366,6 +1367,7 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
                        continue;
 
                list_del(&match->list);
+               kfree(match);
                found++;
        }
 
index 8c225ef349cd733614dfeaca0f2f1bceccdae064..a5923378bdf03ab73a259cd3c74f88b890972030 100644 (file)
@@ -32,6 +32,8 @@
 
 #define SMP_TIMEOUT    msecs_to_jiffies(30000)
 
+#define AUTH_REQ_MASK   0x07
+
 static inline void swap128(u8 src[16], u8 dst[16])
 {
        int i;
@@ -230,7 +232,7 @@ static void build_pairing_cmd(struct l2cap_conn *conn,
                req->max_key_size = SMP_MAX_ENC_KEY_SIZE;
                req->init_key_dist = 0;
                req->resp_key_dist = dist_keys;
-               req->auth_req = authreq;
+               req->auth_req = (authreq & AUTH_REQ_MASK);
                return;
        }
 
@@ -239,7 +241,7 @@ static void build_pairing_cmd(struct l2cap_conn *conn,
        rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE;
        rsp->init_key_dist = 0;
        rsp->resp_key_dist = req->resp_key_dist & dist_keys;
-       rsp->auth_req = authreq;
+       rsp->auth_req = (authreq & AUTH_REQ_MASK);
 }
 
 static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size)
@@ -265,7 +267,7 @@ static void smp_failure(struct l2cap_conn *conn, u8 reason, u8 send)
 
        clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->hcon->flags);
        mgmt_auth_failed(conn->hcon->hdev, conn->dst, hcon->type,
-                        hcon->dst_type, reason);
+                        hcon->dst_type, HCI_ERROR_AUTH_FAILURE);
 
        cancel_delayed_work_sync(&conn->security_timer);
 
index 159aa8bef9e7fe2f89f9b508c39a209aa92d3c0d..3ef1759403b411fe53595e2ddf1eb6314a4f9ef8 100644 (file)
@@ -2300,10 +2300,11 @@ restart:
                        mutex_unlock(&con->mutex);
                        return;
                } else {
-                       con->ops->put(con);
                        dout("con_work %p FAILED to back off %lu\n", con,
                             con->delay);
+                       set_bit(CON_FLAG_BACKOFF, &con->flags);
                }
+               goto done;
        }
 
        if (con->state == CON_STATE_STANDBY) {
@@ -2749,7 +2750,8 @@ static int ceph_con_in_msg_alloc(struct ceph_connection *con, int *skip)
                msg = con->ops->alloc_msg(con, hdr, skip);
                mutex_lock(&con->mutex);
                if (con->state != CON_STATE_OPEN) {
-                       ceph_msg_put(msg);
+                       if (msg)
+                               ceph_msg_put(msg);
                        return -EAGAIN;
                }
                con->in_msg = msg;
index 09cb3f6dc40c4a573a9597ca851b9a91a09a1c3d..c0946cb2b3547f4fdea0fa56b8f7e17c71a75012 100644 (file)
@@ -1666,7 +1666,7 @@ static inline int deliver_skb(struct sk_buff *skb,
 
 static inline bool skb_loop_sk(struct packet_type *ptype, struct sk_buff *skb)
 {
-       if (ptype->af_packet_priv == NULL)
+       if (!ptype->af_packet_priv || !skb->sk)
                return false;
 
        if (ptype->id_match)
@@ -2818,8 +2818,10 @@ static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb,
                if (unlikely(tcpu != next_cpu) &&
                    (tcpu == RPS_NO_CPU || !cpu_online(tcpu) ||
                     ((int)(per_cpu(softnet_data, tcpu).input_queue_head -
-                     rflow->last_qtail)) >= 0))
+                     rflow->last_qtail)) >= 0)) {
+                       tcpu = next_cpu;
                        rflow = set_rps_cpu(dev, skb, rflow, next_cpu);
+               }
 
                if (tcpu != RPS_NO_CPU && cpu_online(tcpu)) {
                        *rflowp = rflow;
index 87cc17db2d566e5846601d6eb03ba38ce64b2ddb..b079c7bbc157a3c047db12e7a39595da380071e8 100644 (file)
@@ -319,7 +319,8 @@ int dev_addr_del(struct net_device *dev, const unsigned char *addr,
         */
        ha = list_first_entry(&dev->dev_addrs.list,
                              struct netdev_hw_addr, list);
-       if (ha->addr == dev->dev_addr && ha->refcount == 1)
+       if (!memcmp(ha->addr, addr, dev->addr_len) &&
+           ha->type == addr_type && ha->refcount == 1)
                return -ENOENT;
 
        err = __hw_addr_del(&dev->dev_addrs, addr, dev->addr_len,
index bcf02f608cbfa76ad06da490f2dbf423e728fc17..017a8bacfb2773483c97c8fa3b162e03f09f454a 100644 (file)
@@ -429,6 +429,17 @@ static struct attribute_group netstat_group = {
        .name  = "statistics",
        .attrs  = netstat_attrs,
 };
+
+#if IS_ENABLED(CONFIG_WIRELESS_EXT) || IS_ENABLED(CONFIG_CFG80211)
+static struct attribute *wireless_attrs[] = {
+       NULL
+};
+
+static struct attribute_group wireless_group = {
+       .name = "wireless",
+       .attrs = wireless_attrs,
+};
+#endif
 #endif /* CONFIG_SYSFS */
 
 #ifdef CONFIG_RPS
@@ -1409,6 +1420,15 @@ int netdev_register_kobject(struct net_device *net)
                groups++;
 
        *groups++ = &netstat_group;
+
+#if IS_ENABLED(CONFIG_WIRELESS_EXT) || IS_ENABLED(CONFIG_CFG80211)
+       if (net->ieee80211_ptr)
+               *groups++ = &wireless_group;
+#if IS_ENABLED(CONFIG_WIRELESS_EXT)
+       else if (net->wireless_handlers)
+               *groups++ = &wireless_group;
+#endif
+#endif
 #endif /* CONFIG_SYSFS */
 
        error = device_add(dev);
index 76d4c2c3c89b9d170e89c39fbf0ed5729621a0bc..fad649ae4decbf393c52b614dc8be0aef07e0750 100644 (file)
@@ -2192,7 +2192,8 @@ static int nlmsg_populate_fdb(struct sk_buff *skb,
                        goto skip;
 
                err = nlmsg_populate_fdb_fill(skb, dev, ha->addr,
-                                             portid, seq, 0, NTF_SELF);
+                                             portid, seq,
+                                             RTM_NEWNEIGH, NTF_SELF);
                if (err < 0)
                        return err;
 skip:
index 6e04b1fa11f2d4c6d0e0aacb27441688c5fe1438..4007c1437fdaf615bbf197ad52e545529e7bce59 100644 (file)
@@ -3379,10 +3379,12 @@ EXPORT_SYMBOL(__skb_warn_lro_forwarding);
 
 void kfree_skb_partial(struct sk_buff *skb, bool head_stolen)
 {
-       if (head_stolen)
+       if (head_stolen) {
+               skb_release_head_state(skb);
                kmem_cache_free(skbuff_head_cache, skb);
-       else
+       } else {
                __kfree_skb(skb);
+       }
 }
 EXPORT_SYMBOL(kfree_skb_partial);
 
index 535584c00f9118fe33a17e79b858e66935f424f9..0c34bfabc11fc8bcb8056a67abf0feb0b652154f 100644 (file)
@@ -892,13 +892,16 @@ static int __inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb,
                struct inet_diag_req_v2 *r, struct nlattr *bc)
 {
        const struct inet_diag_handler *handler;
+       int err = 0;
 
        handler = inet_diag_lock_handler(r->sdiag_protocol);
        if (!IS_ERR(handler))
                handler->dump(skb, cb, r, bc);
+       else
+               err = PTR_ERR(handler);
        inet_diag_unlock_handler(handler);
 
-       return skb->len;
+       return err ? : skb->len;
 }
 
 static int inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb)
index 5eea4a811042adaf3df8e65308c2aeeb23c845e9..14bbfcf717acb9d02df641231cdf30a611a43810 100644 (file)
@@ -457,19 +457,28 @@ static int do_ip_setsockopt(struct sock *sk, int level,
        struct inet_sock *inet = inet_sk(sk);
        int val = 0, err;
 
-       if (((1<<optname) & ((1<<IP_PKTINFO) | (1<<IP_RECVTTL) |
-                            (1<<IP_RECVOPTS) | (1<<IP_RECVTOS) |
-                            (1<<IP_RETOPTS) | (1<<IP_TOS) |
-                            (1<<IP_TTL) | (1<<IP_HDRINCL) |
-                            (1<<IP_MTU_DISCOVER) | (1<<IP_RECVERR) |
-                            (1<<IP_ROUTER_ALERT) | (1<<IP_FREEBIND) |
-                            (1<<IP_PASSSEC) | (1<<IP_TRANSPARENT) |
-                            (1<<IP_MINTTL) | (1<<IP_NODEFRAG))) ||
-           optname == IP_UNICAST_IF ||
-           optname == IP_MULTICAST_TTL ||
-           optname == IP_MULTICAST_ALL ||
-           optname == IP_MULTICAST_LOOP ||
-           optname == IP_RECVORIGDSTADDR) {
+       switch (optname) {
+       case IP_PKTINFO:
+       case IP_RECVTTL:
+       case IP_RECVOPTS:
+       case IP_RECVTOS:
+       case IP_RETOPTS:
+       case IP_TOS:
+       case IP_TTL:
+       case IP_HDRINCL:
+       case IP_MTU_DISCOVER:
+       case IP_RECVERR:
+       case IP_ROUTER_ALERT:
+       case IP_FREEBIND:
+       case IP_PASSSEC:
+       case IP_TRANSPARENT:
+       case IP_MINTTL:
+       case IP_NODEFRAG:
+       case IP_UNICAST_IF:
+       case IP_MULTICAST_TTL:
+       case IP_MULTICAST_ALL:
+       case IP_MULTICAST_LOOP:
+       case IP_RECVORIGDSTADDR:
                if (optlen >= sizeof(int)) {
                        if (get_user(val, (int __user *) optval))
                                return -EFAULT;
index 1831092f999fb32880f2d5e721c242236b000228..858fddf6482a645c46bf441c67d9ed323dc7d78f 100644 (file)
@@ -338,12 +338,17 @@ static int vti_rcv(struct sk_buff *skb)
        if (tunnel != NULL) {
                struct pcpu_tstats *tstats;
 
+               if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
+                       return -1;
+
                tstats = this_cpu_ptr(tunnel->dev->tstats);
                u64_stats_update_begin(&tstats->syncp);
                tstats->rx_packets++;
                tstats->rx_bytes += skb->len;
                u64_stats_update_end(&tstats->syncp);
 
+               skb->mark = 0;
+               secpath_reset(skb);
                skb->dev = tunnel->dev;
                return 1;
        }
index 9e0ffaf1d942624cf44d9693922e13312fc77ff2..a82047282dbbe2513615ae0c0e60dc1c54b2aa92 100644 (file)
@@ -184,7 +184,8 @@ nf_nat_ipv4_out(unsigned int hooknum,
 
                if ((ct->tuplehash[dir].tuple.src.u3.ip !=
                     ct->tuplehash[!dir].tuple.dst.u3.ip) ||
-                   (ct->tuplehash[dir].tuple.src.u.all !=
+                   (ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP &&
+                    ct->tuplehash[dir].tuple.src.u.all !=
                     ct->tuplehash[!dir].tuple.dst.u.all))
                        if (nf_xfrm_me_harder(skb, AF_INET) < 0)
                                ret = NF_DROP;
@@ -221,6 +222,7 @@ nf_nat_ipv4_local_fn(unsigned int hooknum,
                }
 #ifdef CONFIG_XFRM
                else if (!(IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) &&
+                        ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP &&
                         ct->tuplehash[dir].tuple.dst.u.all !=
                         ct->tuplehash[!dir].tuple.src.u.all)
                        if (nf_xfrm_me_harder(skb, AF_INET) < 0)
index 432f4bb77238fcc5c80d5ab7c6ad35bb55609c53..df251424d816b460ae268f21d337c57e64452fc6 100644 (file)
@@ -1163,8 +1163,12 @@ static bool rt_bind_exception(struct rtable *rt, struct fib_nh_exception *fnhe,
        spin_lock_bh(&fnhe_lock);
 
        if (daddr == fnhe->fnhe_daddr) {
-               struct rtable *orig;
-
+               struct rtable *orig = rcu_dereference(fnhe->fnhe_rth);
+               if (orig && rt_is_expired(orig)) {
+                       fnhe->fnhe_gw = 0;
+                       fnhe->fnhe_pmtu = 0;
+                       fnhe->fnhe_expires = 0;
+               }
                if (fnhe->fnhe_pmtu) {
                        unsigned long expires = fnhe->fnhe_expires;
                        unsigned long diff = expires - jiffies;
@@ -1181,7 +1185,6 @@ static bool rt_bind_exception(struct rtable *rt, struct fib_nh_exception *fnhe,
                } else if (!rt->rt_gateway)
                        rt->rt_gateway = daddr;
 
-               orig = rcu_dereference(fnhe->fnhe_rth);
                rcu_assign_pointer(fnhe->fnhe_rth, rt);
                if (orig)
                        rt_free(orig);
@@ -1782,6 +1785,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
        if (dev_out->flags & IFF_LOOPBACK)
                flags |= RTCF_LOCAL;
 
+       do_cache = true;
        if (type == RTN_BROADCAST) {
                flags |= RTCF_BROADCAST | RTCF_LOCAL;
                fi = NULL;
@@ -1790,6 +1794,8 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
                if (!ip_check_mc_rcu(in_dev, fl4->daddr, fl4->saddr,
                                     fl4->flowi4_proto))
                        flags &= ~RTCF_LOCAL;
+               else
+                       do_cache = false;
                /* If multicast route do not exist use
                 * default one, but do not gateway in this case.
                 * Yes, it is hack.
@@ -1799,8 +1805,8 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
        }
 
        fnhe = NULL;
-       do_cache = fi != NULL;
-       if (fi) {
+       do_cache &= fi != NULL;
+       if (do_cache) {
                struct rtable __rcu **prth;
                struct fib_nh *nh = &FIB_RES_NH(*res);
 
@@ -2594,7 +2600,7 @@ int __init ip_rt_init(void)
                pr_err("Unable to create route proc files\n");
 #ifdef CONFIG_XFRM
        xfrm_init();
-       xfrm4_init(ip_rt_max_size);
+       xfrm4_init();
 #endif
        rtnl_register(PF_INET, RTM_GETROUTE, inet_rtm_getroute, NULL, NULL);
 
index f32c02e2a54346cf4e120d39e17d4d1b5e966189..083092e3aed68db2dd5e9c3fb9cd43759a529abe 100644 (file)
@@ -549,14 +549,12 @@ int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg)
                         !tp->urg_data ||
                         before(tp->urg_seq, tp->copied_seq) ||
                         !before(tp->urg_seq, tp->rcv_nxt)) {
-                       struct sk_buff *skb;
 
                        answ = tp->rcv_nxt - tp->copied_seq;
 
-                       /* Subtract 1, if FIN is in queue. */
-                       skb = skb_peek_tail(&sk->sk_receive_queue);
-                       if (answ && skb)
-                               answ -= tcp_hdr(skb)->fin;
+                       /* Subtract 1, if FIN was received */
+                       if (answ && sock_flag(sk, SOCK_DONE))
+                               answ--;
                } else
                        answ = tp->urg_seq - tp->copied_seq;
                release_sock(sk);
@@ -1214,7 +1212,7 @@ new_segment:
 wait_for_sndbuf:
                        set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
 wait_for_memory:
-                       if (copied && likely(!tp->repair))
+                       if (copied)
                                tcp_push(sk, flags & ~MSG_MORE, mss_now, TCP_NAGLE_PUSH);
 
                        if ((err = sk_stream_wait_memory(sk, &timeo)) != 0)
@@ -1225,7 +1223,7 @@ wait_for_memory:
        }
 
 out:
-       if (copied && likely(!tp->repair))
+       if (copied)
                tcp_push(sk, flags, mss_now, tp->nonagle);
        release_sock(sk);
        return copied + copied_syn;
@@ -2766,6 +2764,8 @@ void tcp_get_info(const struct sock *sk, struct tcp_info *info)
                info->tcpi_options |= TCPI_OPT_ECN;
        if (tp->ecn_flags & TCP_ECN_SEEN)
                info->tcpi_options |= TCPI_OPT_ECN_SEEN;
+       if (tp->syn_data_acked)
+               info->tcpi_options |= TCPI_OPT_SYN_DATA;
 
        info->tcpi_rto = jiffies_to_usecs(icsk->icsk_rto);
        info->tcpi_ato = jiffies_to_usecs(icsk->icsk_ack.ato);
index 813b43a76fece71e2614878a5830962d55f35a22..834857f3c8713e8d8b80ab7b4f413725ec0ca9b4 100644 (file)
@@ -313,11 +313,13 @@ static void tcp_illinois_info(struct sock *sk, u32 ext,
                        .tcpv_rttcnt = ca->cnt_rtt,
                        .tcpv_minrtt = ca->base_rtt,
                };
-               u64 t = ca->sum_rtt;
 
-               do_div(t, ca->cnt_rtt);
-               info.tcpv_rtt = t;
+               if (info.tcpv_rttcnt > 0) {
+                       u64 t = ca->sum_rtt;
 
+                       do_div(t, info.tcpv_rttcnt);
+                       info.tcpv_rtt = t;
+               }
                nla_put(skb, INET_DIAG_VEGASINFO, sizeof(info), &info);
        }
 }
index 432c36649db3dd8d579ddb05ae886dd3251dcb66..609ff98aeb47ce99500614ff4a8a9cfe3a290d28 100644 (file)
@@ -4529,6 +4529,9 @@ int tcp_send_rcvq(struct sock *sk, struct msghdr *msg, size_t size)
        struct tcphdr *th;
        bool fragstolen;
 
+       if (size == 0)
+               return 0;
+
        skb = alloc_skb(size + sizeof(*th), sk->sk_allocation);
        if (!skb)
                goto err;
@@ -5310,11 +5313,6 @@ static bool tcp_validate_incoming(struct sock *sk, struct sk_buff *skb,
                goto discard;
        }
 
-       /* ts_recent update must be made after we are sure that the packet
-        * is in window.
-        */
-       tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq);
-
        /* step 3: check security and precedence [ignored] */
 
        /* step 4: Check for a SYN
@@ -5549,6 +5547,11 @@ step5:
        if (th->ack && tcp_ack(sk, skb, FLAG_SLOWPATH) < 0)
                goto discard;
 
+       /* ts_recent update must be made after we are sure that the packet
+        * is in window.
+        */
+       tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq);
+
        tcp_rcv_rtt_measure_ts(sk, skb);
 
        /* Process urgent data. */
@@ -5646,6 +5649,7 @@ static bool tcp_rcv_fastopen_synack(struct sock *sk, struct sk_buff *synack,
                tcp_rearm_rto(sk);
                return true;
        }
+       tp->syn_data_acked = tp->syn_data;
        return false;
 }
 
@@ -5963,7 +5967,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
 
        req = tp->fastopen_rsk;
        if (req != NULL) {
-               BUG_ON(sk->sk_state != TCP_SYN_RECV &&
+               WARN_ON_ONCE(sk->sk_state != TCP_SYN_RECV &&
                    sk->sk_state != TCP_FIN_WAIT1);
 
                if (tcp_check_req(sk, skb, req, NULL, true) == NULL)
@@ -6052,7 +6056,15 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
                         * ACK we have received, this would have acknowledged
                         * our SYNACK so stop the SYNACK timer.
                         */
-                       if (acceptable && req != NULL) {
+                       if (req != NULL) {
+                               /* Return RST if ack_seq is invalid.
+                                * Note that RFC793 only says to generate a
+                                * DUPACK for it but for TCP Fast Open it seems
+                                * better to treat this case like TCP_SYN_RECV
+                                * above.
+                                */
+                               if (!acceptable)
+                                       return 1;
                                /* We no longer need the request sock. */
                                reqsk_fastopen_remove(sk, req, false);
                                tcp_rearm_rto(sk);
@@ -6118,6 +6130,11 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
        } else
                goto discard;
 
+       /* ts_recent update must be made after we are sure that the packet
+        * is in window.
+        */
+       tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq);
+
        /* step 6: check the URG bit */
        tcp_urg(sk, skb, th);
 
index ef998b008a570ba0976b911d85d0b98bb6d834fb..0c4a643556037871c1c6a202aa99ba338a7a92d5 100644 (file)
@@ -1461,6 +1461,7 @@ static int tcp_v4_conn_req_fastopen(struct sock *sk,
                skb_set_owner_r(skb, child);
                __skb_queue_tail(&child->sk_receive_queue, skb);
                tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
+               tp->syn_data_acked = 1;
        }
        sk->sk_data_ready(sk, 0);
        bh_unlock_sock(child);
index 4c752a6e0bcd91b0b932b483a2b9f988908c04a2..f696d7c2e9faac9b2fbfd2e61472d47a7c2fa823 100644 (file)
@@ -1,7 +1,6 @@
 #include <linux/rcupdate.h>
 #include <linux/spinlock.h>
 #include <linux/jiffies.h>
-#include <linux/bootmem.h>
 #include <linux/module.h>
 #include <linux/cache.h>
 #include <linux/slab.h>
@@ -9,6 +8,7 @@
 #include <linux/tcp.h>
 #include <linux/hash.h>
 #include <linux/tcp_metrics.h>
+#include <linux/vmalloc.h>
 
 #include <net/inet_connection_sock.h>
 #include <net/net_namespace.h>
@@ -864,7 +864,7 @@ static int parse_nl_addr(struct genl_info *info, struct inetpeer_addr *addr,
        }
        a = info->attrs[TCP_METRICS_ATTR_ADDR_IPV6];
        if (a) {
-               if (nla_len(a) != sizeof(sizeof(struct in6_addr)))
+               if (nla_len(a) != sizeof(struct in6_addr))
                        return -EINVAL;
                addr->family = AF_INET6;
                memcpy(addr->addr.a6, nla_data(a), sizeof(addr->addr.a6));
@@ -1034,7 +1034,10 @@ static int __net_init tcp_net_metrics_init(struct net *net)
        net->ipv4.tcp_metrics_hash_log = order_base_2(slots);
        size = sizeof(struct tcpm_hash_bucket) << net->ipv4.tcp_metrics_hash_log;
 
-       net->ipv4.tcp_metrics_hash = kzalloc(size, GFP_KERNEL);
+       net->ipv4.tcp_metrics_hash = kzalloc(size, GFP_KERNEL | __GFP_NOWARN);
+       if (!net->ipv4.tcp_metrics_hash)
+               net->ipv4.tcp_metrics_hash = vzalloc(size);
+
        if (!net->ipv4.tcp_metrics_hash)
                return -ENOMEM;
 
@@ -1055,7 +1058,10 @@ static void __net_exit tcp_net_metrics_exit(struct net *net)
                        tm = next;
                }
        }
-       kfree(net->ipv4.tcp_metrics_hash);
+       if (is_vmalloc_addr(net->ipv4.tcp_metrics_hash))
+               vfree(net->ipv4.tcp_metrics_hash);
+       else
+               kfree(net->ipv4.tcp_metrics_hash);
 }
 
 static __net_initdata struct pernet_operations tcp_net_metrics_ops = {
index 27536ba16c9da7b89d5385073c7ae4d4f9e27f3c..a7302d974f32ca563e4aeb589a193e7617c396a5 100644 (file)
@@ -510,6 +510,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req,
                newtp->rx_opt.mss_clamp = req->mss;
                TCP_ECN_openreq_child(newtp, req);
                newtp->fastopen_rsk = NULL;
+               newtp->syn_data_acked = 0;
 
                TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_PASSIVEOPENS);
        }
index cfe6ffe1c1778b6517297ad3ac9b87d17ce14582..2798706cb06385aa87fdb05ba1ed2c6a0a14e6e5 100644 (file)
@@ -1986,6 +1986,9 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle,
                tso_segs = tcp_init_tso_segs(sk, skb, mss_now);
                BUG_ON(!tso_segs);
 
+               if (unlikely(tp->repair) && tp->repair_queue == TCP_SEND_QUEUE)
+                       goto repair; /* Skip network transmission */
+
                cwnd_quota = tcp_cwnd_test(tp, skb);
                if (!cwnd_quota)
                        break;
@@ -2026,6 +2029,7 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle,
                if (unlikely(tcp_transmit_skb(sk, skb, 1, gfp)))
                        break;
 
+repair:
                /* Advance the send_head.  This one is sent out.
                 * This call will increment packets_out.
                 */
index fc04711e80c89dd0dc92ff1027efaa7324b218c3..d47c1b4421a339a3378ef23646c8f99b41d7490b 100644 (file)
@@ -347,8 +347,8 @@ void tcp_retransmit_timer(struct sock *sk)
                return;
        }
        if (tp->fastopen_rsk) {
-               BUG_ON(sk->sk_state != TCP_SYN_RECV &&
-                   sk->sk_state != TCP_FIN_WAIT1);
+               WARN_ON_ONCE(sk->sk_state != TCP_SYN_RECV &&
+                            sk->sk_state != TCP_FIN_WAIT1);
                tcp_fastopen_synack_timer(sk);
                /* Before we receive ACK to our SYN-ACK don't retransmit
                 * anything else (e.g., data or FIN segments).
index 05c5ab8d983c462f75ab6143ca653669d36c1005..3be0ac2c1920e668be3f53f44a3df731a44204fc 100644 (file)
@@ -279,19 +279,8 @@ static void __exit xfrm4_policy_fini(void)
        xfrm_policy_unregister_afinfo(&xfrm4_policy_afinfo);
 }
 
-void __init xfrm4_init(int rt_max_size)
+void __init xfrm4_init(void)
 {
-       /*
-        * Select a default value for the gc_thresh based on the main route
-        * table hash size.  It seems to me the worst case scenario is when
-        * we have ipsec operating in transport mode, in which we create a
-        * dst_entry per socket.  The xfrm gc algorithm starts trying to remove
-        * entries at gc_thresh, and prevents new allocations as 2*gc_thresh
-        * so lets set an initial xfrm gc_thresh value at the rt_max_size/2.
-        * That will let us store an ipsec connection per route table entry,
-        * and start cleaning when were 1/2 full
-        */
-       xfrm4_dst_ops.gc_thresh = rt_max_size/2;
        dst_entries_init(&xfrm4_dst_ops);
 
        xfrm4_state_init();
index c4f934176cabd92ebfb4bba774335427b9f8932a..30647857a375bce469c50071636b5aef6c5a33d7 100644 (file)
@@ -252,6 +252,7 @@ struct dst_entry *inet6_csk_update_pmtu(struct sock *sk, u32 mtu)
                return NULL;
        dst->ops->update_pmtu(dst, sk, NULL, mtu);
 
-       return inet6_csk_route_socket(sk, &fl6);
+       dst = inet6_csk_route_socket(sk, &fl6);
+       return IS_ERR(dst) ? NULL : dst;
 }
 EXPORT_SYMBOL_GPL(inet6_csk_update_pmtu);
index 0185679c5f536c1fa98d71ac90a2c24cd6481d8f..d5cb3c4e66f888bf056b4103cfd684f8a3e0a7a0 100644 (file)
@@ -1633,9 +1633,9 @@ static size_t ip6gre_get_size(const struct net_device *dev)
                /* IFLA_GRE_OKEY */
                nla_total_size(4) +
                /* IFLA_GRE_LOCAL */
-               nla_total_size(4) +
+               nla_total_size(sizeof(struct in6_addr)) +
                /* IFLA_GRE_REMOTE */
-               nla_total_size(4) +
+               nla_total_size(sizeof(struct in6_addr)) +
                /* IFLA_GRE_TTL */
                nla_total_size(1) +
                /* IFLA_GRE_TOS */
@@ -1659,8 +1659,8 @@ static int ip6gre_fill_info(struct sk_buff *skb, const struct net_device *dev)
            nla_put_be16(skb, IFLA_GRE_OFLAGS, p->o_flags) ||
            nla_put_be32(skb, IFLA_GRE_IKEY, p->i_key) ||
            nla_put_be32(skb, IFLA_GRE_OKEY, p->o_key) ||
-           nla_put(skb, IFLA_GRE_LOCAL, sizeof(struct in6_addr), &p->raddr) ||
-           nla_put(skb, IFLA_GRE_REMOTE, sizeof(struct in6_addr), &p->laddr) ||
+           nla_put(skb, IFLA_GRE_LOCAL, sizeof(struct in6_addr), &p->laddr) ||
+           nla_put(skb, IFLA_GRE_REMOTE, sizeof(struct in6_addr), &p->raddr) ||
            nla_put_u8(skb, IFLA_GRE_TTL, p->hop_limit) ||
            /*nla_put_u8(skb, IFLA_GRE_TOS, t->priority) ||*/
            nla_put_u8(skb, IFLA_GRE_ENCAP_LIMIT, p->encap_limit) ||
index ba6d13d1f1e162254fa4e4421e82e4a204a9785c..e02faed6d17efa1684c2c9b0990506008bdb8aff 100644 (file)
@@ -827,6 +827,7 @@ pref_skip_coa:
                if (val < 0 || val > 255)
                        goto e_inval;
                np->min_hopcount = val;
+               retv = 0;
                break;
        case IPV6_DONTFRAG:
                np->dontfrag = valbool;
index ff36194a71aa7dd0fe0f707cff80afd83e40102e..2edce30ef7338cdf1916eef98b353c7dbbc7bcda 100644 (file)
@@ -535,7 +535,7 @@ static void ndisc_send_unsol_na(struct net_device *dev)
 {
        struct inet6_dev *idev;
        struct inet6_ifaddr *ifa;
-       struct in6_addr mcaddr;
+       struct in6_addr mcaddr = IN6ADDR_LINKLOCAL_ALLNODES_INIT;
 
        idev = in6_dev_get(dev);
        if (!idev)
@@ -543,7 +543,6 @@ static void ndisc_send_unsol_na(struct net_device *dev)
 
        read_lock_bh(&idev->lock);
        list_for_each_entry(ifa, &idev->addr_list, if_list) {
-               addrconf_addr_solict_mult(&ifa->addr, &mcaddr);
                ndisc_send_na(dev, NULL, &mcaddr, &ifa->addr,
                              /*router=*/ !!idev->cnf.forwarding,
                              /*solicited=*/ false, /*override=*/ true,
index e418bd6350a405c9912f09207b876d1151961551..d57dab17a18251fcb8c63fc27c2dddfe8bc2a89e 100644 (file)
@@ -186,7 +186,8 @@ nf_nat_ipv6_out(unsigned int hooknum,
 
                if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.src.u3,
                                      &ct->tuplehash[!dir].tuple.dst.u3) ||
-                   (ct->tuplehash[dir].tuple.src.u.all !=
+                   (ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMPV6 &&
+                    ct->tuplehash[dir].tuple.src.u.all !=
                     ct->tuplehash[!dir].tuple.dst.u.all))
                        if (nf_xfrm_me_harder(skb, AF_INET6) < 0)
                                ret = NF_DROP;
@@ -222,6 +223,7 @@ nf_nat_ipv6_local_fn(unsigned int hooknum,
                }
 #ifdef CONFIG_XFRM
                else if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) &&
+                        ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMPV6 &&
                         ct->tuplehash[dir].tuple.dst.u.all !=
                         ct->tuplehash[!dir].tuple.src.u.all)
                        if (nf_xfrm_me_harder(skb, AF_INET6))
index 18bd9bbbd1c6c0f50d8bf74c947c05f91a4f20cd..22c8ea9511852e963b982ad68ed7066bda262ad2 100644 (file)
@@ -85,7 +85,7 @@ static struct ctl_table nf_ct_frag6_sysctl_table[] = {
        { }
 };
 
-static int __net_init nf_ct_frag6_sysctl_register(struct net *net)
+static int nf_ct_frag6_sysctl_register(struct net *net)
 {
        struct ctl_table *table;
        struct ctl_table_header *hdr;
@@ -127,7 +127,7 @@ static void __net_exit nf_ct_frags6_sysctl_unregister(struct net *net)
 }
 
 #else
-static int __net_init nf_ct_frag6_sysctl_register(struct net *net)
+static int nf_ct_frag6_sysctl_register(struct net *net)
 {
        return 0;
 }
index 7c7e963260e1792be01a329d4298dc1123c8f738..b1e6cf0b95fd9bf3546420e8cb48578d1a7d2190 100644 (file)
@@ -219,7 +219,7 @@ static struct dst_ops ip6_dst_blackhole_ops = {
 };
 
 static const u32 ip6_template_metrics[RTAX_MAX] = {
-       [RTAX_HOPLIMIT - 1] = 255,
+       [RTAX_HOPLIMIT - 1] = 0,
 };
 
 static const struct rt6_info ip6_null_entry_template = {
@@ -1232,7 +1232,7 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
        rt->rt6i_dst.addr = fl6->daddr;
        rt->rt6i_dst.plen = 128;
        rt->rt6i_idev     = idev;
-       dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 255);
+       dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 0);
 
        spin_lock_bh(&icmp6_dst_lock);
        rt->dst.next = icmp6_dst_gc_list;
index 37b8b8ba31f7395001cd2f36e234d82878bc22c7..76125c57ee6dddd2396a8a0bef4f19e7720e43ed 100644 (file)
@@ -291,6 +291,7 @@ static int l2tp_eth_create(struct net *net, u32 tunnel_id, u32 session_id, u32 p
 
 out_del_dev:
        free_netdev(dev);
+       spriv->dev = NULL;
 out_del_session:
        l2tp_session_delete(session);
 out:
index 05f3a313db8852b36c677cad188fd7154d6564ef..7371f676cf412e54481751d36bf757f42dfa5134 100644 (file)
@@ -2594,6 +2594,9 @@ static void ieee80211_mgmt_frame_register(struct wiphy *wiphy,
                else
                        local->probe_req_reg--;
 
+               if (!local->open_count)
+                       break;
+
                ieee80211_queue_work(&local->hw, &local->reconfig_filter);
                break;
        default:
index 5f3620f0bc0a651257aa53e28b91c4b2114be637..c21e33d1abd0d945ba041182dff52ad3f9ed4dc6 100644 (file)
@@ -1108,7 +1108,7 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
        sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH;
        sdata->u.ibss.ibss_join_req = jiffies;
 
-       memcpy(sdata->u.ibss.ssid, params->ssid, IEEE80211_MAX_SSID_LEN);
+       memcpy(sdata->u.ibss.ssid, params->ssid, params->ssid_len);
        sdata->u.ibss.ssid_len = params->ssid_len;
 
        mutex_unlock(&sdata->u.ibss.mtx);
@@ -1151,10 +1151,6 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
 
        mutex_lock(&sdata->u.ibss.mtx);
 
-       sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH;
-       memset(sdata->u.ibss.bssid, 0, ETH_ALEN);
-       sdata->u.ibss.ssid_len = 0;
-
        active_ibss = ieee80211_sta_active_ibss(sdata);
 
        if (!active_ibss && !is_zero_ether_addr(ifibss->bssid)) {
@@ -1175,6 +1171,10 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
                }
        }
 
+       ifibss->state = IEEE80211_IBSS_MLME_SEARCH;
+       memset(ifibss->bssid, 0, ETH_ALEN);
+       ifibss->ssid_len = 0;
+
        sta_info_flush(sdata->local, sdata);
 
        spin_lock_bh(&ifibss->incomplete_lock);
index 8c804550465b37857d6dc50b082881ec5bd4ac35..156e5835e37f4b140fb9261c2c1ed44f73cf8408 100644 (file)
@@ -1314,6 +1314,8 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,
                                         struct net_device *dev);
 netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
                                       struct net_device *dev);
+void ieee80211_purge_tx_queue(struct ieee80211_hw *hw,
+                             struct sk_buff_head *skbs);
 
 /* HT */
 void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata,
index 6f8a73c64fb31bde831609fa88a9b4e0425f02b9..7de7717ad67d97c7f75afca4c6a8c13fbec63404 100644 (file)
@@ -853,7 +853,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
                        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
                        if (info->control.vif == &sdata->vif) {
                                __skb_unlink(skb, &local->pending[i]);
-                               dev_kfree_skb_irq(skb);
+                               ieee80211_free_txskb(&local->hw, skb);
                        }
                }
        }
index c80c4490351ce54fb75c41cdb9be1a313b0ffef5..f57f597972f8833ccc5a74a433bfd2ddafe407dd 100644 (file)
@@ -871,8 +871,10 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
                                local->hw.wiphy->cipher_suites,
                                sizeof(u32) * local->hw.wiphy->n_cipher_suites,
                                GFP_KERNEL);
-                       if (!suites)
-                               return -ENOMEM;
+                       if (!suites) {
+                               result = -ENOMEM;
+                               goto fail_wiphy_register;
+                       }
                        for (r = 0; r < local->hw.wiphy->n_cipher_suites; r++) {
                                u32 suite = local->hw.wiphy->cipher_suites[r];
                                if (suite == WLAN_CIPHER_SUITE_WEP40 ||
index e714ed8bb198727c6738c1e3ae7650243dd2a07e..1b7eed252fe9fe0082596d8716c1e0f5e029db7f 100644 (file)
@@ -3099,22 +3099,32 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
                                   ht_cfreq, ht_oper->primary_chan,
                                   cbss->channel->band);
                        ht_oper = NULL;
+               } else {
+                       channel_type = NL80211_CHAN_HT20;
                }
        }
 
-       if (ht_oper) {
-               channel_type = NL80211_CHAN_HT20;
+       if (ht_oper && sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) {
+               /*
+                * cfg80211 already verified that the channel itself can
+                * be used, but it didn't check that we can do the right
+                * HT type, so do that here as well. If HT40 isn't allowed
+                * on this channel, disable 40 MHz operation.
+                */
 
-               if (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) {
-                       switch (ht_oper->ht_param &
-                                       IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
-                       case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
+               switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
+               case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
+                       if (cbss->channel->flags & IEEE80211_CHAN_NO_HT40PLUS)
+                               ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ;
+                       else
                                channel_type = NL80211_CHAN_HT40PLUS;
-                               break;
-                       case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
+                       break;
+               case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
+                       if (cbss->channel->flags & IEEE80211_CHAN_NO_HT40MINUS)
+                               ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ;
+                       else
                                channel_type = NL80211_CHAN_HT40MINUS;
-                               break;
-                       }
+                       break;
                }
        }
 
@@ -3549,6 +3559,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;
 
        mutex_lock(&ifmgd->mtx);
 
@@ -3565,12 +3576,12 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
        if (ifmgd->associated &&
            ether_addr_equal(ifmgd->associated->bssid, req->bssid)) {
                ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
-                                      req->reason_code, true, frame_buf);
+                                      req->reason_code, tx, frame_buf);
        } else {
                drv_mgd_prepare_tx(sdata->local, sdata);
                ieee80211_send_deauth_disassoc(sdata, req->bssid,
                                               IEEE80211_STYPE_DEAUTH,
-                                              req->reason_code, true,
+                                              req->reason_code, tx,
                                               frame_buf);
        }
 
index 61c621e9273fe70c26978d42433d58fca60a80b8..00ade7feb2e3a3b84af12be5bfad378bd8907182 100644 (file)
@@ -531,6 +531,11 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
 
                if (ieee80211_is_action(hdr->frame_control)) {
                        u8 category;
+
+                       /* make sure category field is present */
+                       if (rx->skb->len < IEEE80211_MIN_ACTION_SIZE)
+                               return RX_DROP_MONITOR;
+
                        mgmt = (struct ieee80211_mgmt *)hdr;
                        category = mgmt->u.action.category;
                        if (category != WLAN_CATEGORY_MESH_ACTION &&
@@ -883,14 +888,16 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
                 */
                if (rx->sta && rx->sdata->vif.type == NL80211_IFTYPE_STATION &&
                    ieee80211_is_data_present(hdr->frame_control)) {
-                       u16 ethertype;
-                       u8 *payload;
-
-                       payload = rx->skb->data +
-                               ieee80211_hdrlen(hdr->frame_control);
-                       ethertype = (payload[6] << 8) | payload[7];
-                       if (cpu_to_be16(ethertype) ==
-                           rx->sdata->control_port_protocol)
+                       unsigned int hdrlen;
+                       __be16 ethertype;
+
+                       hdrlen = ieee80211_hdrlen(hdr->frame_control);
+
+                       if (rx->skb->len < hdrlen + 8)
+                               return RX_DROP_MONITOR;
+
+                       skb_copy_bits(rx->skb, hdrlen + 6, &ethertype, 2);
+                       if (ethertype == rx->sdata->control_port_protocol)
                                return RX_CONTINUE;
                }
 
@@ -1462,11 +1469,14 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
 
        hdr = (struct ieee80211_hdr *)rx->skb->data;
        fc = hdr->frame_control;
+
+       if (ieee80211_is_ctl(fc))
+               return RX_CONTINUE;
+
        sc = le16_to_cpu(hdr->seq_ctrl);
        frag = sc & IEEE80211_SCTL_FRAG;
 
        if (likely((!ieee80211_has_morefrags(fc) && frag == 0) ||
-                  (rx->skb)->len < 24 ||
                   is_multicast_ether_addr(hdr->addr1))) {
                /* not fragmented */
                goto out;
@@ -1889,6 +1899,20 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
 
        hdr = (struct ieee80211_hdr *) skb->data;
        hdrlen = ieee80211_hdrlen(hdr->frame_control);
+
+       /* make sure fixed part of mesh header is there, also checks skb len */
+       if (!pskb_may_pull(rx->skb, hdrlen + 6))
+               return RX_DROP_MONITOR;
+
+       mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);
+
+       /* make sure full mesh header is there, also checks skb len */
+       if (!pskb_may_pull(rx->skb,
+                          hdrlen + ieee80211_get_mesh_hdrlen(mesh_hdr)))
+               return RX_DROP_MONITOR;
+
+       /* reload pointers */
+       hdr = (struct ieee80211_hdr *) skb->data;
        mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);
 
        /* frame is in RMC, don't forward */
@@ -1897,7 +1921,8 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
            mesh_rmc_check(hdr->addr3, mesh_hdr, rx->sdata))
                return RX_DROP_MONITOR;
 
-       if (!ieee80211_is_data(hdr->frame_control))
+       if (!ieee80211_is_data(hdr->frame_control) ||
+           !(status->rx_flags & IEEE80211_RX_RA_MATCH))
                return RX_CONTINUE;
 
        if (!mesh_hdr->ttl)
@@ -1911,9 +1936,12 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
                if (is_multicast_ether_addr(hdr->addr1)) {
                        mpp_addr = hdr->addr3;
                        proxied_addr = mesh_hdr->eaddr1;
-               } else {
+               } else if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6) {
+                       /* has_a4 already checked in ieee80211_rx_mesh_check */
                        mpp_addr = hdr->addr4;
                        proxied_addr = mesh_hdr->eaddr2;
+               } else {
+                       return RX_DROP_MONITOR;
                }
 
                rcu_read_lock();
@@ -1941,12 +1969,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
        }
        skb_set_queue_mapping(skb, q);
 
-       if (!(status->rx_flags & IEEE80211_RX_RA_MATCH))
-               goto out;
-
        if (!--mesh_hdr->ttl) {
                IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_ttl);
-               return RX_DROP_MONITOR;
+               goto out;
        }
 
        if (!ifmsh->mshcfg.dot11MeshForwarding)
@@ -2353,6 +2378,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
                }
                break;
        case WLAN_CATEGORY_SELF_PROTECTED:
+               if (len < (IEEE80211_MIN_ACTION_SIZE +
+                          sizeof(mgmt->u.action.u.self_prot.action_code)))
+                       break;
+
                switch (mgmt->u.action.u.self_prot.action_code) {
                case WLAN_SP_MESH_PEERING_OPEN:
                case WLAN_SP_MESH_PEERING_CLOSE:
@@ -2371,6 +2400,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
                }
                break;
        case WLAN_CATEGORY_MESH_ACTION:
+               if (len < (IEEE80211_MIN_ACTION_SIZE +
+                          sizeof(mgmt->u.action.u.mesh_action.action_code)))
+                       break;
+
                if (!ieee80211_vif_is_mesh(&sdata->vif))
                        break;
                if (mesh_action_is_path_sel(mgmt) &&
@@ -2913,10 +2946,15 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
        if (ieee80211_is_data(fc) || ieee80211_is_mgmt(fc))
                local->dot11ReceivedFragmentCount++;
 
-       if (ieee80211_is_mgmt(fc))
-               err = skb_linearize(skb);
-       else
+       if (ieee80211_is_mgmt(fc)) {
+               /* drop frame if too short for header */
+               if (skb->len < ieee80211_hdrlen(fc))
+                       err = -ENOBUFS;
+               else
+                       err = skb_linearize(skb);
+       } else {
                err = !pskb_may_pull(skb, ieee80211_hdrlen(fc));
+       }
 
        if (err) {
                dev_kfree_skb(skb);
index c4cdbde24fd3a70db1141c9460f617710daf98e2..43e60b5a7546eba4fd6e5e18eb313b7526d4f5b1 100644 (file)
@@ -917,7 +917,7 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
                                       struct cfg80211_sched_scan_request *req)
 {
        struct ieee80211_local *local = sdata->local;
-       struct ieee80211_sched_scan_ies sched_scan_ies;
+       struct ieee80211_sched_scan_ies sched_scan_ies = {};
        int ret, i;
 
        mutex_lock(&local->mtx);
index 797dd36a220d92ac549067a9cd4d59a7ebfc09a3..d2eb64e1235383e9b0e6aade66710f74ec1b4f3f 100644 (file)
@@ -117,8 +117,8 @@ static void free_sta_work(struct work_struct *wk)
 
        for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
                local->total_ps_buffered -= skb_queue_len(&sta->ps_tx_buf[ac]);
-               __skb_queue_purge(&sta->ps_tx_buf[ac]);
-               __skb_queue_purge(&sta->tx_filtered[ac]);
+               ieee80211_purge_tx_queue(&local->hw, &sta->ps_tx_buf[ac]);
+               ieee80211_purge_tx_queue(&local->hw, &sta->tx_filtered[ac]);
        }
 
 #ifdef CONFIG_MAC80211_MESH
@@ -141,7 +141,7 @@ static void free_sta_work(struct work_struct *wk)
                tid_tx = rcu_dereference_raw(sta->ampdu_mlme.tid_tx[i]);
                if (!tid_tx)
                        continue;
-               __skb_queue_purge(&tid_tx->pending);
+               ieee80211_purge_tx_queue(&local->hw, &tid_tx->pending);
                kfree(tid_tx);
        }
 
@@ -650,7 +650,7 @@ static bool sta_info_cleanup_expire_buffered_ac(struct ieee80211_local *local,
                 */
                if (!skb)
                        break;
-               dev_kfree_skb(skb);
+               ieee80211_free_txskb(&local->hw, skb);
        }
 
        /*
@@ -679,7 +679,7 @@ static bool sta_info_cleanup_expire_buffered_ac(struct ieee80211_local *local,
                local->total_ps_buffered--;
                ps_dbg(sta->sdata, "Buffered frame expired (STA %pM)\n",
                       sta->sta.addr);
-               dev_kfree_skb(skb);
+               ieee80211_free_txskb(&local->hw, skb);
        }
 
        /*
@@ -961,6 +961,7 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
        struct ieee80211_local *local = sdata->local;
        struct sk_buff_head pending;
        int filtered = 0, buffered = 0, ac;
+       unsigned long flags;
 
        clear_sta_flag(sta, WLAN_STA_SP);
 
@@ -976,12 +977,16 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
        for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
                int count = skb_queue_len(&pending), tmp;
 
+               spin_lock_irqsave(&sta->tx_filtered[ac].lock, flags);
                skb_queue_splice_tail_init(&sta->tx_filtered[ac], &pending);
+               spin_unlock_irqrestore(&sta->tx_filtered[ac].lock, flags);
                tmp = skb_queue_len(&pending);
                filtered += tmp - count;
                count = tmp;
 
+               spin_lock_irqsave(&sta->ps_tx_buf[ac].lock, flags);
                skb_queue_splice_tail_init(&sta->ps_tx_buf[ac], &pending);
+               spin_unlock_irqrestore(&sta->ps_tx_buf[ac].lock, flags);
                tmp = skb_queue_len(&pending);
                buffered += tmp - count;
        }
index 3af0cc4130f1986e1cf672a9246830d478e222e9..101eb88a2b78563965d4477a815bf8069d586db8 100644 (file)
@@ -668,3 +668,12 @@ void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb)
        dev_kfree_skb_any(skb);
 }
 EXPORT_SYMBOL(ieee80211_free_txskb);
+
+void ieee80211_purge_tx_queue(struct ieee80211_hw *hw,
+                             struct sk_buff_head *skbs)
+{
+       struct sk_buff *skb;
+
+       while ((skb = __skb_dequeue(skbs)))
+               ieee80211_free_txskb(hw, skb);
+}
index c9bf83f36657c3ca9929e64d2fd27c47a6486e3a..b858ebe41fdac2f20326cfd58fb37840270fcaa1 100644 (file)
@@ -1358,7 +1358,7 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
                if (tx->skb)
                        ieee80211_free_txskb(&tx->local->hw, tx->skb);
                else
-                       __skb_queue_purge(&tx->skbs);
+                       ieee80211_purge_tx_queue(&tx->local->hw, &tx->skbs);
                return -1;
        } else if (unlikely(res == TX_QUEUED)) {
                I802_DEBUG_INC(tx->local->tx_handlers_queued);
@@ -2120,10 +2120,13 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
  */
 void ieee80211_clear_tx_pending(struct ieee80211_local *local)
 {
+       struct sk_buff *skb;
        int i;
 
-       for (i = 0; i < local->hw.queues; i++)
-               skb_queue_purge(&local->pending[i]);
+       for (i = 0; i < local->hw.queues; i++) {
+               while ((skb = skb_dequeue(&local->pending[i])) != NULL)
+                       ieee80211_free_txskb(&local->hw, skb);
+       }
 }
 
 /*
index 22ca35054dd065753b9e7d6c4f3e5ab990903e83..0151ae33c4cd448e4812b0e9255d47898bf595da 100644 (file)
@@ -406,7 +406,7 @@ void ieee80211_add_pending_skb(struct ieee80211_local *local,
        int queue = info->hw_queue;
 
        if (WARN_ON(!info->control.vif)) {
-               kfree_skb(skb);
+               ieee80211_free_txskb(&local->hw, skb);
                return;
        }
 
@@ -431,7 +431,7 @@ void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local,
                struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 
                if (WARN_ON(!info->control.vif)) {
-                       kfree_skb(skb);
+                       ieee80211_free_txskb(&local->hw, skb);
                        continue;
                }
 
@@ -643,13 +643,41 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
                        break;
                }
 
-               if (id != WLAN_EID_VENDOR_SPECIFIC &&
-                   id != WLAN_EID_QUIET &&
-                   test_bit(id, seen_elems)) {
-                       elems->parse_error = true;
-                       left -= elen;
-                       pos += elen;
-                       continue;
+               switch (id) {
+               case WLAN_EID_SSID:
+               case WLAN_EID_SUPP_RATES:
+               case WLAN_EID_FH_PARAMS:
+               case WLAN_EID_DS_PARAMS:
+               case WLAN_EID_CF_PARAMS:
+               case WLAN_EID_TIM:
+               case WLAN_EID_IBSS_PARAMS:
+               case WLAN_EID_CHALLENGE:
+               case WLAN_EID_RSN:
+               case WLAN_EID_ERP_INFO:
+               case WLAN_EID_EXT_SUPP_RATES:
+               case WLAN_EID_HT_CAPABILITY:
+               case WLAN_EID_HT_OPERATION:
+               case WLAN_EID_VHT_CAPABILITY:
+               case WLAN_EID_VHT_OPERATION:
+               case WLAN_EID_MESH_ID:
+               case WLAN_EID_MESH_CONFIG:
+               case WLAN_EID_PEER_MGMT:
+               case WLAN_EID_PREQ:
+               case WLAN_EID_PREP:
+               case WLAN_EID_PERR:
+               case WLAN_EID_RANN:
+               case WLAN_EID_CHANNEL_SWITCH:
+               case WLAN_EID_EXT_CHANSWITCH_ANN:
+               case WLAN_EID_COUNTRY:
+               case WLAN_EID_PWR_CONSTRAINT:
+               case WLAN_EID_TIMEOUT_INTERVAL:
+                       if (test_bit(id, seen_elems)) {
+                               elems->parse_error = true;
+                               left -= elen;
+                               pos += elen;
+                               continue;
+                       }
+                       break;
                }
 
                if (calc_crc && id < 64 && (filter & (1ULL << id)))
@@ -1463,6 +1491,8 @@ int ieee80211_reconfig(struct ieee80211_local *local)
                list_for_each_entry(sdata, &local->interfaces, list) {
                        if (sdata->vif.type != NL80211_IFTYPE_STATION)
                                continue;
+                       if (!sdata->u.mgd.associated)
+                               continue;
 
                        ieee80211_send_nullfunc(local, sdata, 0);
                }
index bdb53aba888e147cfd3bae984cd69811f520261a..8bd2f5c6a56edfa26193de6da2560c88d5ac75ce 100644 (file)
@@ -106,7 +106,8 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx)
                if (status->flag & RX_FLAG_MMIC_ERROR)
                        goto mic_fail;
 
-               if (!(status->flag & RX_FLAG_IV_STRIPPED) && rx->key)
+               if (!(status->flag & RX_FLAG_IV_STRIPPED) && rx->key &&
+                   rx->key->conf.cipher == WLAN_CIPHER_SUITE_TKIP)
                        goto update_iv;
 
                return RX_CONTINUE;
@@ -545,14 +546,19 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
 
 static void bip_aad(struct sk_buff *skb, u8 *aad)
 {
+       __le16 mask_fc;
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+
        /* BIP AAD: FC(masked) || A1 || A2 || A3 */
 
        /* FC type/subtype */
-       aad[0] = skb->data[0];
        /* Mask FC Retry, PwrMgt, MoreData flags to zero */
-       aad[1] = skb->data[1] & ~(BIT(4) | BIT(5) | BIT(6));
+       mask_fc = hdr->frame_control;
+       mask_fc &= ~cpu_to_le16(IEEE80211_FCTL_RETRY | IEEE80211_FCTL_PM |
+                               IEEE80211_FCTL_MOREDATA);
+       put_unaligned(mask_fc, (__le16 *) &aad[0]);
        /* A1 || A2 || A3 */
-       memcpy(aad + 2, skb->data + 4, 3 * ETH_ALEN);
+       memcpy(aad + 2, &hdr->addr1, 3 * ETH_ALEN);
 }
 
 
index ec3dba5dcd62f081c1749fb60f2aa71cd31d11ad..5c0b78528e55b1af2288aa2e1a398202131413d5 100644 (file)
@@ -173,6 +173,7 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
                return adtfn(set, &nip, timeout, flags);
        }
 
+       ip_to = ip;
        if (tb[IPSET_ATTR_IP_TO]) {
                ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
                if (ret)
@@ -185,8 +186,7 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
                if (!cidr || cidr > 32)
                        return -IPSET_ERR_INVALID_CIDR;
                ip_set_mask_from_to(ip, ip_to, cidr);
-       } else
-               ip_to = ip;
+       }
 
        hosts = h->netmask == 32 ? 1 : 2 << (32 - h->netmask - 1);
 
index 0171f7502fa58d035fcda2361a6c4968acf09b7b..6283351f4eebee920c2939613ff05676b16f91ad 100644 (file)
@@ -162,7 +162,7 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
        const struct ip_set_hash *h = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct hash_ipport4_elem data = { };
-       u32 ip, ip_to = 0, p = 0, port, port_to;
+       u32 ip, ip_to, p = 0, port, port_to;
        u32 timeout = h->timeout;
        bool with_ports = false;
        int ret;
@@ -210,7 +210,7 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
                return ip_set_eexist(ret, flags) ? 0 : ret;
        }
 
-       ip = ntohl(data.ip);
+       ip_to = ip = ntohl(data.ip);
        if (tb[IPSET_ATTR_IP_TO]) {
                ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
                if (ret)
@@ -223,8 +223,7 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
                if (!cidr || cidr > 32)
                        return -IPSET_ERR_INVALID_CIDR;
                ip_set_mask_from_to(ip, ip_to, cidr);
-       } else
-               ip_to = ip;
+       }
 
        port_to = port = ntohs(data.port);
        if (with_ports && tb[IPSET_ATTR_PORT_TO]) {
index 6344ef551ec811208b79ddc54c89a1270c2419cd..6a21271c8d5a9f5da822c9789d55b761924d6da5 100644 (file)
@@ -166,7 +166,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
        const struct ip_set_hash *h = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct hash_ipportip4_elem data = { };
-       u32 ip, ip_to = 0, p = 0, port, port_to;
+       u32 ip, ip_to, p = 0, port, port_to;
        u32 timeout = h->timeout;
        bool with_ports = false;
        int ret;
@@ -218,7 +218,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
                return ip_set_eexist(ret, flags) ? 0 : ret;
        }
 
-       ip = ntohl(data.ip);
+       ip_to = ip = ntohl(data.ip);
        if (tb[IPSET_ATTR_IP_TO]) {
                ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
                if (ret)
@@ -231,8 +231,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
                if (!cidr || cidr > 32)
                        return -IPSET_ERR_INVALID_CIDR;
                ip_set_mask_from_to(ip, ip_to, cidr);
-       } else
-               ip_to = ip;
+       }
 
        port_to = port = ntohs(data.port);
        if (with_ports && tb[IPSET_ATTR_PORT_TO]) {
index cb71f9a774e7d50d67998aaaadc199a563f43f40..2d5cd4ee30eb4d5872b4aa9be7199a3d8999f6c7 100644 (file)
@@ -215,8 +215,8 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
        const struct ip_set_hash *h = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct hash_ipportnet4_elem data = { .cidr = HOST_MASK - 1 };
-       u32 ip, ip_to = 0, p = 0, port, port_to;
-       u32 ip2_from = 0, ip2_to, ip2_last, ip2;
+       u32 ip, ip_to, p = 0, port, port_to;
+       u32 ip2_from, ip2_to, ip2_last, ip2;
        u32 timeout = h->timeout;
        bool with_ports = false;
        u8 cidr;
@@ -286,6 +286,7 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
                return ip_set_eexist(ret, flags) ? 0 : ret;
        }
 
+       ip_to = ip;
        if (tb[IPSET_ATTR_IP_TO]) {
                ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
                if (ret)
@@ -306,6 +307,8 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
                if (port > port_to)
                        swap(port, port_to);
        }
+
+       ip2_to = ip2_from;
        if (tb[IPSET_ATTR_IP2_TO]) {
                ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP2_TO], &ip2_to);
                if (ret)
index 7e7198b51c068a7ea10446af4d390a9e6e2044f4..c4ee43710aab63ce34657a06ba9d26d3862a6a61 100644 (file)
@@ -2589,6 +2589,8 @@ __ip_vs_get_timeouts(struct net *net, struct ip_vs_timeout_user *u)
        struct ip_vs_proto_data *pd;
 #endif
 
+       memset(u, 0, sizeof (*u));
+
 #ifdef CONFIG_IP_VS_PROTO_TCP
        pd = ip_vs_proto_data_get(net, IPPROTO_TCP);
        u->tcp_timeout = pd->timeout_table[IP_VS_TCP_S_ESTABLISHED] / HZ;
@@ -2766,7 +2768,6 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
        {
                struct ip_vs_timeout_user t;
 
-               memset(&t, 0, sizeof(t));
                __ip_vs_get_timeouts(net, &t);
                if (copy_to_user(user, &t, sizeof(t)) != 0)
                        ret = -EFAULT;
index 1b30b0dee70818c4842b1835964ffc5f59e6b6e3..962795e839ab099ce426a27a1dcd4d887bc56eef 100644 (file)
@@ -753,7 +753,8 @@ static int callforward_do_filter(const union nf_inet_addr *src,
                                   flowi4_to_flowi(&fl1), false)) {
                        if (!afinfo->route(&init_net, (struct dst_entry **)&rt2,
                                           flowi4_to_flowi(&fl2), false)) {
-                               if (rt1->rt_gateway == rt2->rt_gateway &&
+                               if (rt_nexthop(rt1, fl1.daddr) ==
+                                   rt_nexthop(rt2, fl2.daddr) &&
                                    rt1->dst.dev  == rt2->dst.dev)
                                        ret = 1;
                                dst_release(&rt2->dst);
index 8847b4d8be06b9ad536c2bb32d9bbd3d34a7c289..701c88a20fea4c2a3ca6c9b4b2189521e13f96fe 100644 (file)
@@ -41,7 +41,8 @@ MODULE_DESCRIPTION("cttimeout: Extended Netfilter Connection Tracking timeout tu
 static LIST_HEAD(cttimeout_list);
 
 static const struct nla_policy cttimeout_nla_policy[CTA_TIMEOUT_MAX+1] = {
-       [CTA_TIMEOUT_NAME]      = { .type = NLA_NUL_STRING },
+       [CTA_TIMEOUT_NAME]      = { .type = NLA_NUL_STRING,
+                                   .len  = CTNL_TIMEOUT_NAME_MAX - 1},
        [CTA_TIMEOUT_L3PROTO]   = { .type = NLA_U16 },
        [CTA_TIMEOUT_L4PROTO]   = { .type = NLA_U8 },
        [CTA_TIMEOUT_DATA]      = { .type = NLA_NESTED },
index 16c712563860bad8b8ba03041b06cf2c386d43ab..ae7f5daeee4362bff5aee9a30a85347de70a2ccc 100644 (file)
@@ -180,9 +180,9 @@ xt_ct_set_timeout(struct nf_conn *ct, const struct xt_tgchk_param *par,
        typeof(nf_ct_timeout_find_get_hook) timeout_find_get;
        struct ctnl_timeout *timeout;
        struct nf_conn_timeout *timeout_ext;
-       const struct ipt_entry *e = par->entryinfo;
        struct nf_conntrack_l4proto *l4proto;
        int ret = 0;
+       u8 proto;
 
        rcu_read_lock();
        timeout_find_get = rcu_dereference(nf_ct_timeout_find_get_hook);
@@ -192,9 +192,11 @@ xt_ct_set_timeout(struct nf_conn *ct, const struct xt_tgchk_param *par,
                goto out;
        }
 
-       if (e->ip.invflags & IPT_INV_PROTO) {
+       proto = xt_ct_find_proto(par);
+       if (!proto) {
                ret = -EINVAL;
-               pr_info("You cannot use inversion on L4 protocol\n");
+               pr_info("You must specify a L4 protocol, and not use "
+                       "inversions on it.\n");
                goto out;
        }
 
@@ -214,7 +216,7 @@ xt_ct_set_timeout(struct nf_conn *ct, const struct xt_tgchk_param *par,
        /* Make sure the timeout policy matches any existing protocol tracker,
         * otherwise default to generic.
         */
-       l4proto = __nf_ct_l4proto_find(par->family, e->ip.proto);
+       l4proto = __nf_ct_l4proto_find(par->family, proto);
        if (timeout->l4proto->l4proto != l4proto->l4proto) {
                ret = -EINVAL;
                pr_info("Timeout policy `%s' can only be used by L4 protocol "
index ee2e5bc5a8c7b506842b6d143fba3f7aa04f3a8d..bd93e51d30acc4eded7e5e4da0898e0838dd7c43 100644 (file)
@@ -70,6 +70,7 @@ tee_tg_route4(struct sk_buff *skb, const struct xt_tee_tginfo *info)
        fl4.daddr = info->gw.ip;
        fl4.flowi4_tos = RT_TOS(iph->tos);
        fl4.flowi4_scope = RT_SCOPE_UNIVERSE;
+       fl4.flowi4_flags = FLOWI_FLAG_KNOWN_NH;
        rt = ip_route_output_key(net, &fl4);
        if (IS_ERR(rt))
                return false;
index 81aafa8e4fef894e9f24d7c460b627108884bba6..bea7464cc43fd9ced593ece7d073b66ea85d18de 100644 (file)
@@ -111,7 +111,7 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = {
                .family         = NFPROTO_IPV4,
                .table          = "nat",
                .hooks          = (1 << NF_INET_POST_ROUTING) |
-                                 (1 << NF_INET_LOCAL_OUT),
+                                 (1 << NF_INET_LOCAL_IN),
                .me             = THIS_MODULE,
        },
        {
@@ -123,7 +123,7 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = {
                .family         = NFPROTO_IPV4,
                .table          = "nat",
                .hooks          = (1 << NF_INET_PRE_ROUTING) |
-                                 (1 << NF_INET_LOCAL_IN),
+                                 (1 << NF_INET_LOCAL_OUT),
                .me             = THIS_MODULE,
        },
        {
@@ -133,7 +133,7 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = {
                .targetsize     = sizeof(struct nf_nat_range),
                .table          = "nat",
                .hooks          = (1 << NF_INET_POST_ROUTING) |
-                                 (1 << NF_INET_LOCAL_OUT),
+                                 (1 << NF_INET_LOCAL_IN),
                .me             = THIS_MODULE,
        },
        {
@@ -143,7 +143,7 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = {
                .targetsize     = sizeof(struct nf_nat_range),
                .table          = "nat",
                .hooks          = (1 << NF_INET_PRE_ROUTING) |
-                                 (1 << NF_INET_LOCAL_IN),
+                                 (1 << NF_INET_LOCAL_OUT),
                .me             = THIS_MODULE,
        },
 };
index 01e944a017a4db6be96c3d4a8e7adc8d7890b34e..4da797fa5ec57641a0fa70b5dd1e6e517884fad4 100644 (file)
@@ -138,6 +138,8 @@ static int netlink_dump(struct sock *sk);
 static DEFINE_RWLOCK(nl_table_lock);
 static atomic_t nl_table_users = ATOMIC_INIT(0);
 
+#define nl_deref_protected(X) rcu_dereference_protected(X, lockdep_is_held(&nl_table_lock));
+
 static ATOMIC_NOTIFIER_HEAD(netlink_chain);
 
 static inline u32 netlink_group_mask(u32 group)
@@ -345,6 +347,11 @@ netlink_update_listeners(struct sock *sk)
        struct hlist_node *node;
        unsigned long mask;
        unsigned int i;
+       struct listeners *listeners;
+
+       listeners = nl_deref_protected(tbl->listeners);
+       if (!listeners)
+               return;
 
        for (i = 0; i < NLGRPLONGS(tbl->groups); i++) {
                mask = 0;
@@ -352,7 +359,7 @@ netlink_update_listeners(struct sock *sk)
                        if (i < NLGRPLONGS(nlk_sk(sk)->ngroups))
                                mask |= nlk_sk(sk)->groups[i];
                }
-               tbl->listeners->masks[i] = mask;
+               listeners->masks[i] = mask;
        }
        /* this function is only called with the netlink table "grabbed", which
         * makes sure updates are visible before bind or setsockopt return. */
@@ -536,7 +543,11 @@ static int netlink_release(struct socket *sock)
        if (netlink_is_kernel(sk)) {
                BUG_ON(nl_table[sk->sk_protocol].registered == 0);
                if (--nl_table[sk->sk_protocol].registered == 0) {
-                       kfree(nl_table[sk->sk_protocol].listeners);
+                       struct listeners *old;
+
+                       old = nl_deref_protected(nl_table[sk->sk_protocol].listeners);
+                       RCU_INIT_POINTER(nl_table[sk->sk_protocol].listeners, NULL);
+                       kfree_rcu(old, rcu);
                        nl_table[sk->sk_protocol].module = NULL;
                        nl_table[sk->sk_protocol].bind = NULL;
                        nl_table[sk->sk_protocol].flags = 0;
@@ -982,7 +993,7 @@ int netlink_has_listeners(struct sock *sk, unsigned int group)
        rcu_read_lock();
        listeners = rcu_dereference(nl_table[sk->sk_protocol].listeners);
 
-       if (group - 1 < nl_table[sk->sk_protocol].groups)
+       if (listeners && group - 1 < nl_table[sk->sk_protocol].groups)
                res = test_bit(group - 1, listeners->masks);
 
        rcu_read_unlock();
@@ -1625,7 +1636,7 @@ int __netlink_change_ngroups(struct sock *sk, unsigned int groups)
                new = kzalloc(sizeof(*new) + NLGRPSZ(groups), GFP_ATOMIC);
                if (!new)
                        return -ENOMEM;
-               old = rcu_dereference_protected(tbl->listeners, 1);
+               old = nl_deref_protected(tbl->listeners);
                memcpy(new->masks, old->masks, NLGRPSZ(tbl->groups));
                rcu_assign_pointer(tbl->listeners, new);
 
index cc10d073c3381179671ef709b58baf4600e51a2b..9e8f4b2801f6099ebd5afcff20d2b5ef19e16589 100644 (file)
@@ -1210,7 +1210,7 @@ int nfc_llcp_register_device(struct nfc_dev *ndev)
        local->remote_miu = LLCP_DEFAULT_MIU;
        local->remote_lto = LLCP_DEFAULT_LTO;
 
-       list_add(&llcp_devices, &local->list);
+       list_add(&local->list, &llcp_devices);
 
        return 0;
 }
index f0dd83cff90652dc870f5bc720f9ae1a404b8931..9687fa1c2275c76cb7033a83657068406d716de7 100644 (file)
  * grp->index is the index of the group; and grp->slot_shift
  * is the shift for the corresponding (scaled) sigma_i.
  */
-#define QFQ_MAX_INDEX          19
-#define QFQ_MAX_WSHIFT         16
+#define QFQ_MAX_INDEX          24
+#define QFQ_MAX_WSHIFT         12
 
 #define        QFQ_MAX_WEIGHT          (1<<QFQ_MAX_WSHIFT)
-#define QFQ_MAX_WSUM           (2*QFQ_MAX_WEIGHT)
+#define QFQ_MAX_WSUM           (16*QFQ_MAX_WEIGHT)
 
 #define FRAC_BITS              30      /* fixed point arithmetic */
 #define ONE_FP                 (1UL << FRAC_BITS)
 #define IWSUM                  (ONE_FP/QFQ_MAX_WSUM)
 
-#define QFQ_MTU_SHIFT          11
+#define QFQ_MTU_SHIFT          16      /* to support TSO/GSO */
 #define QFQ_MIN_SLOT_SHIFT     (FRAC_BITS + QFQ_MTU_SHIFT - QFQ_MAX_INDEX)
+#define QFQ_MIN_LMAX           256     /* min possible lmax for a class */
 
 /*
  * Possible group states.  These values are used as indexes for the bitmaps
@@ -231,6 +232,32 @@ static void qfq_update_class_params(struct qfq_sched *q, struct qfq_class *cl,
        q->wsum += delta_w;
 }
 
+static void qfq_update_reactivate_class(struct qfq_sched *q,
+                                       struct qfq_class *cl,
+                                       u32 inv_w, u32 lmax, int delta_w)
+{
+       bool need_reactivation = false;
+       int i = qfq_calc_index(inv_w, lmax);
+
+       if (&q->groups[i] != cl->grp && cl->qdisc->q.qlen > 0) {
+               /*
+                * shift cl->F back, to not charge the
+                * class for the not-yet-served head
+                * packet
+                */
+               cl->F = cl->S;
+               /* remove class from its slot in the old group */
+               qfq_deactivate_class(q, cl);
+               need_reactivation = true;
+       }
+
+       qfq_update_class_params(q, cl, lmax, inv_w, delta_w);
+
+       if (need_reactivation) /* activate in new group */
+               qfq_activate_class(q, cl, qdisc_peek_len(cl->qdisc));
+}
+
+
 static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
                            struct nlattr **tca, unsigned long *arg)
 {
@@ -238,7 +265,7 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
        struct qfq_class *cl = (struct qfq_class *)*arg;
        struct nlattr *tb[TCA_QFQ_MAX + 1];
        u32 weight, lmax, inv_w;
-       int i, err;
+       int err;
        int delta_w;
 
        if (tca[TCA_OPTIONS] == NULL) {
@@ -270,16 +297,14 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
 
        if (tb[TCA_QFQ_LMAX]) {
                lmax = nla_get_u32(tb[TCA_QFQ_LMAX]);
-               if (!lmax || lmax > (1UL << QFQ_MTU_SHIFT)) {
+               if (lmax < QFQ_MIN_LMAX || lmax > (1UL << QFQ_MTU_SHIFT)) {
                        pr_notice("qfq: invalid max length %u\n", lmax);
                        return -EINVAL;
                }
        } else
-               lmax = 1UL << QFQ_MTU_SHIFT;
+               lmax = psched_mtu(qdisc_dev(sch));
 
        if (cl != NULL) {
-               bool need_reactivation = false;
-
                if (tca[TCA_RATE]) {
                        err = gen_replace_estimator(&cl->bstats, &cl->rate_est,
                                                    qdisc_root_sleeping_lock(sch),
@@ -291,24 +316,8 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
                if (lmax == cl->lmax && inv_w == cl->inv_w)
                        return 0; /* nothing to update */
 
-               i = qfq_calc_index(inv_w, lmax);
                sch_tree_lock(sch);
-               if (&q->groups[i] != cl->grp && cl->qdisc->q.qlen > 0) {
-                       /*
-                        * shift cl->F back, to not charge the
-                        * class for the not-yet-served head
-                        * packet
-                        */
-                       cl->F = cl->S;
-                       /* remove class from its slot in the old group */
-                       qfq_deactivate_class(q, cl);
-                       need_reactivation = true;
-               }
-
-               qfq_update_class_params(q, cl, lmax, inv_w, delta_w);
-
-               if (need_reactivation) /* activate in new group */
-                       qfq_activate_class(q, cl, qdisc_peek_len(cl->qdisc));
+               qfq_update_reactivate_class(q, cl, inv_w, lmax, delta_w);
                sch_tree_unlock(sch);
 
                return 0;
@@ -663,15 +672,48 @@ static void qfq_make_eligible(struct qfq_sched *q, u64 old_V)
 
 
 /*
- * XXX we should make sure that slot becomes less than 32.
- * This is guaranteed by the input values.
- * roundedS is always cl->S rounded on grp->slot_shift bits.
+ * If the weight and lmax (max_pkt_size) of the classes do not change,
+ * then QFQ guarantees that the slot index is never higher than
+ * 2 + ((1<<QFQ_MTU_SHIFT)/QFQ_MIN_LMAX) * (QFQ_MAX_WEIGHT/QFQ_MAX_WSUM).
+ *
+ * With the current values of the above constants, the index is
+ * then guaranteed to never be higher than 2 + 256 * (1 / 16) = 18.
+ *
+ * When the weight of a class is increased or the lmax of the class is
+ * decreased, a new class with smaller slot size may happen to be
+ * activated. The activation of this class should be properly delayed
+ * to when the service of the class has finished in the ideal system
+ * tracked by QFQ. If the activation of the class is not delayed to
+ * this reference time instant, then this class may be unjustly served
+ * before other classes waiting for service. This may cause
+ * (unfrequently) the above bound to the slot index to be violated for
+ * some of these unlucky classes.
+ *
+ * Instead of delaying the activation of the new class, which is quite
+ * complex, the following inaccurate but simple solution is used: if
+ * the slot index is higher than QFQ_MAX_SLOTS-2, then the timestamps
+ * of the class are shifted backward so as to let the slot index
+ * become equal to QFQ_MAX_SLOTS-2. This threshold is used because, if
+ * the slot index is above it, then the data structure implementing
+ * the bucket list either gets immediately corrupted or may get
+ * corrupted on a possible next packet arrival that causes the start
+ * time of the group to be shifted backward.
  */
 static void qfq_slot_insert(struct qfq_group *grp, struct qfq_class *cl,
                            u64 roundedS)
 {
        u64 slot = (roundedS - grp->S) >> grp->slot_shift;
-       unsigned int i = (grp->front + slot) % QFQ_MAX_SLOTS;
+       unsigned int i; /* slot index in the bucket list */
+
+       if (unlikely(slot > QFQ_MAX_SLOTS - 2)) {
+               u64 deltaS = roundedS - grp->S -
+                       ((u64)(QFQ_MAX_SLOTS - 2)<<grp->slot_shift);
+               cl->S -= deltaS;
+               cl->F -= deltaS;
+               slot = QFQ_MAX_SLOTS - 2;
+       }
+
+       i = (grp->front + slot) % QFQ_MAX_SLOTS;
 
        hlist_add_head(&cl->next, &grp->slots[i]);
        __set_bit(slot, &grp->full_slots);
@@ -892,6 +934,13 @@ static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch)
        }
        pr_debug("qfq_enqueue: cl = %x\n", cl->common.classid);
 
+       if (unlikely(cl->lmax < qdisc_pkt_len(skb))) {
+               pr_debug("qfq: increasing maxpkt from %u to %u for class %u",
+                         cl->lmax, qdisc_pkt_len(skb), cl->common.classid);
+               qfq_update_reactivate_class(q, cl, cl->inv_w,
+                                           qdisc_pkt_len(skb), 0);
+       }
+
        err = qdisc_enqueue(skb, cl->qdisc);
        if (unlikely(err != NET_XMIT_SUCCESS)) {
                pr_debug("qfq_enqueue: enqueue failed %d\n", err);
index c3bea269faf4e6228143f70c6422046842922177..9966e7b16451230319f63d601284281970226799 100644 (file)
@@ -102,7 +102,7 @@ static const struct file_operations sctp_snmp_seq_fops = {
        .open    = sctp_snmp_seq_open,
        .read    = seq_read,
        .llseek  = seq_lseek,
-       .release = single_release,
+       .release = single_release_net,
 };
 
 /* Set up the proc fs entry for 'snmp' object. */
@@ -251,7 +251,7 @@ static const struct file_operations sctp_eps_seq_fops = {
        .open    = sctp_eps_seq_open,
        .read    = seq_read,
        .llseek  = seq_lseek,
-       .release = seq_release,
+       .release = seq_release_net,
 };
 
 /* Set up the proc fs entry for 'eps' object. */
@@ -372,7 +372,7 @@ static const struct file_operations sctp_assocs_seq_fops = {
        .open    = sctp_assocs_seq_open,
        .read    = seq_read,
        .llseek  = seq_lseek,
-       .release = seq_release,
+       .release = seq_release_net,
 };
 
 /* Set up the proc fs entry for 'assocs' object. */
@@ -517,7 +517,7 @@ static const struct file_operations sctp_remaddr_seq_fops = {
        .open = sctp_remaddr_seq_open,
        .read = seq_read,
        .llseek = seq_lseek,
-       .release = seq_release,
+       .release = seq_release_net,
 };
 
 int __net_init sctp_remaddr_proc_init(struct net *net)
index 59d16ea927f0f83d706d3a59c79d13be0a95c1e8..a60d1f8b41c5e2330e837265e175202aba322fcb 100644 (file)
@@ -974,7 +974,7 @@ SCTP_STATIC int sctp_setsockopt_bindx(struct sock* sk,
        void *addr_buf;
        struct sctp_af *af;
 
-       SCTP_DEBUG_PRINTK("sctp_setsocktopt_bindx: sk %p addrs %p"
+       SCTP_DEBUG_PRINTK("sctp_setsockopt_bindx: sk %p addrs %p"
                          " addrs_size %d opt %d\n", sk, addrs, addrs_size, op);
 
        if (unlikely(addrs_size <= 0))
index 5a3d675d2f2f9f3971b4707474cc511ad328ac2a..a9c0bbccad6bfb787b4ff1630a1eb7a28918e634 100644 (file)
@@ -172,7 +172,7 @@ out_free:
                xprt_free_allocation(req);
 
        dprintk("RPC:       setup backchannel transport failed\n");
-       return -1;
+       return -ENOMEM;
 }
 EXPORT_SYMBOL_GPL(xprt_setup_backchannel);
 
index aaaadfbe36e9525a42a86e1f649bf66e59eb7274..75853cabf4c97b153873eda4ce67cd228581fd15 100644 (file)
@@ -254,7 +254,6 @@ struct sock_xprt {
        void                    (*old_data_ready)(struct sock *, int);
        void                    (*old_state_change)(struct sock *);
        void                    (*old_write_space)(struct sock *);
-       void                    (*old_error_report)(struct sock *);
 };
 
 /*
@@ -737,10 +736,10 @@ static int xs_tcp_send_request(struct rpc_task *task)
                dprintk("RPC:       sendmsg returned unrecognized error %d\n",
                        -status);
        case -ECONNRESET:
-       case -EPIPE:
                xs_tcp_shutdown(xprt);
        case -ECONNREFUSED:
        case -ENOTCONN:
+       case -EPIPE:
                clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags);
        }
 
@@ -781,7 +780,6 @@ static void xs_save_old_callbacks(struct sock_xprt *transport, struct sock *sk)
        transport->old_data_ready = sk->sk_data_ready;
        transport->old_state_change = sk->sk_state_change;
        transport->old_write_space = sk->sk_write_space;
-       transport->old_error_report = sk->sk_error_report;
 }
 
 static void xs_restore_old_callbacks(struct sock_xprt *transport, struct sock *sk)
@@ -789,7 +787,6 @@ static void xs_restore_old_callbacks(struct sock_xprt *transport, struct sock *s
        sk->sk_data_ready = transport->old_data_ready;
        sk->sk_state_change = transport->old_state_change;
        sk->sk_write_space = transport->old_write_space;
-       sk->sk_error_report = transport->old_error_report;
 }
 
 static void xs_reset_transport(struct sock_xprt *transport)
@@ -1453,7 +1450,7 @@ static void xs_tcp_cancel_linger_timeout(struct rpc_xprt *xprt)
        xprt_clear_connecting(xprt);
 }
 
-static void xs_sock_mark_closed(struct rpc_xprt *xprt)
+static void xs_sock_reset_connection_flags(struct rpc_xprt *xprt)
 {
        smp_mb__before_clear_bit();
        clear_bit(XPRT_CONNECTION_ABORT, &xprt->state);
@@ -1461,6 +1458,11 @@ static void xs_sock_mark_closed(struct rpc_xprt *xprt)
        clear_bit(XPRT_CLOSE_WAIT, &xprt->state);
        clear_bit(XPRT_CLOSING, &xprt->state);
        smp_mb__after_clear_bit();
+}
+
+static void xs_sock_mark_closed(struct rpc_xprt *xprt)
+{
+       xs_sock_reset_connection_flags(xprt);
        /* Mark transport as closed and wake up all pending tasks */
        xprt_disconnect_done(xprt);
 }
@@ -1516,6 +1518,7 @@ static void xs_tcp_state_change(struct sock *sk)
        case TCP_CLOSE_WAIT:
                /* The server initiated a shutdown of the socket */
                xprt->connect_cookie++;
+               clear_bit(XPRT_CONNECTED, &xprt->state);
                xs_tcp_force_close(xprt);
        case TCP_CLOSING:
                /*
@@ -1540,25 +1543,6 @@ static void xs_tcp_state_change(struct sock *sk)
        read_unlock_bh(&sk->sk_callback_lock);
 }
 
-/**
- * xs_error_report - callback mainly for catching socket errors
- * @sk: socket
- */
-static void xs_error_report(struct sock *sk)
-{
-       struct rpc_xprt *xprt;
-
-       read_lock_bh(&sk->sk_callback_lock);
-       if (!(xprt = xprt_from_sock(sk)))
-               goto out;
-       dprintk("RPC:       %s client %p...\n"
-                       "RPC:       error %d\n",
-                       __func__, xprt, sk->sk_err);
-       xprt_wake_pending_tasks(xprt, -EAGAIN);
-out:
-       read_unlock_bh(&sk->sk_callback_lock);
-}
-
 static void xs_write_space(struct sock *sk)
 {
        struct socket *sock;
@@ -1858,7 +1842,6 @@ static int xs_local_finish_connecting(struct rpc_xprt *xprt,
                sk->sk_user_data = xprt;
                sk->sk_data_ready = xs_local_data_ready;
                sk->sk_write_space = xs_udp_write_space;
-               sk->sk_error_report = xs_error_report;
                sk->sk_allocation = GFP_ATOMIC;
 
                xprt_clear_connected(xprt);
@@ -1983,7 +1966,6 @@ static void xs_udp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
                sk->sk_user_data = xprt;
                sk->sk_data_ready = xs_udp_data_ready;
                sk->sk_write_space = xs_udp_write_space;
-               sk->sk_error_report = xs_error_report;
                sk->sk_no_check = UDP_CSUM_NORCV;
                sk->sk_allocation = GFP_ATOMIC;
 
@@ -2050,10 +2032,8 @@ static void xs_abort_connection(struct sock_xprt *transport)
        any.sa_family = AF_UNSPEC;
        result = kernel_connect(transport->sock, &any, sizeof(any), 0);
        if (!result)
-               xs_sock_mark_closed(&transport->xprt);
-       else
-               dprintk("RPC:       AF_UNSPEC connect return code %d\n",
-                               result);
+               xs_sock_reset_connection_flags(&transport->xprt);
+       dprintk("RPC:       AF_UNSPEC connect return code %d\n", result);
 }
 
 static void xs_tcp_reuse_connection(struct sock_xprt *transport)
@@ -2098,7 +2078,6 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
                sk->sk_data_ready = xs_tcp_data_ready;
                sk->sk_state_change = xs_tcp_state_change;
                sk->sk_write_space = xs_tcp_write_space;
-               sk->sk_error_report = xs_error_report;
                sk->sk_allocation = GFP_ATOMIC;
 
                /* socket options */
index 111ff8300ae52ed43226f3ec8ab079bdb2e00b9c..b36f0fcd9bdfe76d04adf287687190ada3e9ccca 100644 (file)
@@ -116,7 +116,6 @@ void tipc_handler_stop(void)
                return;
 
        handler_enabled = 0;
-       tasklet_disable(&tipc_tasklet);
        tasklet_kill(&tipc_tasklet);
 
        spin_lock_bh(&qitem_lock);
index 443d4d7deea299c7e997045d22d8b2b146d2c877..3f72530520883ae4aa510516bf7a4ce641c646d8 100644 (file)
@@ -526,8 +526,7 @@ int wiphy_register(struct wiphy *wiphy)
                for (i = 0; i < sband->n_channels; i++) {
                        sband->channels[i].orig_flags =
                                sband->channels[i].flags;
-                       sband->channels[i].orig_mag =
-                               sband->channels[i].max_antenna_gain;
+                       sband->channels[i].orig_mag = INT_MAX;
                        sband->channels[i].orig_mpwr =
                                sband->channels[i].max_power;
                        sband->channels[i].band = band;
index 8016fee0752b0325a20409b7b1b93b5433c73872..904a7f36832531cbe2fa3d50f220b94775eaf8a9 100644 (file)
@@ -457,20 +457,14 @@ int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
                .reason_code = reason,
                .ie = ie,
                .ie_len = ie_len,
+               .local_state_change = local_state_change,
        };
 
        ASSERT_WDEV_LOCK(wdev);
 
-       if (local_state_change) {
-               if (wdev->current_bss &&
-                   ether_addr_equal(wdev->current_bss->pub.bssid, bssid)) {
-                       cfg80211_unhold_bss(wdev->current_bss);
-                       cfg80211_put_bss(&wdev->current_bss->pub);
-                       wdev->current_bss = NULL;
-               }
-
+       if (local_state_change && (!wdev->current_bss ||
+           !ether_addr_equal(wdev->current_bss->pub.bssid, bssid)))
                return 0;
-       }
 
        return rdev->ops->deauth(&rdev->wiphy, dev, &req);
 }
index 3b8cbbc214db563ba962ecda1e49fe6929c263cc..b75756b05af76374cf62b432249be933881bc594 100644 (file)
@@ -141,9 +141,8 @@ static const struct ieee80211_regdomain world_regdom = {
        .reg_rules = {
                /* IEEE 802.11b/g, channels 1..11 */
                REG_RULE(2412-10, 2462+10, 40, 6, 20, 0),
-               /* IEEE 802.11b/g, channels 12..13. No HT40
-                * channel fits here. */
-               REG_RULE(2467-10, 2472+10, 20, 6, 20,
+               /* IEEE 802.11b/g, channels 12..13. */
+               REG_RULE(2467-10, 2472+10, 40, 6, 20,
                        NL80211_RRF_PASSIVE_SCAN |
                        NL80211_RRF_NO_IBSS),
                /* IEEE 802.11 channel 14 - Only JP enables
@@ -908,7 +907,7 @@ static void handle_channel(struct wiphy *wiphy,
                        map_regdom_flags(reg_rule->flags) | bw_flags;
                chan->max_antenna_gain = chan->orig_mag =
                        (int) MBI_TO_DBI(power_rule->max_antenna_gain);
-               chan->max_power = chan->orig_mpwr =
+               chan->max_reg_power = chan->max_power = chan->orig_mpwr =
                        (int) MBM_TO_DBM(power_rule->max_eirp);
                return;
        }
@@ -1331,7 +1330,8 @@ static void handle_channel_custom(struct wiphy *wiphy,
 
        chan->flags |= map_regdom_flags(reg_rule->flags) | bw_flags;
        chan->max_antenna_gain = (int) MBI_TO_DBI(power_rule->max_antenna_gain);
-       chan->max_power = (int) MBM_TO_DBM(power_rule->max_eirp);
+       chan->max_reg_power = chan->max_power =
+               (int) MBM_TO_DBM(power_rule->max_eirp);
 }
 
 static void handle_band_custom(struct wiphy *wiphy, enum ieee80211_band band,
index ef35f4ef2aa623d16f3556a5e3f4709fba363db4..2762e8329986afd57efd3f7735d1904e221ab05e 100644 (file)
@@ -309,23 +309,21 @@ unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb)
 }
 EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb);
 
-static int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr)
+unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr)
 {
        int ae = meshhdr->flags & MESH_FLAGS_AE;
-       /* 7.1.3.5a.2 */
+       /* 802.11-2012, 8.2.4.7.3 */
        switch (ae) {
+       default:
        case 0:
                return 6;
        case MESH_FLAGS_AE_A4:
                return 12;
        case MESH_FLAGS_AE_A5_A6:
                return 18;
-       case (MESH_FLAGS_AE_A4 | MESH_FLAGS_AE_A5_A6):
-               return 24;
-       default:
-               return 6;
        }
 }
+EXPORT_SYMBOL(ieee80211_get_mesh_hdrlen);
 
 int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
                           enum nl80211_iftype iftype)
@@ -373,6 +371,8 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
                        /* make sure meshdr->flags is on the linear part */
                        if (!pskb_may_pull(skb, hdrlen + 1))
                                return -1;
+                       if (meshdr->flags & MESH_FLAGS_AE_A4)
+                               return -1;
                        if (meshdr->flags & MESH_FLAGS_AE_A5_A6) {
                                skb_copy_bits(skb, hdrlen +
                                        offsetof(struct ieee80211s_hdr, eaddr1),
@@ -397,6 +397,8 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
                        /* make sure meshdr->flags is on the linear part */
                        if (!pskb_may_pull(skb, hdrlen + 1))
                                return -1;
+                       if (meshdr->flags & MESH_FLAGS_AE_A5_A6)
+                               return -1;
                        if (meshdr->flags & MESH_FLAGS_AE_A4)
                                skb_copy_bits(skb, hdrlen +
                                        offsetof(struct ieee80211s_hdr, eaddr1),
index dda4b2b619275517826af60a61de2edb731f5524..ecbb44797e28226e85027c277435d053415aec8c 100644 (file)
@@ -16,8 +16,9 @@ PHONY += $(modules)
 __modinst: $(modules)
        @:
 
+# Don't stop modules_install if we can't sign external modules.
 quiet_cmd_modules_install = INSTALL $@
-      cmd_modules_install = mkdir -p $(2); cp $@ $(2) ; $(mod_strip_cmd) $(2)/$(notdir $@) ; $(mod_sign_cmd) $(2)/$(notdir $@)
+      cmd_modules_install = mkdir -p $(2); cp $@ $(2) ; $(mod_strip_cmd) $(2)/$(notdir $@) ; $(mod_sign_cmd) $(2)/$(notdir $@) $(patsubst %,|| true,$(KBUILD_EXTMOD))
 
 # Modules built outside the kernel source tree go into extra by default
 INSTALL_MOD_DIR ?= extra
index 21a9f5de0a2120c26b5f3bd0e70529078766a247..f18750e3bd6c290b285464b193d7d65972b6de19 100755 (executable)
@@ -1890,8 +1890,10 @@ sub process {
                }
 
                if ($realfile =~ m@^(drivers/net/|net/)@ &&
-                   $rawline !~ m@^\+[ \t]*(\/\*|\*\/)@ &&
-                   $rawline =~ m@^\+[ \t]*.+\*\/[ \t]*$@) {
+                   $rawline !~ m@^\+[ \t]*\*/[ \t]*$@ &&       #trailing */
+                   $rawline !~ m@^\+.*/\*.*\*/[ \t]*$@ &&      #inline /*...*/
+                   $rawline !~ m@^\+.*\*{2,}/[ \t]*$@ &&       #trailing **/
+                   $rawline =~ m@^\+[ \t]*.+\*\/[ \t]*$@) {    #non blank */
                        WARN("NETWORKING_BLOCK_COMMENT_STYLE",
                             "networking block comments put the trailing */ on a separate line\n" . $herecurr);
                }
index bd2e098955532a26a3935e44ad58283598cbf673..cdd48600e02a9bd842f2e43ab6b7f263949451ec 100644 (file)
@@ -12,7 +12,7 @@ extern "C" {
 
 #include <assert.h>
 #include <stdio.h>
-#include <sys/queue.h>
+#include "list.h"
 #ifndef __cplusplus
 #include <stdbool.h>
 #endif
@@ -175,12 +175,11 @@ struct menu {
 #define MENU_ROOT              0x0002
 
 struct jump_key {
-       CIRCLEQ_ENTRY(jump_key) entries;
+       struct list_head entries;
        size_t offset;
        struct menu *target;
        int index;
 };
-CIRCLEQ_HEAD(jk_head, jump_key);
 
 #define JUMP_NB                        9
 
diff --git a/scripts/kconfig/list.h b/scripts/kconfig/list.h
new file mode 100644 (file)
index 0000000..0ae730b
--- /dev/null
@@ -0,0 +1,91 @@
+#ifndef LIST_H
+#define LIST_H
+
+/*
+ * Copied from include/linux/...
+ */
+
+#undef offsetof
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+
+/**
+ * container_of - cast a member of a structure out to the containing structure
+ * @ptr:        the pointer to the member.
+ * @type:       the type of the container struct this is embedded in.
+ * @member:     the name of the member within the struct.
+ *
+ */
+#define container_of(ptr, type, member) ({                      \
+       const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
+       (type *)( (char *)__mptr - offsetof(type,member) );})
+
+
+struct list_head {
+       struct list_head *next, *prev;
+};
+
+
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define LIST_HEAD(name) \
+       struct list_head name = LIST_HEAD_INIT(name)
+
+/**
+ * list_entry - get the struct for this entry
+ * @ptr:       the &struct list_head pointer.
+ * @type:      the type of the struct this is embedded in.
+ * @member:    the name of the list_struct within the struct.
+ */
+#define list_entry(ptr, type, member) \
+       container_of(ptr, type, member)
+
+/**
+ * list_for_each_entry -       iterate over list of given type
+ * @pos:       the type * to use as a loop cursor.
+ * @head:      the head for your list.
+ * @member:    the name of the list_struct within the struct.
+ */
+#define list_for_each_entry(pos, head, member)                         \
+       for (pos = list_entry((head)->next, typeof(*pos), member);      \
+            &pos->member != (head);    \
+            pos = list_entry(pos->member.next, typeof(*pos), member))
+
+/**
+ * list_empty - tests whether a list is empty
+ * @head: the list to test.
+ */
+static inline int list_empty(const struct list_head *head)
+{
+       return head->next == head;
+}
+
+/*
+ * Insert a new entry between two known consecutive entries.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_add(struct list_head *_new,
+                             struct list_head *prev,
+                             struct list_head *next)
+{
+       next->prev = _new;
+       _new->next = next;
+       _new->prev = prev;
+       prev->next = _new;
+}
+
+/**
+ * list_add_tail - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it before
+ *
+ * Insert a new entry before the specified head.
+ * This is useful for implementing queues.
+ */
+static inline void list_add_tail(struct list_head *_new, struct list_head *head)
+{
+       __list_add(_new, head->prev, head);
+}
+
+#endif
index 1d1c08537f1e59b2cab76bd88437489fcbea393b..ef1a7381f956d5e7d0ebb8d3ba6af2361a0c3c74 100644 (file)
@@ -21,9 +21,9 @@ P(menu_get_root_menu,struct menu *,(struct menu *menu));
 P(menu_get_parent_menu,struct menu *,(struct menu *menu));
 P(menu_has_help,bool,(struct menu *menu));
 P(menu_get_help,const char *,(struct menu *menu));
-P(get_symbol_str, void, (struct gstr *r, struct symbol *sym, struct jk_head
+P(get_symbol_str, void, (struct gstr *r, struct symbol *sym, struct list_head
                         *head));
-P(get_relations_str, struct gstr, (struct symbol **sym_arr, struct jk_head
+P(get_relations_str, struct gstr, (struct symbol **sym_arr, struct list_head
                                   *head));
 P(menu_get_ext_help,void,(struct menu *menu, struct gstr *help));
 
index 48f67448af7b67cf6c8df7394702a65767891992..53975cf876083ecba455a7033222b2ccc3690686 100644 (file)
@@ -312,7 +312,7 @@ static void set_config_filename(const char *config_filename)
 
 
 struct search_data {
-       struct jk_head *head;
+       struct list_head *head;
        struct menu **targets;
        int *keys;
 };
@@ -323,7 +323,7 @@ static void update_text(char *buf, size_t start, size_t end, void *_data)
        struct jump_key *pos;
        int k = 0;
 
-       CIRCLEQ_FOREACH(pos, data->head, entries) {
+       list_for_each_entry(pos, data->head, entries) {
                if (pos->offset >= start && pos->offset < end) {
                        char header[4];
 
@@ -375,7 +375,7 @@ again:
 
        sym_arr = sym_re_search(dialog_input);
        do {
-               struct jk_head head = CIRCLEQ_HEAD_INITIALIZER(head);
+               LIST_HEAD(head);
                struct menu *targets[JUMP_NB];
                int keys[JUMP_NB + 1], i;
                struct search_data data = {
index a3cade659f89cb5f67828b797ae49b9311bf1d98..e98a05c8e50882d3b2833a2f4d05761dcffd22d3 100644 (file)
@@ -508,7 +508,7 @@ const char *menu_get_help(struct menu *menu)
 }
 
 static void get_prompt_str(struct gstr *r, struct property *prop,
-                          struct jk_head *head)
+                          struct list_head *head)
 {
        int i, j;
        struct menu *submenu[8], *menu, *location = NULL;
@@ -544,12 +544,13 @@ static void get_prompt_str(struct gstr *r, struct property *prop,
                } else
                        jump->target = location;
 
-               if (CIRCLEQ_EMPTY(head))
+               if (list_empty(head))
                        jump->index = 0;
                else
-                       jump->index = CIRCLEQ_LAST(head)->index + 1;
+                       jump->index = list_entry(head->prev, struct jump_key,
+                                                entries)->index + 1;
 
-               CIRCLEQ_INSERT_TAIL(head, jump, entries);
+               list_add_tail(&jump->entries, head);
        }
 
        if (i > 0) {
@@ -573,7 +574,8 @@ static void get_prompt_str(struct gstr *r, struct property *prop,
 /*
  * head is optional and may be NULL
  */
-void get_symbol_str(struct gstr *r, struct symbol *sym, struct jk_head *head)
+void get_symbol_str(struct gstr *r, struct symbol *sym,
+                   struct list_head *head)
 {
        bool hit;
        struct property *prop;
@@ -612,7 +614,7 @@ void get_symbol_str(struct gstr *r, struct symbol *sym, struct jk_head *head)
        str_append(r, "\n\n");
 }
 
-struct gstr get_relations_str(struct symbol **sym_arr, struct jk_head *head)
+struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head)
 {
        struct symbol *sym;
        struct gstr res = str_new();
index 87ca59d36e7ef64754892be3d842ac614bf2a9d5..974a20b661b79c6385f5fbc0cd40cd57e2a7ef94 100755 (executable)
@@ -156,12 +156,12 @@ sub asn1_extract($$@)
 
        if ($l == 0x1) {
            $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1));
-       } elsif ($l = 0x2) {
+       } elsif ($l == 0x2) {
            $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0], 2));
-       } elsif ($l = 0x3) {
+       } elsif ($l == 0x3) {
            $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1)) << 16;
            $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0] + 1, 2));
-       } elsif ($l = 0x4) {
+       } elsif ($l == 0x4) {
            $len = unpack("N", substr(${$cursor->[2]}, $cursor->[0], 4));
        } else {
            die $x509, ": ", $cursor->[0], ": ASN.1 element too long (", $l, ")\n";
index cf5fd220309be40d597ac7ca02e0d61658cd8eee..813200384d97cfc7f06a76e9b2f6286be7dfa7ab 100644 (file)
@@ -724,6 +724,8 @@ fail:
  */
 static void free_profile(struct aa_profile *profile)
 {
+       struct aa_profile *p;
+
        AA_DEBUG("%s(%p)\n", __func__, profile);
 
        if (!profile)
@@ -751,7 +753,27 @@ static void free_profile(struct aa_profile *profile)
        aa_put_dfa(profile->xmatch);
        aa_put_dfa(profile->policy.dfa);
 
-       aa_put_profile(profile->replacedby);
+       /* put the profile reference for replacedby, but not via
+        * put_profile(kref_put).
+        * replacedby can form a long chain that can result in cascading
+        * frees that blows the stack because kref_put makes a nested fn
+        * call (it looks like recursion, with free_profile calling
+        * free_profile) for each profile in the chain lp#1056078.
+        */
+       for (p = profile->replacedby; p; ) {
+               if (atomic_dec_and_test(&p->base.count.refcount)) {
+                       /* no more refs on p, grab its replacedby */
+                       struct aa_profile *next = p->replacedby;
+                       /* break the chain */
+                       p->replacedby = NULL;
+                       /* now free p, chain is broken */
+                       free_profile(p);
+
+                       /* follow up with next profile in the chain */
+                       p = next;
+               } else
+                       break;
+       }
 
        kzfree(profile);
 }
index 44dfc415a379afc9c327388664e949bfcc855bcb..b08d20c66c2e17e0fa8333984df8eb4a82595e0b 100644 (file)
@@ -42,7 +42,10 @@ struct dev_exception_item {
 struct dev_cgroup {
        struct cgroup_subsys_state css;
        struct list_head exceptions;
-       bool deny_all;
+       enum {
+               DEVCG_DEFAULT_ALLOW,
+               DEVCG_DEFAULT_DENY,
+       } behavior;
 };
 
 static inline struct dev_cgroup *css_to_devcgroup(struct cgroup_subsys_state *s)
@@ -161,8 +164,8 @@ static void dev_exception_clean(struct dev_cgroup *dev_cgroup)
        struct dev_exception_item *ex, *tmp;
 
        list_for_each_entry_safe(ex, tmp, &dev_cgroup->exceptions, list) {
-               list_del(&ex->list);
-               kfree(ex);
+               list_del_rcu(&ex->list);
+               kfree_rcu(ex, rcu);
        }
 }
 
@@ -182,13 +185,13 @@ static struct cgroup_subsys_state *devcgroup_create(struct cgroup *cgroup)
        parent_cgroup = cgroup->parent;
 
        if (parent_cgroup == NULL)
-               dev_cgroup->deny_all = false;
+               dev_cgroup->behavior = DEVCG_DEFAULT_ALLOW;
        else {
                parent_dev_cgroup = cgroup_to_devcgroup(parent_cgroup);
                mutex_lock(&devcgroup_mutex);
                ret = dev_exceptions_copy(&dev_cgroup->exceptions,
                                          &parent_dev_cgroup->exceptions);
-               dev_cgroup->deny_all = parent_dev_cgroup->deny_all;
+               dev_cgroup->behavior = parent_dev_cgroup->behavior;
                mutex_unlock(&devcgroup_mutex);
                if (ret) {
                        kfree(dev_cgroup);
@@ -260,7 +263,7 @@ static int devcgroup_seq_read(struct cgroup *cgroup, struct cftype *cft,
         * - List the exceptions in case the default policy is to deny
         * This way, the file remains as a "whitelist of devices"
         */
-       if (devcgroup->deny_all == false) {
+       if (devcgroup->behavior == DEVCG_DEFAULT_ALLOW) {
                set_access(acc, ACC_MASK);
                set_majmin(maj, ~0);
                set_majmin(min, ~0);
@@ -295,7 +298,7 @@ static int may_access(struct dev_cgroup *dev_cgroup,
        struct dev_exception_item *ex;
        bool match = false;
 
-       list_for_each_entry(ex, &dev_cgroup->exceptions, list) {
+       list_for_each_entry_rcu(ex, &dev_cgroup->exceptions, list) {
                if ((refex->type & DEV_BLOCK) && !(ex->type & DEV_BLOCK))
                        continue;
                if ((refex->type & DEV_CHAR) && !(ex->type & DEV_CHAR))
@@ -314,12 +317,12 @@ static int may_access(struct dev_cgroup *dev_cgroup,
         * In two cases we'll consider this new exception valid:
         * - the dev cgroup has its default policy to allow + exception list:
         *   the new exception should *not* match any of the exceptions
-        *   (!deny_all, !match)
+        *   (behavior == DEVCG_DEFAULT_ALLOW, !match)
         * - the dev cgroup has its default policy to deny + exception list:
         *   the new exception *should* match the exceptions
-        *   (deny_all, match)
+        *   (behavior == DEVCG_DEFAULT_DENY, match)
         */
-       if (dev_cgroup->deny_all == match)
+       if ((dev_cgroup->behavior == DEVCG_DEFAULT_DENY) == match)
                return 1;
        return 0;
 }
@@ -341,6 +344,19 @@ static int parent_has_perm(struct dev_cgroup *childcg,
        return may_access(parent, ex);
 }
 
+/**
+ * may_allow_all - checks if it's possible to change the behavior to
+ *                allow based on parent's rules.
+ * @parent: device cgroup's parent
+ * returns: != 0 in case it's allowed, 0 otherwise
+ */
+static inline int may_allow_all(struct dev_cgroup *parent)
+{
+       if (!parent)
+               return 1;
+       return parent->behavior == DEVCG_DEFAULT_ALLOW;
+}
+
 /*
  * Modify the exception list using allow/deny rules.
  * CAP_SYS_ADMIN is needed for this.  It's at least separate from CAP_MKNOD
@@ -358,13 +374,18 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,
                                   int filetype, const char *buffer)
 {
        const char *b;
-       char *endp;
-       int count;
+       char temp[12];          /* 11 + 1 characters needed for a u32 */
+       int count, rc;
        struct dev_exception_item ex;
+       struct cgroup *p = devcgroup->css.cgroup;
+       struct dev_cgroup *parent = NULL;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
+       if (p->parent)
+               parent = cgroup_to_devcgroup(p->parent);
+
        memset(&ex, 0, sizeof(ex));
        b = buffer;
 
@@ -372,14 +393,21 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,
        case 'a':
                switch (filetype) {
                case DEVCG_ALLOW:
-                       if (!parent_has_perm(devcgroup, &ex))
+                       if (!may_allow_all(parent))
                                return -EPERM;
                        dev_exception_clean(devcgroup);
-                       devcgroup->deny_all = false;
+                       devcgroup->behavior = DEVCG_DEFAULT_ALLOW;
+                       if (!parent)
+                               break;
+
+                       rc = dev_exceptions_copy(&devcgroup->exceptions,
+                                                &parent->exceptions);
+                       if (rc)
+                               return rc;
                        break;
                case DEVCG_DENY:
                        dev_exception_clean(devcgroup);
-                       devcgroup->deny_all = true;
+                       devcgroup->behavior = DEVCG_DEFAULT_DENY;
                        break;
                default:
                        return -EINVAL;
@@ -402,8 +430,16 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,
                ex.major = ~0;
                b++;
        } else if (isdigit(*b)) {
-               ex.major = simple_strtoul(b, &endp, 10);
-               b = endp;
+               memset(temp, 0, sizeof(temp));
+               for (count = 0; count < sizeof(temp) - 1; count++) {
+                       temp[count] = *b;
+                       b++;
+                       if (!isdigit(*b))
+                               break;
+               }
+               rc = kstrtou32(temp, 10, &ex.major);
+               if (rc)
+                       return -EINVAL;
        } else {
                return -EINVAL;
        }
@@ -416,8 +452,16 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,
                ex.minor = ~0;
                b++;
        } else if (isdigit(*b)) {
-               ex.minor = simple_strtoul(b, &endp, 10);
-               b = endp;
+               memset(temp, 0, sizeof(temp));
+               for (count = 0; count < sizeof(temp) - 1; count++) {
+                       temp[count] = *b;
+                       b++;
+                       if (!isdigit(*b))
+                               break;
+               }
+               rc = kstrtou32(temp, 10, &ex.minor);
+               if (rc)
+                       return -EINVAL;
        } else {
                return -EINVAL;
        }
@@ -452,7 +496,7 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,
                 * an matching exception instead. And be silent about it: we
                 * don't want to break compatibility
                 */
-               if (devcgroup->deny_all == false) {
+               if (devcgroup->behavior == DEVCG_DEFAULT_ALLOW) {
                        dev_exception_rm(devcgroup, &ex);
                        return 0;
                }
@@ -463,7 +507,7 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,
                 * an matching exception instead. And be silent about it: we
                 * don't want to break compatibility
                 */
-               if (devcgroup->deny_all == true) {
+               if (devcgroup->behavior == DEVCG_DEFAULT_DENY) {
                        dev_exception_rm(devcgroup, &ex);
                        return 0;
                }
@@ -533,10 +577,10 @@ struct cgroup_subsys devices_subsys = {
  *
  * returns 0 on success, -EPERM case the operation is not permitted
  */
-static int __devcgroup_check_permission(struct dev_cgroup *dev_cgroup,
-                                       short type, u32 major, u32 minor,
+static int __devcgroup_check_permission(short type, u32 major, u32 minor,
                                        short access)
 {
+       struct dev_cgroup *dev_cgroup;
        struct dev_exception_item ex;
        int rc;
 
@@ -547,6 +591,7 @@ static int __devcgroup_check_permission(struct dev_cgroup *dev_cgroup,
        ex.access = access;
 
        rcu_read_lock();
+       dev_cgroup = task_devcgroup(current);
        rc = may_access(dev_cgroup, &ex);
        rcu_read_unlock();
 
@@ -558,7 +603,6 @@ static int __devcgroup_check_permission(struct dev_cgroup *dev_cgroup,
 
 int __devcgroup_inode_permission(struct inode *inode, int mask)
 {
-       struct dev_cgroup *dev_cgroup = task_devcgroup(current);
        short type, access = 0;
 
        if (S_ISBLK(inode->i_mode))
@@ -570,13 +614,12 @@ int __devcgroup_inode_permission(struct inode *inode, int mask)
        if (mask & MAY_READ)
                access |= ACC_READ;
 
-       return __devcgroup_check_permission(dev_cgroup, type, imajor(inode),
-                                           iminor(inode), access);
+       return __devcgroup_check_permission(type, imajor(inode), iminor(inode),
+                       access);
 }
 
 int devcgroup_inode_mknod(int mode, dev_t dev)
 {
-       struct dev_cgroup *dev_cgroup = task_devcgroup(current);
        short type;
 
        if (!S_ISBLK(mode) && !S_ISCHR(mode))
@@ -587,7 +630,7 @@ int devcgroup_inode_mknod(int mode, dev_t dev)
        else
                type = DEV_CHAR;
 
-       return __devcgroup_check_permission(dev_cgroup, type, MAJOR(dev),
-                                           MINOR(dev), ACC_MKNOD);
+       return __devcgroup_check_permission(type, MAJOR(dev), MINOR(dev),
+                       ACC_MKNOD);
 
 }
index 28f911cdd7c79dc292171fea10385adad51a27eb..c5454c0477c346e4d814f5ff209feba86e5b86ad 100644 (file)
@@ -174,7 +174,8 @@ static void sel_netnode_insert(struct sel_netnode *node)
        if (sel_netnode_hash[idx].size == SEL_NETNODE_HASH_BKT_LIMIT) {
                struct sel_netnode *tail;
                tail = list_entry(
-                       rcu_dereference(sel_netnode_hash[idx].list.prev),
+                       rcu_dereference_protected(sel_netnode_hash[idx].list.prev,
+                                                 lockdep_is_held(&sel_netnode_lock)),
                        struct sel_netnode, list);
                list_del_rcu(&tail->list);
                kfree_rcu(tail, rcu);
index c40ae573346dd140031af773c532dd4f32f32240..ad11dc994792b4bb080c49a7036b8761731e5a1d 100644 (file)
@@ -100,12 +100,15 @@ static int snd_compr_open(struct inode *inode, struct file *f)
 
        if (dirn != compr->direction) {
                pr_err("this device doesn't support this direction\n");
+               snd_card_unref(compr->card);
                return -EINVAL;
        }
 
        data = kzalloc(sizeof(*data), GFP_KERNEL);
-       if (!data)
+       if (!data) {
+               snd_card_unref(compr->card);
                return -ENOMEM;
+       }
        data->stream.ops = compr->ops;
        data->stream.direction = dirn;
        data->stream.private_data = compr->private_data;
@@ -113,6 +116,7 @@ static int snd_compr_open(struct inode *inode, struct file *f)
        runtime = kzalloc(sizeof(*runtime), GFP_KERNEL);
        if (!runtime) {
                kfree(data);
+               snd_card_unref(compr->card);
                return -ENOMEM;
        }
        runtime->state = SNDRV_PCM_STATE_OPEN;
@@ -126,7 +130,8 @@ static int snd_compr_open(struct inode *inode, struct file *f)
                kfree(runtime);
                kfree(data);
        }
-       return ret;
+       snd_card_unref(compr->card);
+       return 0;
 }
 
 static int snd_compr_free(struct inode *inode, struct file *f)
index 7e86a5b9f3b572f9c97f351027ed4e1b9b7b75b3..8c7c2c9bba61e4dd421eb6a0c797bd0cf17b81ae 100644 (file)
@@ -86,6 +86,7 @@ static int snd_ctl_open(struct inode *inode, struct file *file)
        write_lock_irqsave(&card->ctl_files_rwlock, flags);
        list_add_tail(&ctl->list, &card->ctl_files);
        write_unlock_irqrestore(&card->ctl_files_rwlock, flags);
+       snd_card_unref(card);
        return 0;
 
       __error:
@@ -93,6 +94,8 @@ static int snd_ctl_open(struct inode *inode, struct file *file)
       __error2:
        snd_card_file_remove(card, file);
       __error1:
+       if (card)
+               snd_card_unref(card);
        return err;
 }
 
@@ -1434,6 +1437,8 @@ static ssize_t snd_ctl_read(struct file *file, char __user *buffer,
                        spin_unlock_irq(&ctl->read_lock);
                        schedule();
                        remove_wait_queue(&ctl->change_sleep, &wait);
+                       if (ctl->card->shutdown)
+                               return -ENODEV;
                        if (signal_pending(current))
                                return -ERESTARTSYS;
                        spin_lock_irq(&ctl->read_lock);
index 75ea16f35b1aa1e1db985802e923c86e28f69af3..3f7f6628cf7b1704ed7cdb4094703416697af0a0 100644 (file)
@@ -100,8 +100,10 @@ static int snd_hwdep_open(struct inode *inode, struct file * file)
        if (hw == NULL)
                return -ENODEV;
 
-       if (!try_module_get(hw->card->module))
+       if (!try_module_get(hw->card->module)) {
+               snd_card_unref(hw->card);
                return -EFAULT;
+       }
 
        init_waitqueue_entry(&wait, current);
        add_wait_queue(&hw->open_wait, &wait);
@@ -129,6 +131,10 @@ static int snd_hwdep_open(struct inode *inode, struct file * file)
                mutex_unlock(&hw->open_mutex);
                schedule();
                mutex_lock(&hw->open_mutex);
+               if (hw->card->shutdown) {
+                       err = -ENODEV;
+                       break;
+               }
                if (signal_pending(current)) {
                        err = -ERESTARTSYS;
                        break;
@@ -148,6 +154,7 @@ static int snd_hwdep_open(struct inode *inode, struct file * file)
        mutex_unlock(&hw->open_mutex);
        if (err < 0)
                module_put(hw->card->module);
+       snd_card_unref(hw->card);
        return err;
 }
 
@@ -459,12 +466,15 @@ static int snd_hwdep_dev_disconnect(struct snd_device *device)
                mutex_unlock(&register_mutex);
                return -EINVAL;
        }
+       mutex_lock(&hwdep->open_mutex);
+       wake_up(&hwdep->open_wait);
 #ifdef CONFIG_SND_OSSEMUL
        if (hwdep->ossreg)
                snd_unregister_oss_device(hwdep->oss_type, hwdep->card, hwdep->device);
 #endif
        snd_unregister_device(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card, hwdep->device);
        list_del_init(&hwdep->list);
+       mutex_unlock(&hwdep->open_mutex);
        mutex_unlock(&register_mutex);
        return 0;
 }
index d8ec849af128ed1d248effdd2f606baa52a5f06d..7b012d15c2cf1599e92d0ddc832a6b0ece653e9e 100644 (file)
@@ -213,6 +213,7 @@ int snd_card_create(int idx, const char *xid,
        spin_lock_init(&card->files_lock);
        INIT_LIST_HEAD(&card->files_list);
        init_waitqueue_head(&card->shutdown_sleep);
+       atomic_set(&card->refcount, 0);
 #ifdef CONFIG_PM
        mutex_init(&card->power_lock);
        init_waitqueue_head(&card->power_sleep);
@@ -446,21 +447,36 @@ static int snd_card_do_free(struct snd_card *card)
        return 0;
 }
 
+/**
+ * snd_card_unref - release the reference counter
+ * @card: the card instance
+ *
+ * Decrements the reference counter.  When it reaches to zero, wake up
+ * the sleeper and call the destructor if needed.
+ */
+void snd_card_unref(struct snd_card *card)
+{
+       if (atomic_dec_and_test(&card->refcount)) {
+               wake_up(&card->shutdown_sleep);
+               if (card->free_on_last_close)
+                       snd_card_do_free(card);
+       }
+}
+EXPORT_SYMBOL(snd_card_unref);
+
 int snd_card_free_when_closed(struct snd_card *card)
 {
-       int free_now = 0;
-       int ret = snd_card_disconnect(card);
-       if (ret)
-               return ret;
+       int ret;
 
-       spin_lock(&card->files_lock);
-       if (list_empty(&card->files_list))
-               free_now = 1;
-       else
-               card->free_on_last_close = 1;
-       spin_unlock(&card->files_lock);
+       atomic_inc(&card->refcount);
+       ret = snd_card_disconnect(card);
+       if (ret) {
+               atomic_dec(&card->refcount);
+               return ret;
+       }
 
-       if (free_now)
+       card->free_on_last_close = 1;
+       if (atomic_dec_and_test(&card->refcount))
                snd_card_do_free(card);
        return 0;
 }
@@ -474,7 +490,7 @@ int snd_card_free(struct snd_card *card)
                return ret;
 
        /* wait, until all devices are ready for the free operation */
-       wait_event(card->shutdown_sleep, list_empty(&card->files_list));
+       wait_event(card->shutdown_sleep, !atomic_read(&card->refcount));
        snd_card_do_free(card);
        return 0;
 }
@@ -886,6 +902,7 @@ int snd_card_file_add(struct snd_card *card, struct file *file)
                return -ENODEV;
        }
        list_add(&mfile->list, &card->files_list);
+       atomic_inc(&card->refcount);
        spin_unlock(&card->files_lock);
        return 0;
 }
@@ -908,7 +925,6 @@ EXPORT_SYMBOL(snd_card_file_add);
 int snd_card_file_remove(struct snd_card *card, struct file *file)
 {
        struct snd_monitor_file *mfile, *found = NULL;
-       int last_close = 0;
 
        spin_lock(&card->files_lock);
        list_for_each_entry(mfile, &card->files_list, list) {
@@ -923,19 +939,13 @@ int snd_card_file_remove(struct snd_card *card, struct file *file)
                        break;
                }
        }
-       if (list_empty(&card->files_list))
-               last_close = 1;
        spin_unlock(&card->files_lock);
-       if (last_close) {
-               wake_up(&card->shutdown_sleep);
-               if (card->free_on_last_close)
-                       snd_card_do_free(card);
-       }
        if (!found) {
                snd_printk(KERN_ERR "ALSA card file remove problem (%p)\n", file);
                return -ENOENT;
        }
        kfree(found);
+       snd_card_unref(card);
        return 0;
 }
 
index 29f6ded02555568498473fb37547c9e7b0b96c2b..e8a1d18774b2073f997746f6d6f16881a1ecc4bc 100644 (file)
@@ -52,14 +52,19 @@ static int snd_mixer_oss_open(struct inode *inode, struct file *file)
                                         SNDRV_OSS_DEVICE_TYPE_MIXER);
        if (card == NULL)
                return -ENODEV;
-       if (card->mixer_oss == NULL)
+       if (card->mixer_oss == NULL) {
+               snd_card_unref(card);
                return -ENODEV;
+       }
        err = snd_card_file_add(card, file);
-       if (err < 0)
+       if (err < 0) {
+               snd_card_unref(card);
                return err;
+       }
        fmixer = kzalloc(sizeof(*fmixer), GFP_KERNEL);
        if (fmixer == NULL) {
                snd_card_file_remove(card, file);
+               snd_card_unref(card);
                return -ENOMEM;
        }
        fmixer->card = card;
@@ -68,8 +73,10 @@ static int snd_mixer_oss_open(struct inode *inode, struct file *file)
        if (!try_module_get(card->module)) {
                kfree(fmixer);
                snd_card_file_remove(card, file);
+               snd_card_unref(card);
                return -EFAULT;
        }
+       snd_card_unref(card);
        return 0;
 }
 
index 08fde0060fd9377ee9f5e12dc1113858c73b3d20..4c1cc51772e6f18e9ab03671069c738471ca8c04 100644 (file)
@@ -2441,6 +2441,10 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
                mutex_unlock(&pcm->open_mutex);
                schedule();
                mutex_lock(&pcm->open_mutex);
+               if (pcm->card->shutdown) {
+                       err = -ENODEV;
+                       break;
+               }
                if (signal_pending(current)) {
                        err = -ERESTARTSYS;
                        break;
@@ -2450,6 +2454,7 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
        mutex_unlock(&pcm->open_mutex);
        if (err < 0)
                goto __error;
+       snd_card_unref(pcm->card);
        return err;
 
       __error:
@@ -2457,6 +2462,8 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
       __error2:
        snd_card_file_remove(pcm->card, file);
       __error1:
+       if (pcm)
+               snd_card_unref(pcm->card);
        return err;
 }
 
index f2991940b271df46ef503173750a89d874fec6ad..030102caeee96b8080d9af6f2c99217278ec5a86 100644 (file)
@@ -1086,11 +1086,19 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
        if (list_empty(&pcm->list))
                goto unlock;
 
+       mutex_lock(&pcm->open_mutex);
+       wake_up(&pcm->open_wait);
        list_del_init(&pcm->list);
        for (cidx = 0; cidx < 2; cidx++)
-               for (substream = pcm->streams[cidx].substream; substream; substream = substream->next)
-                       if (substream->runtime)
+               for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) {
+                       snd_pcm_stream_lock_irq(substream);
+                       if (substream->runtime) {
                                substream->runtime->status->state = SNDRV_PCM_STATE_DISCONNECTED;
+                               wake_up(&substream->runtime->sleep);
+                               wake_up(&substream->runtime->tsleep);
+                       }
+                       snd_pcm_stream_unlock_irq(substream);
+               }
        list_for_each_entry(notify, &snd_pcm_notify_list, list) {
                notify->n_disconnect(pcm);
        }
@@ -1110,6 +1118,7 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
                        pcm->streams[cidx].chmap_kctl = NULL;
                }
        }
+       mutex_unlock(&pcm->open_mutex);
  unlock:
        mutex_unlock(&register_mutex);
        return 0;
index 5e12e5bacbba36cdf64c41a1d6e7e3d984902cf9..f9ddecf2f4cd7a17ebc0d5f0ba92405c03ab904a 100644 (file)
@@ -369,6 +369,14 @@ static int period_to_usecs(struct snd_pcm_runtime *runtime)
        return usecs;
 }
 
+static void snd_pcm_set_state(struct snd_pcm_substream *substream, int state)
+{
+       snd_pcm_stream_lock_irq(substream);
+       if (substream->runtime->status->state != SNDRV_PCM_STATE_DISCONNECTED)
+               substream->runtime->status->state = state;
+       snd_pcm_stream_unlock_irq(substream);
+}
+
 static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
                             struct snd_pcm_hw_params *params)
 {
@@ -452,7 +460,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
                runtime->boundary *= 2;
 
        snd_pcm_timer_resolution_change(substream);
-       runtime->status->state = SNDRV_PCM_STATE_SETUP;
+       snd_pcm_set_state(substream, SNDRV_PCM_STATE_SETUP);
 
        if (pm_qos_request_active(&substream->latency_pm_qos_req))
                pm_qos_remove_request(&substream->latency_pm_qos_req);
@@ -464,7 +472,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
        /* hardware might be unusable from this time,
           so we force application to retry to set
           the correct hardware parameter settings */
-       runtime->status->state = SNDRV_PCM_STATE_OPEN;
+       snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN);
        if (substream->ops->hw_free != NULL)
                substream->ops->hw_free(substream);
        return err;
@@ -512,7 +520,7 @@ static int snd_pcm_hw_free(struct snd_pcm_substream *substream)
                return -EBADFD;
        if (substream->ops->hw_free)
                result = substream->ops->hw_free(substream);
-       runtime->status->state = SNDRV_PCM_STATE_OPEN;
+       snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN);
        pm_qos_remove_request(&substream->latency_pm_qos_req);
        return result;
 }
@@ -1320,7 +1328,7 @@ static void snd_pcm_post_prepare(struct snd_pcm_substream *substream, int state)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        runtime->control->appl_ptr = runtime->status->hw_ptr;
-       runtime->status->state = SNDRV_PCM_STATE_PREPARED;
+       snd_pcm_set_state(substream, SNDRV_PCM_STATE_PREPARED);
 }
 
 static struct action_ops snd_pcm_action_prepare = {
@@ -1510,6 +1518,10 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
                down_read(&snd_pcm_link_rwsem);
                snd_pcm_stream_lock_irq(substream);
                remove_wait_queue(&to_check->sleep, &wait);
+               if (card->shutdown) {
+                       result = -ENODEV;
+                       break;
+               }
                if (tout == 0) {
                        if (substream->runtime->status->state == SNDRV_PCM_STATE_SUSPENDED)
                                result = -ESTRPIPE;
@@ -1634,6 +1646,7 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
        write_unlock_irq(&snd_pcm_link_rwlock);
        up_write(&snd_pcm_link_rwsem);
  _nolock:
+       snd_card_unref(substream1->pcm->card);
        fput_light(file, fput_needed);
        if (res < 0)
                kfree(group);
@@ -2108,7 +2121,10 @@ static int snd_pcm_playback_open(struct inode *inode, struct file *file)
                return err;
        pcm = snd_lookup_minor_data(iminor(inode),
                                    SNDRV_DEVICE_TYPE_PCM_PLAYBACK);
-       return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK);
+       err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK);
+       if (pcm)
+               snd_card_unref(pcm->card);
+       return err;
 }
 
 static int snd_pcm_capture_open(struct inode *inode, struct file *file)
@@ -2119,7 +2135,10 @@ static int snd_pcm_capture_open(struct inode *inode, struct file *file)
                return err;
        pcm = snd_lookup_minor_data(iminor(inode),
                                    SNDRV_DEVICE_TYPE_PCM_CAPTURE);
-       return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE);
+       err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE);
+       if (pcm)
+               snd_card_unref(pcm->card);
+       return err;
 }
 
 static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream)
@@ -2156,6 +2175,10 @@ static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream)
                mutex_unlock(&pcm->open_mutex);
                schedule();
                mutex_lock(&pcm->open_mutex);
+               if (pcm->card->shutdown) {
+                       err = -ENODEV;
+                       break;
+               }
                if (signal_pending(current)) {
                        err = -ERESTARTSYS;
                        break;
index ebf6e49ad3d461ba843131d903b0c66cc7840ba4..1bb95aeea084d33cd8225c53257058a23c25cf4e 100644 (file)
@@ -379,8 +379,10 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
        if (rmidi == NULL)
                return -ENODEV;
 
-       if (!try_module_get(rmidi->card->module))
+       if (!try_module_get(rmidi->card->module)) {
+               snd_card_unref(rmidi->card);
                return -ENXIO;
+       }
 
        mutex_lock(&rmidi->open_mutex);
        card = rmidi->card;
@@ -422,6 +424,10 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
                mutex_unlock(&rmidi->open_mutex);
                schedule();
                mutex_lock(&rmidi->open_mutex);
+               if (rmidi->card->shutdown) {
+                       err = -ENODEV;
+                       break;
+               }
                if (signal_pending(current)) {
                        err = -ERESTARTSYS;
                        break;
@@ -440,6 +446,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
 #endif
        file->private_data = rawmidi_file;
        mutex_unlock(&rmidi->open_mutex);
+       snd_card_unref(rmidi->card);
        return 0;
 
  __error:
@@ -447,6 +454,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
  __error_card:
        mutex_unlock(&rmidi->open_mutex);
        module_put(rmidi->card->module);
+       snd_card_unref(rmidi->card);
        return err;
 }
 
@@ -991,6 +999,8 @@ static ssize_t snd_rawmidi_read(struct file *file, char __user *buf, size_t coun
                        spin_unlock_irq(&runtime->lock);
                        schedule();
                        remove_wait_queue(&runtime->sleep, &wait);
+                       if (rfile->rmidi->card->shutdown)
+                               return -ENODEV;
                        if (signal_pending(current))
                                return result > 0 ? result : -ERESTARTSYS;
                        if (!runtime->avail)
@@ -1234,6 +1244,8 @@ static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf,
                        spin_unlock_irq(&runtime->lock);
                        timeout = schedule_timeout(30 * HZ);
                        remove_wait_queue(&runtime->sleep, &wait);
+                       if (rfile->rmidi->card->shutdown)
+                               return -ENODEV;
                        if (signal_pending(current))
                                return result > 0 ? result : -ERESTARTSYS;
                        if (!runtime->avail && !timeout)
@@ -1609,9 +1621,20 @@ static int snd_rawmidi_dev_register(struct snd_device *device)
 static int snd_rawmidi_dev_disconnect(struct snd_device *device)
 {
        struct snd_rawmidi *rmidi = device->device_data;
+       int dir;
 
        mutex_lock(&register_mutex);
+       mutex_lock(&rmidi->open_mutex);
+       wake_up(&rmidi->open_wait);
        list_del_init(&rmidi->list);
+       for (dir = 0; dir < 2; dir++) {
+               struct snd_rawmidi_substream *s;
+               list_for_each_entry(s, &rmidi->streams[dir].substreams, list) {
+                       if (s->runtime)
+                               wake_up(&s->runtime->sleep);
+               }
+       }
+
 #ifdef CONFIG_SND_OSSEMUL
        if (rmidi->ossreg) {
                if ((int)rmidi->device == midi_map[rmidi->card->number]) {
@@ -1626,6 +1649,7 @@ static int snd_rawmidi_dev_disconnect(struct snd_device *device)
        }
 #endif /* CONFIG_SND_OSSEMUL */
        snd_unregister_device(SNDRV_DEVICE_TYPE_RAWMIDI, rmidi->card, rmidi->device);
+       mutex_unlock(&rmidi->open_mutex);
        mutex_unlock(&register_mutex);
        return 0;
 }
index 643976000ce825d1857fd3a3192fadeff0da4e5b..70ccdab7415320e3b20a2aba6c5837f42962f758 100644 (file)
@@ -98,6 +98,10 @@ static void snd_request_other(int minor)
  *
  * Checks that a minor device with the specified type is registered, and returns
  * its user data pointer.
+ *
+ * This function increments the reference counter of the card instance
+ * if an associated instance with the given minor number and type is found.
+ * The caller must call snd_card_unref() appropriately later.
  */
 void *snd_lookup_minor_data(unsigned int minor, int type)
 {
@@ -108,9 +112,11 @@ void *snd_lookup_minor_data(unsigned int minor, int type)
                return NULL;
        mutex_lock(&sound_mutex);
        mreg = snd_minors[minor];
-       if (mreg && mreg->type == type)
+       if (mreg && mreg->type == type) {
                private_data = mreg->private_data;
-       else
+               if (private_data && mreg->card_ptr)
+                       atomic_inc(&mreg->card_ptr->refcount);
+       } else
                private_data = NULL;
        mutex_unlock(&sound_mutex);
        return private_data;
@@ -275,6 +281,7 @@ int snd_register_device_for_dev(int type, struct snd_card *card, int dev,
        preg->device = dev;
        preg->f_ops = f_ops;
        preg->private_data = private_data;
+       preg->card_ptr = card;
        mutex_lock(&sound_mutex);
 #ifdef CONFIG_SND_DYNAMIC_MINORS
        minor = snd_find_free_minor(type);
index e9528333e36d01e6e0282255639da08b7174e505..726a49ac97253d50634313265abc5699480c7e71 100644 (file)
@@ -40,6 +40,9 @@
 static struct snd_minor *snd_oss_minors[SNDRV_OSS_MINORS];
 static DEFINE_MUTEX(sound_oss_mutex);
 
+/* NOTE: This function increments the refcount of the associated card like
+ * snd_lookup_minor_data(); the caller must call snd_card_unref() appropriately
+ */
 void *snd_lookup_oss_minor_data(unsigned int minor, int type)
 {
        struct snd_minor *mreg;
@@ -49,9 +52,11 @@ void *snd_lookup_oss_minor_data(unsigned int minor, int type)
                return NULL;
        mutex_lock(&sound_oss_mutex);
        mreg = snd_oss_minors[minor];
-       if (mreg && mreg->type == type)
+       if (mreg && mreg->type == type) {
                private_data = mreg->private_data;
-       else
+               if (private_data && mreg->card_ptr)
+                       atomic_inc(&mreg->card_ptr->refcount);
+       } else
                private_data = NULL;
        mutex_unlock(&sound_oss_mutex);
        return private_data;
@@ -123,6 +128,7 @@ int snd_register_oss_device(int type, struct snd_card *card, int dev,
        preg->device = dev;
        preg->f_ops = f_ops;
        preg->private_data = private_data;
+       preg->card_ptr = card;
        mutex_lock(&sound_oss_mutex);
        snd_oss_minors[minor] = preg;
        minor_unit = SNDRV_MINOR_OSS_DEVICE(minor);
index ef68d710d08cfc13121089ae5f86f97dfb813ebb..e04e750a77ed4bac80875bf05e979bbd946f2219 100644 (file)
@@ -426,7 +426,7 @@ static struct snd_kcontrol_new snd_ak4113_iec958_controls[] = {
 },
 {
        .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
-       .name =         "IEC958 Preample Capture Default",
+       .name =         "IEC958 Preamble Capture Default",
        .access =       SNDRV_CTL_ELEM_ACCESS_READ |
                SNDRV_CTL_ELEM_ACCESS_VOLATILE,
        .info =         snd_ak4113_spdif_pinfo,
index 816e7d225fb0a626147eb6d339d141edede00dc9..5bf4fca19e48656916180ecc353109018b771aa3 100644 (file)
@@ -401,7 +401,7 @@ static struct snd_kcontrol_new snd_ak4114_iec958_controls[] = {
 },
 {
        .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
-       .name =         "IEC958 Preample Capture Default",
+       .name =         "IEC958 Preamble Capture Default",
        .access =       SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
        .info =         snd_ak4114_spdif_pinfo,
        .get =          snd_ak4114_spdif_pget,
index b4b2a51fc117a98b667e10de335a86c5e2c1ce00..40e33c9f2b095f1eb7488729afe20f1f991d994f 100644 (file)
@@ -380,7 +380,7 @@ static struct snd_kcontrol_new snd_ak4117_iec958_controls[] = {
 },
 {
        .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
-       .name =         "IEC958 Preample Capture Default",
+       .name =         "IEC958 Preamble Capture Default",
        .access =       SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
        .info =         snd_ak4117_spdif_pinfo,
        .get =          snd_ak4117_spdif_pget,
index 3d1afb612b3548ade1db68d1b60af8f3e7e6ce4b..4a7ff4e8985ba2fe3b71ac7b57a191e694063ae2 100644 (file)
@@ -1286,7 +1286,6 @@ static int __devinit snd_miro_probe(struct snd_card *card)
 
        error = snd_card_miro_aci_detect(card, miro);
        if (error < 0) {
-               snd_card_free(card);
                snd_printk(KERN_ERR "unable to detect aci chip\n");
                return -ENODEV;
        }
index 00f157a2cf6411d8b1ad1b1ffef32f566d5e02b8..5af3cb6b0c18d36345aadfefee3d509404bbba80 100644 (file)
@@ -394,6 +394,8 @@ static int snd_als300_playback_open(struct snd_pcm_substream *substream)
        struct snd_als300_substream_data *data = kzalloc(sizeof(*data),
                                                                GFP_KERNEL);
 
+       if (!data)
+               return -ENOMEM;
        snd_als300_dbgcallenter();
        chip->playback_substream = substream;
        runtime->hw = snd_als300_playback_hw;
@@ -425,6 +427,8 @@ static int snd_als300_capture_open(struct snd_pcm_substream *substream)
        struct snd_als300_substream_data *data = kzalloc(sizeof(*data),
                                                                GFP_KERNEL);
 
+       if (!data)
+               return -ENOMEM;
        snd_als300_dbgcallenter();
        chip->capture_substream = substream;
        runtime->hw = snd_als300_capture_hw;
index 5d0e568fdea1b39e6a4c94f9c4fa360edffa5ede..7266020c16cb3a489a22418fd3b1f32e3dbd9fdb 100644 (file)
@@ -2581,9 +2581,14 @@ static u8 snd_es1968_tea575x_get_pins(struct snd_tea575x *tea)
        struct es1968 *chip = tea->private_data;
        unsigned long io = chip->io_port + GPIO_DATA;
        u16 val = inw(io);
+       u8 ret;
 
-       return  (val & STR_DATA) ? TEA575X_DATA : 0 |
-               (val & STR_MOST) ? TEA575X_MOST : 0;
+       ret = 0;
+       if (val & STR_DATA)
+               ret |= TEA575X_DATA;
+       if (val & STR_MOST)
+               ret |= TEA575X_MOST;
+       return ret;
 }
 
 static void snd_es1968_tea575x_set_direction(struct snd_tea575x *tea, bool output)
@@ -2655,6 +2660,8 @@ static struct ess_device_list pm_whitelist[] __devinitdata = {
        { TYPE_MAESTRO2E, 0x1179 },
        { TYPE_MAESTRO2E, 0x14c0 },     /* HP omnibook 4150 */
        { TYPE_MAESTRO2E, 0x1558 },
+       { TYPE_MAESTRO2E, 0x125d },     /* a PCI card, e.g. Terratec DMX */
+       { TYPE_MAESTRO2, 0x125d },      /* a PCI card, e.g. SF64-PCE2 */
 };
 
 static struct ess_device_list mpu_blacklist[] __devinitdata = {
index cc2e91d1553822699251c15baf950e406243df8d..c5806f89be1ed8b23e0ad5e0ace6344815bb13f2 100644 (file)
@@ -767,9 +767,14 @@ static u8 snd_fm801_tea575x_get_pins(struct snd_tea575x *tea)
        struct fm801 *chip = tea->private_data;
        unsigned short reg = inw(FM801_REG(chip, GPIO_CTRL));
        struct snd_fm801_tea575x_gpio gpio = *get_tea575x_gpio(chip);
-
-       return  (reg & FM801_GPIO_GP(gpio.data)) ? TEA575X_DATA : 0 |
-               (reg & FM801_GPIO_GP(gpio.most)) ? TEA575X_MOST : 0;
+       u8 ret;
+
+       ret = 0;
+       if (reg & FM801_GPIO_GP(gpio.data))
+               ret |= TEA575X_DATA;
+       if (reg & FM801_GPIO_GP(gpio.most))
+               ret |= TEA575X_MOST;
+       return ret;
 }
 
 static void snd_fm801_tea575x_set_direction(struct snd_tea575x *tea, bool output)
index 70d4848b5cd0ad25ce272877f9c759ed010dfc58..d010de12335e16525df3219cbe33647262316f7e 100644 (file)
@@ -95,6 +95,7 @@ int snd_hda_delete_codec_preset(struct hda_codec_preset_list *preset)
 EXPORT_SYMBOL_HDA(snd_hda_delete_codec_preset);
 
 #ifdef CONFIG_PM
+#define codec_in_pm(codec)     ((codec)->in_pm)
 static void hda_power_work(struct work_struct *work);
 static void hda_keep_power_on(struct hda_codec *codec);
 #define hda_codec_is_power_on(codec)   ((codec)->power_on)
@@ -104,6 +105,7 @@ static inline void hda_call_pm_notify(struct hda_bus *bus, bool power_up)
                bus->ops.pm_notify(bus, power_up);
 }
 #else
+#define codec_in_pm(codec)     0
 static inline void hda_keep_power_on(struct hda_codec *codec) {}
 #define hda_codec_is_power_on(codec)   1
 #define hda_call_pm_notify(bus, state) {}
@@ -228,7 +230,7 @@ static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd,
        }
        mutex_unlock(&bus->cmd_mutex);
        snd_hda_power_down(codec);
-       if (res && *res == -1 && bus->rirb_error) {
+       if (!codec_in_pm(codec) && res && *res == -1 && bus->rirb_error) {
                if (bus->response_reset) {
                        snd_printd("hda_codec: resetting BUS due to "
                                   "fatal communication error\n");
@@ -238,7 +240,7 @@ static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd,
                goto again;
        }
        /* clear reset-flag when the communication gets recovered */
-       if (!err)
+       if (!err || codec_in_pm(codec))
                bus->response_reset = 0;
        return err;
 }
@@ -3616,6 +3618,8 @@ static unsigned int hda_call_codec_suspend(struct hda_codec *codec, bool in_wq)
 {
        unsigned int state;
 
+       codec->in_pm = 1;
+
        if (codec->patch_ops.suspend)
                codec->patch_ops.suspend(codec);
        hda_cleanup_all_streams(codec);
@@ -3630,6 +3634,7 @@ static unsigned int hda_call_codec_suspend(struct hda_codec *codec, bool in_wq)
        codec->power_transition = 0;
        codec->power_jiffies = jiffies;
        spin_unlock(&codec->power_lock);
+       codec->in_pm = 0;
        return state;
 }
 
@@ -3638,6 +3643,8 @@ static unsigned int hda_call_codec_suspend(struct hda_codec *codec, bool in_wq)
  */
 static void hda_call_codec_resume(struct hda_codec *codec)
 {
+       codec->in_pm = 1;
+
        /* set as if powered on for avoiding re-entering the resume
         * in the resume / power-save sequence
         */
@@ -3656,6 +3663,8 @@ static void hda_call_codec_resume(struct hda_codec *codec)
                snd_hda_codec_resume_cache(codec);
        }
        snd_hda_jack_report_sync(codec);
+
+       codec->in_pm = 0;
        snd_hda_power_down(codec); /* flag down before returning */
 }
 #endif /* CONFIG_PM */
index 507fe8a917b69b09993193ef460f4fbc3f3af31a..4f4e545c0f4b2ded6029d21851b3443973ea7d23 100644 (file)
@@ -869,6 +869,7 @@ struct hda_codec {
        unsigned int power_on :1;       /* current (global) power-state */
        unsigned int d3_stop_clk:1;     /* support D3 operation without BCLK */
        unsigned int pm_down_notified:1; /* PM notified to controller */
+       unsigned int in_pm:1;           /* suspend/resume being performed */
        int power_transition;   /* power-state in transition */
        int power_count;        /* current (global) power refcount */
        struct delayed_work power_work; /* delayed task for powerdown */
index 72b085ae7d469e14559267558e515a578e3142dd..f9d870e554d98d2fabe8791e904d7a393c8925e6 100644 (file)
@@ -556,6 +556,12 @@ enum {
 #define AZX_DCAPS_ALIGN_BUFSIZE        (1 << 22)       /* buffer size alignment */
 #define AZX_DCAPS_4K_BDLE_BOUNDARY (1 << 23)   /* BDLE in 4k boundary */
 #define AZX_DCAPS_COUNT_LPIB_DELAY  (1 << 25)  /* Take LPIB as delay */
+#define AZX_DCAPS_PM_RUNTIME   (1 << 26)       /* runtime PM support */
+
+/* quirks for Intel PCH */
+#define AZX_DCAPS_INTEL_PCH \
+       (AZX_DCAPS_SCH_SNOOP | AZX_DCAPS_BUFSIZE | \
+        AZX_DCAPS_COUNT_LPIB_DELAY | AZX_DCAPS_PM_RUNTIME)
 
 /* quirks for ATI SB / AMD Hudson */
 #define AZX_DCAPS_PRESET_ATI_SB \
@@ -2433,6 +2439,9 @@ static void azx_power_notify(struct hda_bus *bus, bool power_up)
 {
        struct azx *chip = bus->private_data;
 
+       if (!(chip->driver_caps & AZX_DCAPS_PM_RUNTIME))
+               return;
+
        if (power_up)
                pm_runtime_get_sync(&chip->pci->dev);
        else
@@ -2548,7 +2557,8 @@ static int azx_runtime_suspend(struct device *dev)
        struct snd_card *card = dev_get_drvdata(dev);
        struct azx *chip = card->private_data;
 
-       if (!power_save_controller)
+       if (!power_save_controller ||
+           !(chip->driver_caps & AZX_DCAPS_PM_RUNTIME))
                return -EAGAIN;
 
        azx_stop_chip(chip);
@@ -3429,39 +3439,30 @@ static void __devexit azx_remove(struct pci_dev *pci)
 static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
        /* CPT */
        { PCI_DEVICE(0x8086, 0x1c20),
-         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
-         AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
+         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
        /* PBG */
        { PCI_DEVICE(0x8086, 0x1d20),
-         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
-         AZX_DCAPS_BUFSIZE},
+         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
        /* Panther Point */
        { PCI_DEVICE(0x8086, 0x1e20),
-         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
-         AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
+         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
        /* Lynx Point */
        { PCI_DEVICE(0x8086, 0x8c20),
-         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
-         AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
+         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
        /* Lynx Point-LP */
        { PCI_DEVICE(0x8086, 0x9c20),
-         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
-         AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
+         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
        /* Lynx Point-LP */
        { PCI_DEVICE(0x8086, 0x9c21),
-         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
-         AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
+         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
        /* Haswell */
        { PCI_DEVICE(0x8086, 0x0c0c),
-         .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP |
-         AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
+         .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH },
        { PCI_DEVICE(0x8086, 0x0d0c),
-         .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP |
-         AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
+         .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH },
        /* 5 Series/3400 */
        { PCI_DEVICE(0x8086, 0x3b56),
-         .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP |
-         AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
+         .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH },
        /* SCH */
        { PCI_DEVICE(0x8086, 0x811b),
          .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP |
@@ -3563,6 +3564,8 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
        /* Teradici */
        { PCI_DEVICE(0x6549, 0x1200),
          .driver_data = AZX_DRIVER_TERA | AZX_DCAPS_NO_64BIT },
+       { PCI_DEVICE(0x6549, 0x2200),
+         .driver_data = AZX_DRIVER_TERA | AZX_DCAPS_NO_64BIT },
        /* Creative X-Fi (CA0110-IBG) */
        /* CTHDA chips */
        { PCI_DEVICE(0x1102, 0x0010),
index cdd43eadbc67425e80237b7da979c778b6bd835b..1eeba738666634329d17a76149618c1c6f3e8c26 100644 (file)
@@ -545,6 +545,7 @@ static int ad198x_build_pcms(struct hda_codec *codec)
        if (spec->multiout.dig_out_nid) {
                info++;
                codec->num_pcms++;
+               codec->spdif_status_reset = 1;
                info->name = "AD198x Digital";
                info->pcm_type = HDA_PCM_TYPE_SPDIF;
                info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_digital_playback;
index 61a71131711c734556249b17fc61fc51f1218c1a..3bcb671723583ed852ec97aa844d2736ffd4b330 100644 (file)
@@ -101,8 +101,8 @@ enum {
 #define CS420X_VENDOR_NID      0x11
 #define CS_DIG_OUT1_PIN_NID    0x10
 #define CS_DIG_OUT2_PIN_NID    0x15
-#define CS_DMIC1_PIN_NID       0x12
-#define CS_DMIC2_PIN_NID       0x0e
+#define CS_DMIC1_PIN_NID       0x0e
+#define CS_DMIC2_PIN_NID       0x12
 
 /* coef indices */
 #define IDX_SPDIF_STAT         0x0000
@@ -466,6 +466,7 @@ static int parse_output(struct hda_codec *codec)
                memcpy(cfg->speaker_pins, cfg->line_out_pins,
                       sizeof(cfg->speaker_pins));
                cfg->line_outs = 0;
+               memset(cfg->line_out_pins, 0, sizeof(cfg->line_out_pins));
        }
 
        return 0;
@@ -1079,14 +1080,18 @@ static void init_input(struct hda_codec *codec)
                        cs_automic(codec, NULL);
 
                coef = 0x000a; /* ADC1/2 - Digital and Analog Soft Ramp */
+               cs_vendor_coef_set(codec, IDX_ADC_CFG, coef);
+
+               coef = cs_vendor_coef_get(codec, IDX_BEEP_CFG);
                if (is_active_pin(codec, CS_DMIC2_PIN_NID))
-                       coef |= 0x0500; /* DMIC2 2 chan on, GPIO1 off */
+                       coef |= 1 << 4; /* DMIC2 2 chan on, GPIO1 off */
                if (is_active_pin(codec, CS_DMIC1_PIN_NID))
-                       coef |= 0x1800; /* DMIC1 2 chan on, GPIO0 off
+                       coef |= 1 << 3; /* DMIC1 2 chan on, GPIO0 off
                                         * No effect if SPDIF_OUT2 is
                                         * selected in IDX_SPDIF_CTL.
                                        */
-               cs_vendor_coef_set(codec, IDX_ADC_CFG, coef);
+
+               cs_vendor_coef_set(codec, IDX_BEEP_CFG, coef);
        } else {
                if (spec->mic_detect)
                        cs_automic(codec, NULL);
@@ -1107,7 +1112,7 @@ static const struct hda_verb cs_coef_init_verbs[] = {
          | 0x0400 /* Disable Coefficient Auto increment */
          )},
        /* Beep */
-       {0x11, AC_VERB_SET_COEF_INDEX, IDX_DAC_CFG},
+       {0x11, AC_VERB_SET_COEF_INDEX, IDX_BEEP_CFG},
        {0x11, AC_VERB_SET_PROC_COEF, 0x0007}, /* Enable Beep thru DAC1/2/3 */
 
        {} /* terminator */
@@ -1728,8 +1733,7 @@ static int cs421x_mux_enum_put(struct snd_kcontrol *kcontrol,
 
 }
 
-static struct snd_kcontrol_new cs421x_capture_source = {
-
+static const struct snd_kcontrol_new cs421x_capture_source = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "Capture Source",
        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
@@ -1946,7 +1950,7 @@ static int cs421x_suspend(struct hda_codec *codec)
 }
 #endif
 
-static struct hda_codec_ops cs421x_patch_ops = {
+static const struct hda_codec_ops cs421x_patch_ops = {
        .build_controls = cs421x_build_controls,
        .build_pcms = cs_build_pcms,
        .init = cs421x_init,
index 48d9d609f89b06bca17210b8ca9dfaec2a600c1d..ad68d223f8af9e7dc43d24af303aab1eec64ca3d 100644 (file)
@@ -5407,6 +5407,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
        SND_PCI_QUIRK(0x106b, 0x4000, "MacbookPro 5,1", ALC889_FIXUP_IMAC91_VREF),
        SND_PCI_QUIRK(0x106b, 0x4100, "Macmini 3,1", ALC889_FIXUP_IMAC91_VREF),
        SND_PCI_QUIRK(0x106b, 0x4200, "Mac Pro 5,1", ALC885_FIXUP_MACPRO_GPIO),
+       SND_PCI_QUIRK(0x106b, 0x4300, "iMac 9,1", ALC889_FIXUP_IMAC91_VREF),
        SND_PCI_QUIRK(0x106b, 0x4600, "MacbookPro 5,2", ALC889_FIXUP_IMAC91_VREF),
        SND_PCI_QUIRK(0x106b, 0x4900, "iMac 9,1 Aluminum", ALC889_FIXUP_IMAC91_VREF),
        SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC889_FIXUP_IMAC91_VREF),
@@ -5677,6 +5678,7 @@ static const struct hda_verb alc268_beep_init_verbs[] = {
 
 enum {
        ALC268_FIXUP_INV_DMIC,
+       ALC268_FIXUP_HP_EAPD,
 };
 
 static const struct alc_fixup alc268_fixups[] = {
@@ -5684,10 +5686,26 @@ static const struct alc_fixup alc268_fixups[] = {
                .type = ALC_FIXUP_FUNC,
                .v.func = alc_fixup_inv_dmic_0x12,
        },
+       [ALC268_FIXUP_HP_EAPD] = {
+               .type = ALC_FIXUP_VERBS,
+               .v.verbs = (const struct hda_verb[]) {
+                       {0x15, AC_VERB_SET_EAPD_BTLENABLE, 0},
+                       {}
+               }
+       },
 };
 
 static const struct alc_model_fixup alc268_fixup_models[] = {
        {.id = ALC268_FIXUP_INV_DMIC, .name = "inv-dmic"},
+       {.id = ALC268_FIXUP_HP_EAPD, .name = "hp-eapd"},
+       {}
+};
+
+static const struct snd_pci_quirk alc268_fixup_tbl[] = {
+       /* below is codec SSID since multiple Toshiba laptops have the
+        * same PCI SSID 1179:ff00
+        */
+       SND_PCI_QUIRK(0x1179, 0xff06, "Toshiba P200", ALC268_FIXUP_HP_EAPD),
        {}
 };
 
@@ -5722,7 +5740,7 @@ static int patch_alc268(struct hda_codec *codec)
 
        spec = codec->spec;
 
-       alc_pick_fixup(codec, alc268_fixup_models, NULL, alc268_fixups);
+       alc_pick_fixup(codec, alc268_fixup_models, alc268_fixup_tbl, alc268_fixups);
        alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
 
        /* automatic parse from the BIOS config */
@@ -5823,7 +5841,7 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
        return alc_parse_auto_config(codec, alc269_ignore, ssids);
 }
 
-static void alc269_toggle_power_output(struct hda_codec *codec, int power_up)
+static void alc269vb_toggle_power_output(struct hda_codec *codec, int power_up)
 {
        int val = alc_read_coef_idx(codec, 0x04);
        if (power_up)
@@ -5840,10 +5858,10 @@ static void alc269_shutup(struct hda_codec *codec)
        if (spec->codec_variant != ALC269_TYPE_ALC269VB)
                return;
 
-       if ((alc_get_coef0(codec) & 0x00ff) == 0x017)
-               alc269_toggle_power_output(codec, 0);
-       if ((alc_get_coef0(codec) & 0x00ff) == 0x018) {
-               alc269_toggle_power_output(codec, 0);
+       if (spec->codec_variant == ALC269_TYPE_ALC269VB)
+               alc269vb_toggle_power_output(codec, 0);
+       if (spec->codec_variant == ALC269_TYPE_ALC269VB &&
+                       (alc_get_coef0(codec) & 0x00ff) == 0x018) {
                msleep(150);
        }
 }
@@ -5853,24 +5871,22 @@ static int alc269_resume(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
 
-       if (spec->codec_variant == ALC269_TYPE_ALC269VB ||
+       if (spec->codec_variant == ALC269_TYPE_ALC269VB)
+               alc269vb_toggle_power_output(codec, 0);
+       if (spec->codec_variant == ALC269_TYPE_ALC269VB &&
                        (alc_get_coef0(codec) & 0x00ff) == 0x018) {
-               alc269_toggle_power_output(codec, 0);
                msleep(150);
        }
 
        codec->patch_ops.init(codec);
 
-       if (spec->codec_variant == ALC269_TYPE_ALC269VB ||
+       if (spec->codec_variant == ALC269_TYPE_ALC269VB)
+               alc269vb_toggle_power_output(codec, 1);
+       if (spec->codec_variant == ALC269_TYPE_ALC269VB &&
                        (alc_get_coef0(codec) & 0x00ff) == 0x017) {
-               alc269_toggle_power_output(codec, 1);
                msleep(200);
        }
 
-       if (spec->codec_variant == ALC269_TYPE_ALC269VB ||
-                       (alc_get_coef0(codec) & 0x00ff) == 0x018)
-               alc269_toggle_power_output(codec, 1);
-
        snd_hda_codec_resume_amp(codec);
        snd_hda_codec_resume_cache(codec);
        hda_call_check_power_status(codec, 0x01);
@@ -6188,6 +6204,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x17aa, 0x21e9, "Thinkpad Edge 15", ALC269_FIXUP_SKU_IGNORE),
        SND_PCI_QUIRK(0x17aa, 0x21f6, "Thinkpad T530", ALC269_FIXUP_LENOVO_DOCK),
        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, 0x2203, "Thinkpad X230 Tablet", ALC269_FIXUP_LENOVO_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K),
@@ -7048,6 +7065,7 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = {
        { .id = 0x10ec0282, .name = "ALC282", .patch = patch_alc269 },
        { .id = 0x10ec0283, .name = "ALC283", .patch = patch_alc269 },
        { .id = 0x10ec0290, .name = "ALC290", .patch = patch_alc269 },
+       { .id = 0x10ec0292, .name = "ALC292", .patch = patch_alc269 },
        { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",
          .patch = patch_alc861 },
        { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd },
@@ -7061,6 +7079,7 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = {
          .patch = patch_alc662 },
        { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 },
        { .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 },
+       { .id = 0x10ec0668, .name = "ALC668", .patch = patch_alc662 },
        { .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 },
        { .id = 0x10ec0680, .name = "ALC680", .patch = patch_alc680 },
        { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
@@ -7078,6 +7097,7 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = {
        { .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc882 },
        { .id = 0x10ec0892, .name = "ALC892", .patch = patch_alc662 },
        { .id = 0x10ec0899, .name = "ALC898", .patch = patch_alc882 },
+       { .id = 0x10ec0900, .name = "ALC1150", .patch = patch_alc882 },
        {} /* terminator */
 };
 
index 770013ff556f6be0500b14039a8e60df2fa74b2a..9ba8af05617080f8081a5a69d68bcaec81cfb847 100644 (file)
@@ -1763,6 +1763,8 @@ static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = {
                          "HP", STAC_HP_ZEPHYR),
        SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3660,
                          "HP Mini", STAC_92HD83XXX_HP_LED),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x144E,
+                         "HP Pavilion dv5", STAC_92HD83XXX_HP_INV_LED),
        {} /* terminator */
 };
 
index 72a2f60b087c8ba066b52e5aaf4cda500227471f..019e1a00414a460cb7a43c8c6bf142ecc2f01d38 100644 (file)
@@ -1809,11 +1809,11 @@ static int via_auto_fill_dac_nids(struct hda_codec *codec)
 {
        struct via_spec *spec = codec->spec;
        const struct auto_pin_cfg *cfg = &spec->autocfg;
-       int i, dac_num;
+       int i;
        hda_nid_t nid;
 
+       spec->multiout.num_dacs = 0;
        spec->multiout.dac_nids = spec->private_dac_nids;
-       dac_num = 0;
        for (i = 0; i < cfg->line_outs; i++) {
                hda_nid_t dac = 0;
                nid = cfg->line_out_pins[i];
@@ -1824,16 +1824,13 @@ static int via_auto_fill_dac_nids(struct hda_codec *codec)
                if (!i && parse_output_path(codec, nid, dac, 1,
                                            &spec->out_mix_path))
                        dac = spec->out_mix_path.path[0];
-               if (dac) {
-                       spec->private_dac_nids[i] = dac;
-                       dac_num++;
-               }
+               if (dac)
+                       spec->private_dac_nids[spec->multiout.num_dacs++] = dac;
        }
        if (!spec->out_path[0].depth && spec->out_mix_path.depth) {
                spec->out_path[0] = spec->out_mix_path;
                spec->out_mix_path.depth = 0;
        }
-       spec->multiout.num_dacs = dac_num;
        return 0;
 }
 
@@ -3628,6 +3625,7 @@ static void set_widgets_power_state_vt2002P(struct hda_codec *codec)
  */
 enum {
        VIA_FIXUP_INTMIC_BOOST,
+       VIA_FIXUP_ASUS_G75,
 };
 
 static void via_fixup_intmic_boost(struct hda_codec *codec,
@@ -3642,13 +3640,35 @@ static const struct hda_fixup via_fixups[] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = via_fixup_intmic_boost,
        },
+       [VIA_FIXUP_ASUS_G75] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                       /* set 0x24 and 0x33 as speakers */
+                       { 0x24, 0x991301f0 },
+                       { 0x33, 0x991301f1 }, /* subwoofer */
+                       { }
+               }
+       },
 };
 
 static const struct snd_pci_quirk vt2002p_fixups[] = {
+       SND_PCI_QUIRK(0x1043, 0x1487, "Asus G75", VIA_FIXUP_ASUS_G75),
        SND_PCI_QUIRK(0x1043, 0x8532, "Asus X202E", VIA_FIXUP_INTMIC_BOOST),
        {}
 };
 
+/* NIDs 0x24 and 0x33 on VT1802 have connections to non-existing NID 0x3e
+ * Replace this with mixer NID 0x1c
+ */
+static void fix_vt1802_connections(struct hda_codec *codec)
+{
+       static hda_nid_t conn_24[] = { 0x14, 0x1c };
+       static hda_nid_t conn_33[] = { 0x1c };
+
+       snd_hda_override_conn_list(codec, 0x24, ARRAY_SIZE(conn_24), conn_24);
+       snd_hda_override_conn_list(codec, 0x33, ARRAY_SIZE(conn_33), conn_33);
+}
+
 /* patch for vt2002P */
 static int patch_vt2002P(struct hda_codec *codec)
 {
@@ -3663,6 +3683,8 @@ static int patch_vt2002P(struct hda_codec *codec)
        spec->aa_mix_nid = 0x21;
        override_mic_boost(codec, 0x2b, 0, 3, 40);
        override_mic_boost(codec, 0x29, 0, 3, 40);
+       if (spec->codec_type == VT1802)
+               fix_vt1802_connections(codec);
        add_secret_dac_path(codec);
 
        snd_hda_pick_fixup(codec, NULL, vt2002p_fixups, via_fixups);
index 3050a52792532ad3a58303f54a800dcc7c0ab883..245d874891ba25c2d993ea9de44536e0ab27ae6e 100644 (file)
@@ -2859,7 +2859,12 @@ static int snd_vt1724_resume(struct device *dev)
                ice->set_spdif_clock(ice, 0);
        } else {
                /* internal on-card clock */
-               snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 1);
+               int rate;
+               if (ice->cur_rate)
+                       rate = ice->cur_rate;
+               else
+                       rate = ice->pro_rate_default;
+               snd_vt1724_set_pro_rate(ice, rate, 1);
        }
 
        update_spdif_bits(ice, ice->pm_saved_spdif_ctrl);
index b12308b5ba2a01170b56b5cd7b69a9d1d93aa6e3..748e36c66603a7f9928f70a6f13ea8e64b875f76 100644 (file)
@@ -971,6 +971,7 @@ static inline void snd_hdspm_initialize_midi_flush(struct hdspm *hdspm);
 static int hdspm_update_simple_mixer_controls(struct hdspm *hdspm);
 static int hdspm_autosync_ref(struct hdspm *hdspm);
 static int snd_hdspm_set_defaults(struct hdspm *hdspm);
+static int hdspm_system_clock_mode(struct hdspm *hdspm);
 static void hdspm_set_sgbuf(struct hdspm *hdspm,
                            struct snd_pcm_substream *substream,
                             unsigned int reg, int channels);
@@ -1989,10 +1990,14 @@ static int hdspm_get_system_sample_rate(struct hdspm *hdspm)
        rate = hdspm_calc_dds_value(hdspm, period);
 
        if (rate > 207000) {
-               /* Unreasonable high sample rate as seen on PCI MADI cards.
-                * Use the cached value instead.
-                */
-               rate = hdspm->system_sample_rate;
+               /* Unreasonable high sample rate as seen on PCI MADI cards. */
+               if (0 == hdspm_system_clock_mode(hdspm)) {
+                       /* master mode, return internal sample rate */
+                       rate = hdspm->system_sample_rate;
+               } else {
+                       /* slave mode, return external sample rate */
+                       rate = hdspm_external_sample_rate(hdspm);
+               }
        }
 
        return rate;
@@ -2000,12 +2005,14 @@ static int hdspm_get_system_sample_rate(struct hdspm *hdspm)
 
 
 #define HDSPM_SYSTEM_SAMPLE_RATE(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .access = SNDRV_CTL_ELEM_ACCESS_READ, \
-  .info = snd_hdspm_info_system_sample_rate, \
-  .get = snd_hdspm_get_system_sample_rate \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
+               SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
+       .info = snd_hdspm_info_system_sample_rate, \
+       .put = snd_hdspm_put_system_sample_rate, \
+       .get = snd_hdspm_get_system_sample_rate \
 }
 
 static int snd_hdspm_info_system_sample_rate(struct snd_kcontrol *kcontrol,
@@ -2030,6 +2037,16 @@ static int snd_hdspm_get_system_sample_rate(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
+static int snd_hdspm_put_system_sample_rate(struct snd_kcontrol *kcontrol,
+                                           struct snd_ctl_elem_value *
+                                           ucontrol)
+{
+       struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
+
+       hdspm_set_dds_value(hdspm, ucontrol->value.enumerated.item[0]);
+       return 0;
+}
+
 
 /**
  * Returns the WordClock sample rate class for the given card.
@@ -2163,6 +2180,7 @@ static int snd_hdspm_get_autosync_sample_rate(struct snd_kcontrol *kcontrol,
                                hdspm_get_s1_sample_rate(hdspm,
                                                kcontrol->private_value-1);
                }
+               break;
 
        case AIO:
                switch (kcontrol->private_value) {
@@ -2183,6 +2201,7 @@ static int snd_hdspm_get_autosync_sample_rate(struct snd_kcontrol *kcontrol,
                                hdspm_get_s1_sample_rate(hdspm,
                                                ucontrol->id.index-1);
                }
+               break;
 
        case AES32:
 
@@ -2204,8 +2223,23 @@ static int snd_hdspm_get_autosync_sample_rate(struct snd_kcontrol *kcontrol,
                                hdspm_get_s1_sample_rate(hdspm,
                                                kcontrol->private_value-1);
                        break;
+               }
+               break;
 
+       case MADI:
+       case MADIface:
+               {
+                       int rate = hdspm_external_sample_rate(hdspm);
+                       int i, selected_rate = 0;
+                       for (i = 1; i < 10; i++)
+                               if (HDSPM_bit2freq(i) == rate) {
+                                       selected_rate = i;
+                                       break;
+                               }
+                       ucontrol->value.enumerated.item[0] = selected_rate;
                }
+               break;
+
        default:
                break;
        }
@@ -2430,7 +2464,7 @@ static int snd_hdspm_put_clock_source(struct snd_kcontrol *kcontrol,
 
 
 #define HDSPM_PREF_SYNC_REF(xname, xindex) \
-{.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
        .name = xname, \
        .index = xindex, \
        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
@@ -2766,12 +2800,12 @@ static int snd_hdspm_put_pref_sync_ref(struct snd_kcontrol *kcontrol,
 
 
 #define HDSPM_AUTOSYNC_REF(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .access = SNDRV_CTL_ELEM_ACCESS_READ, \
-  .info = snd_hdspm_info_autosync_ref, \
-  .get = snd_hdspm_get_autosync_ref, \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .access = SNDRV_CTL_ELEM_ACCESS_READ, \
+       .info = snd_hdspm_info_autosync_ref, \
+       .get = snd_hdspm_get_autosync_ref, \
 }
 
 static int hdspm_autosync_ref(struct hdspm *hdspm)
@@ -2855,12 +2889,12 @@ static int snd_hdspm_get_autosync_ref(struct snd_kcontrol *kcontrol,
 
 
 #define HDSPM_LINE_OUT(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .info = snd_hdspm_info_line_out, \
-  .get = snd_hdspm_get_line_out, \
-  .put = snd_hdspm_put_line_out \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .info = snd_hdspm_info_line_out, \
+       .get = snd_hdspm_get_line_out, \
+       .put = snd_hdspm_put_line_out \
 }
 
 static int hdspm_line_out(struct hdspm * hdspm)
@@ -2912,12 +2946,12 @@ static int snd_hdspm_put_line_out(struct snd_kcontrol *kcontrol,
 
 
 #define HDSPM_TX_64(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .info = snd_hdspm_info_tx_64, \
-  .get = snd_hdspm_get_tx_64, \
-  .put = snd_hdspm_put_tx_64 \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .info = snd_hdspm_info_tx_64, \
+       .get = snd_hdspm_get_tx_64, \
+       .put = snd_hdspm_put_tx_64 \
 }
 
 static int hdspm_tx_64(struct hdspm * hdspm)
@@ -2968,12 +3002,12 @@ static int snd_hdspm_put_tx_64(struct snd_kcontrol *kcontrol,
 
 
 #define HDSPM_C_TMS(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .info = snd_hdspm_info_c_tms, \
-  .get = snd_hdspm_get_c_tms, \
-  .put = snd_hdspm_put_c_tms \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .info = snd_hdspm_info_c_tms, \
+       .get = snd_hdspm_get_c_tms, \
+       .put = snd_hdspm_put_c_tms \
 }
 
 static int hdspm_c_tms(struct hdspm * hdspm)
@@ -3024,12 +3058,12 @@ static int snd_hdspm_put_c_tms(struct snd_kcontrol *kcontrol,
 
 
 #define HDSPM_SAFE_MODE(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .info = snd_hdspm_info_safe_mode, \
-  .get = snd_hdspm_get_safe_mode, \
-  .put = snd_hdspm_put_safe_mode \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .info = snd_hdspm_info_safe_mode, \
+       .get = snd_hdspm_get_safe_mode, \
+       .put = snd_hdspm_put_safe_mode \
 }
 
 static int hdspm_safe_mode(struct hdspm * hdspm)
@@ -3080,12 +3114,12 @@ static int snd_hdspm_put_safe_mode(struct snd_kcontrol *kcontrol,
 
 
 #define HDSPM_EMPHASIS(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .info = snd_hdspm_info_emphasis, \
-  .get = snd_hdspm_get_emphasis, \
-  .put = snd_hdspm_put_emphasis \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .info = snd_hdspm_info_emphasis, \
+       .get = snd_hdspm_get_emphasis, \
+       .put = snd_hdspm_put_emphasis \
 }
 
 static int hdspm_emphasis(struct hdspm * hdspm)
@@ -3136,12 +3170,12 @@ static int snd_hdspm_put_emphasis(struct snd_kcontrol *kcontrol,
 
 
 #define HDSPM_DOLBY(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .info = snd_hdspm_info_dolby, \
-  .get = snd_hdspm_get_dolby, \
-  .put = snd_hdspm_put_dolby \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .info = snd_hdspm_info_dolby, \
+       .get = snd_hdspm_get_dolby, \
+       .put = snd_hdspm_put_dolby \
 }
 
 static int hdspm_dolby(struct hdspm * hdspm)
@@ -3192,12 +3226,12 @@ static int snd_hdspm_put_dolby(struct snd_kcontrol *kcontrol,
 
 
 #define HDSPM_PROFESSIONAL(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .info = snd_hdspm_info_professional, \
-  .get = snd_hdspm_get_professional, \
-  .put = snd_hdspm_put_professional \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .info = snd_hdspm_info_professional, \
+       .get = snd_hdspm_get_professional, \
+       .put = snd_hdspm_put_professional \
 }
 
 static int hdspm_professional(struct hdspm * hdspm)
@@ -3247,12 +3281,12 @@ static int snd_hdspm_put_professional(struct snd_kcontrol *kcontrol,
 }
 
 #define HDSPM_INPUT_SELECT(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .info = snd_hdspm_info_input_select, \
-  .get = snd_hdspm_get_input_select, \
-  .put = snd_hdspm_put_input_select \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .info = snd_hdspm_info_input_select, \
+       .get = snd_hdspm_get_input_select, \
+       .put = snd_hdspm_put_input_select \
 }
 
 static int hdspm_input_select(struct hdspm * hdspm)
@@ -3319,12 +3353,12 @@ static int snd_hdspm_put_input_select(struct snd_kcontrol *kcontrol,
 
 
 #define HDSPM_DS_WIRE(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .info = snd_hdspm_info_ds_wire, \
-  .get = snd_hdspm_get_ds_wire, \
-  .put = snd_hdspm_put_ds_wire \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .info = snd_hdspm_info_ds_wire, \
+       .get = snd_hdspm_get_ds_wire, \
+       .put = snd_hdspm_put_ds_wire \
 }
 
 static int hdspm_ds_wire(struct hdspm * hdspm)
@@ -3391,12 +3425,12 @@ static int snd_hdspm_put_ds_wire(struct snd_kcontrol *kcontrol,
 
 
 #define HDSPM_QS_WIRE(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .info = snd_hdspm_info_qs_wire, \
-  .get = snd_hdspm_get_qs_wire, \
-  .put = snd_hdspm_put_qs_wire \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .info = snd_hdspm_info_qs_wire, \
+       .get = snd_hdspm_get_qs_wire, \
+       .put = snd_hdspm_put_qs_wire \
 }
 
 static int hdspm_qs_wire(struct hdspm * hdspm)
@@ -3563,15 +3597,15 @@ static int snd_hdspm_put_madi_speedmode(struct snd_kcontrol *kcontrol,
 }
 
 #define HDSPM_MIXER(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
-  .name = xname, \
-  .index = xindex, \
-  .device = 0, \
-  .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
-                SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
-  .info = snd_hdspm_info_mixer, \
-  .get = snd_hdspm_get_mixer, \
-  .put = snd_hdspm_put_mixer \
+{      .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+       .name = xname, \
+       .index = xindex, \
+       .device = 0, \
+       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
+               SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
+       .info = snd_hdspm_info_mixer, \
+       .get = snd_hdspm_get_mixer, \
+       .put = snd_hdspm_put_mixer \
 }
 
 static int snd_hdspm_info_mixer(struct snd_kcontrol *kcontrol,
@@ -3670,12 +3704,12 @@ static int snd_hdspm_put_mixer(struct snd_kcontrol *kcontrol,
 */
 
 #define HDSPM_PLAYBACK_MIXER \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE | \
-                SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
-  .info = snd_hdspm_info_playback_mixer, \
-  .get = snd_hdspm_get_playback_mixer, \
-  .put = snd_hdspm_put_playback_mixer \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE | \
+               SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
+       .info = snd_hdspm_info_playback_mixer, \
+       .get = snd_hdspm_get_playback_mixer, \
+       .put = snd_hdspm_put_playback_mixer \
 }
 
 static int snd_hdspm_info_playback_mixer(struct snd_kcontrol *kcontrol,
@@ -3851,12 +3885,17 @@ static int hdspm_sync_in_sync_check(struct hdspm *hdspm)
                break;
 
        case MADI:
-       case AES32:
-               status = hdspm_read(hdspm, HDSPM_statusRegister2);
+               status = hdspm_read(hdspm, HDSPM_statusRegister);
                lock = (status & HDSPM_syncInLock) ? 1 : 0;
                sync = (status & HDSPM_syncInSync) ? 1 : 0;
                break;
 
+       case AES32:
+               status = hdspm_read(hdspm, HDSPM_statusRegister2);
+               lock = (status & 0x100000) ? 1 : 0;
+               sync = (status & 0x200000) ? 1 : 0;
+               break;
+
        case MADIface:
                break;
        }
@@ -3940,8 +3979,10 @@ static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol,
                case 8: /* SYNC IN */
                        val = hdspm_sync_in_sync_check(hdspm); break;
                default:
-                       val = hdspm_s1_sync_check(hdspm, ucontrol->id.index-1);
+                       val = hdspm_s1_sync_check(hdspm,
+                                       kcontrol->private_value-1);
                }
+               break;
 
        case AIO:
                switch (kcontrol->private_value) {
@@ -3954,6 +3995,7 @@ static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol,
                default:
                        val = hdspm_s1_sync_check(hdspm, ucontrol->id.index-1);
                }
+               break;
 
        case MADI:
                switch (kcontrol->private_value) {
@@ -3966,6 +4008,7 @@ static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol,
                case 3: /* SYNC_IN */
                        val = hdspm_sync_in_sync_check(hdspm); break;
                }
+               break;
 
        case MADIface:
                val = hdspm_madi_sync_check(hdspm); /* MADI */
@@ -3983,6 +4026,7 @@ static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol,
                         val = hdspm_aes_sync_check(hdspm,
                                         kcontrol->private_value-1);
                }
+               break;
 
        }
 
@@ -4427,9 +4471,10 @@ static struct snd_kcontrol_new snd_hdspm_controls_madi[] = {
        HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
        HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
        HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
+       HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
        HDSPM_SYNC_CHECK("WC SyncCheck", 0),
        HDSPM_SYNC_CHECK("MADI SyncCheck", 1),
-       HDSPM_SYNC_CHECK("TCO SyncCHeck", 2),
+       HDSPM_SYNC_CHECK("TCO SyncCheck", 2),
        HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 3),
        HDSPM_LINE_OUT("Line Out", 0),
        HDSPM_TX_64("TX 64 channels mode", 0),
@@ -4855,7 +4900,7 @@ snd_hdspm_proc_read_madi(struct snd_info_entry * entry,
                insel = "Coaxial";
                break;
        default:
-               insel = "Unkown";
+               insel = "Unknown";
        }
 
        snd_iprintf(buffer,
index 72b09cfd3dc367d4aa28826e750e27aa2ffb1885..d1b691bf8e2d918cb3e8fd97e61cce74c464cd76 100644 (file)
@@ -6,6 +6,14 @@ config SND_ATMEL_SOC
          the ATMEL SSC interface. You will also need
          to select the audio interfaces to support below.
 
+config SND_ATMEL_SOC_PDC
+       tristate
+       depends on SND_ATMEL_SOC
+
+config SND_ATMEL_SOC_DMA
+       tristate
+       depends on SND_ATMEL_SOC
+
 config SND_ATMEL_SOC_SSC
        tristate
        depends on SND_ATMEL_SOC
@@ -16,8 +24,8 @@ config SND_ATMEL_SOC_SSC
 
 config SND_AT91_SOC_SAM9G20_WM8731
        tristate "SoC Audio support for WM8731-based At91sam9g20 evaluation board"
-       depends on ATMEL_SSC && ARCH_AT91SAM9G20 && SND_ATMEL_SOC && \
-                   AT91_PROGRAMMABLE_CLOCKS
+       depends on ATMEL_SSC && SND_ATMEL_SOC && AT91_PROGRAMMABLE_CLOCKS
+       select SND_ATMEL_SOC_PDC
        select SND_ATMEL_SOC_SSC
        select SND_SOC_WM8731
        help
@@ -27,6 +35,7 @@ config SND_AT91_SOC_SAM9G20_WM8731
 config SND_AT91_SOC_AFEB9260
        tristate "SoC Audio support for AFEB9260 board"
        depends on ATMEL_SSC && ARCH_AT91 && MACH_AFEB9260 && SND_ATMEL_SOC
+       select SND_ATMEL_SOC_PDC
        select SND_ATMEL_SOC_SSC
        select SND_SOC_TLV320AIC23
        help
index a5c0bf19da78f01e823fc614c61528c30272a67c..41967ccb6f41e3968753d4922ad03f2439ad81b9 100644 (file)
@@ -1,8 +1,12 @@
 # AT91 Platform Support
 snd-soc-atmel-pcm-objs := atmel-pcm.o
+snd-soc-atmel-pcm-pdc-objs := atmel-pcm-pdc.o
+snd-soc-atmel-pcm-dma-objs := atmel-pcm-dma.o
 snd-soc-atmel_ssc_dai-objs := atmel_ssc_dai.o
 
 obj-$(CONFIG_SND_ATMEL_SOC) += snd-soc-atmel-pcm.o
+obj-$(CONFIG_SND_ATMEL_SOC_PDC) += snd-soc-atmel-pcm-pdc.o
+obj-$(CONFIG_SND_ATMEL_SOC_DMA) += snd-soc-atmel-pcm-dma.o
 obj-$(CONFIG_SND_ATMEL_SOC_SSC) += snd-soc-atmel_ssc_dai.o
 
 # AT91 Machine Support
diff --git a/sound/soc/atmel/atmel-pcm-dma.c b/sound/soc/atmel/atmel-pcm-dma.c
new file mode 100644 (file)
index 0000000..30184a4
--- /dev/null
@@ -0,0 +1,240 @@
+/*
+ * atmel-pcm-dma.c  --  ALSA PCM DMA support for the Atmel SoC.
+ *
+ *  Copyright (C) 2012 Atmel
+ *
+ * Author: Bo Shen <voice.shen@atmel.com>
+ *
+ * Based on atmel-pcm by:
+ * Sedji Gaouaou <sedji.gaouaou@atmel.com>
+ * Copyright 2008 Atmel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
+#include <linux/atmel-ssc.h>
+#include <linux/platform_data/dma-atmel.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/dmaengine_pcm.h>
+
+#include "atmel-pcm.h"
+
+/*--------------------------------------------------------------------------*\
+ * Hardware definition
+\*--------------------------------------------------------------------------*/
+static const struct snd_pcm_hardware atmel_pcm_dma_hardware = {
+       .info                   = SNDRV_PCM_INFO_MMAP |
+                                 SNDRV_PCM_INFO_MMAP_VALID |
+                                 SNDRV_PCM_INFO_INTERLEAVED |
+                                 SNDRV_PCM_INFO_RESUME |
+                                 SNDRV_PCM_INFO_PAUSE,
+       .formats                = SNDRV_PCM_FMTBIT_S16_LE,
+       .period_bytes_min       = 256,          /* lighting DMA overhead */
+       .period_bytes_max       = 2 * 0xffff,   /* if 2 bytes format */
+       .periods_min            = 8,
+       .periods_max            = 1024,         /* no limit */
+       .buffer_bytes_max       = ATMEL_SSC_DMABUF_SIZE,
+};
+
+/**
+ * atmel_pcm_dma_irq: SSC interrupt handler for DMAENGINE enabled SSC
+ *
+ * We use DMAENGINE to send/receive data to/from SSC so this ISR is only to
+ * check if any overrun occured.
+ */
+static void atmel_pcm_dma_irq(u32 ssc_sr,
+       struct snd_pcm_substream *substream)
+{
+       struct atmel_pcm_dma_params *prtd;
+
+       prtd = snd_dmaengine_pcm_get_data(substream);
+
+       if (ssc_sr & prtd->mask->ssc_error) {
+               if (snd_pcm_running(substream))
+                       pr_warn("atmel-pcm: buffer %s on %s (SSC_SR=%#x)\n",
+                               substream->stream == SNDRV_PCM_STREAM_PLAYBACK
+                               ? "underrun" : "overrun", prtd->name,
+                               ssc_sr);
+
+               /* stop RX and capture: will be enabled again at restart */
+               ssc_writex(prtd->ssc->regs, SSC_CR, prtd->mask->ssc_disable);
+               snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
+
+               /* now drain RHR and read status to remove xrun condition */
+               ssc_readx(prtd->ssc->regs, SSC_RHR);
+               ssc_readx(prtd->ssc->regs, SSC_SR);
+       }
+}
+
+/*--------------------------------------------------------------------------*\
+ * DMAENGINE operations
+\*--------------------------------------------------------------------------*/
+static bool filter(struct dma_chan *chan, void *slave)
+{
+       struct at_dma_slave *sl = slave;
+
+       if (sl->dma_dev == chan->device->dev) {
+               chan->private = sl;
+               return true;
+       } else {
+               return false;
+       }
+}
+
+static int atmel_pcm_configure_dma(struct snd_pcm_substream *substream,
+       struct snd_pcm_hw_params *params)
+{
+       struct atmel_pcm_dma_params *prtd;
+       struct ssc_device *ssc;
+       struct dma_chan *dma_chan;
+       struct dma_slave_config slave_config;
+       int ret;
+
+       prtd = snd_dmaengine_pcm_get_data(substream);
+       ssc = prtd->ssc;
+
+       ret = snd_hwparams_to_dma_slave_config(substream, params,
+                       &slave_config);
+       if (ret) {
+               pr_err("atmel-pcm: hwparams to dma slave configure failed\n");
+               return ret;
+       }
+
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               slave_config.dst_addr = (dma_addr_t)ssc->phybase + SSC_THR;
+               slave_config.dst_maxburst = 1;
+       } else {
+               slave_config.src_addr = (dma_addr_t)ssc->phybase + SSC_RHR;
+               slave_config.src_maxburst = 1;
+       }
+
+       slave_config.device_fc = false;
+
+       dma_chan = snd_dmaengine_pcm_get_chan(substream);
+       if (dmaengine_slave_config(dma_chan, &slave_config)) {
+               pr_err("atmel-pcm: failed to configure dma channel\n");
+               ret = -EBUSY;
+               return ret;
+       }
+
+       return 0;
+}
+
+static int atmel_pcm_hw_params(struct snd_pcm_substream *substream,
+       struct snd_pcm_hw_params *params)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct atmel_pcm_dma_params *prtd;
+       struct ssc_device *ssc;
+       struct at_dma_slave *sdata = NULL;
+       int ret;
+
+       snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
+
+       prtd = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
+       ssc = prtd->ssc;
+       if (ssc->pdev)
+               sdata = ssc->pdev->dev.platform_data;
+
+       ret = snd_dmaengine_pcm_open(substream, filter, sdata);
+       if (ret) {
+               pr_err("atmel-pcm: dmaengine pcm open failed\n");
+               return -EINVAL;
+       }
+
+       snd_dmaengine_pcm_set_data(substream, prtd);
+
+       ret = atmel_pcm_configure_dma(substream, params);
+       if (ret) {
+               pr_err("atmel-pcm: failed to configure dmai\n");
+               goto err;
+       }
+
+       prtd->dma_intr_handler = atmel_pcm_dma_irq;
+
+       return 0;
+err:
+       snd_dmaengine_pcm_close(substream);
+       return ret;
+}
+
+static int atmel_pcm_dma_prepare(struct snd_pcm_substream *substream)
+{
+       struct atmel_pcm_dma_params *prtd;
+
+       prtd = snd_dmaengine_pcm_get_data(substream);
+
+       ssc_writex(prtd->ssc->regs, SSC_IER, prtd->mask->ssc_error);
+       ssc_writex(prtd->ssc->regs, SSC_CR, prtd->mask->ssc_enable);
+
+       return 0;
+}
+
+static int atmel_pcm_open(struct snd_pcm_substream *substream)
+{
+       snd_soc_set_runtime_hwparams(substream, &atmel_pcm_dma_hardware);
+
+       return 0;
+}
+
+static int atmel_pcm_close(struct snd_pcm_substream *substream)
+{
+       snd_dmaengine_pcm_close(substream);
+
+       return 0;
+}
+
+static struct snd_pcm_ops atmel_pcm_ops = {
+       .open           = atmel_pcm_open,
+       .close          = atmel_pcm_close,
+       .ioctl          = snd_pcm_lib_ioctl,
+       .hw_params      = atmel_pcm_hw_params,
+       .prepare        = atmel_pcm_dma_prepare,
+       .trigger        = snd_dmaengine_pcm_trigger,
+       .pointer        = snd_dmaengine_pcm_pointer_no_residue,
+       .mmap           = atmel_pcm_mmap,
+};
+
+static struct snd_soc_platform_driver atmel_soc_platform = {
+       .ops            = &atmel_pcm_ops,
+       .pcm_new        = atmel_pcm_new,
+       .pcm_free       = atmel_pcm_free,
+};
+
+int atmel_pcm_dma_platform_register(struct device *dev)
+{
+       return snd_soc_register_platform(dev, &atmel_soc_platform);
+}
+EXPORT_SYMBOL(atmel_pcm_dma_platform_register);
+
+void atmel_pcm_dma_platform_unregister(struct device *dev)
+{
+       snd_soc_unregister_platform(dev);
+}
+EXPORT_SYMBOL(atmel_pcm_dma_platform_unregister);
+
+MODULE_AUTHOR("Bo Shen <voice.shen@atmel.com>");
+MODULE_DESCRIPTION("Atmel DMA based PCM module");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/atmel/atmel-pcm-pdc.c b/sound/soc/atmel/atmel-pcm-pdc.c
new file mode 100644 (file)
index 0000000..6a293c7
--- /dev/null
@@ -0,0 +1,401 @@
+/*
+ * atmel-pcm.c  --  ALSA PCM interface for the Atmel atmel SoC.
+ *
+ *  Copyright (C) 2005 SAN People
+ *  Copyright (C) 2008 Atmel
+ *
+ * Authors: Sedji Gaouaou <sedji.gaouaou@atmel.com>
+ *
+ * Based on at91-pcm. by:
+ * Frank Mandarino <fmandarino@endrelia.com>
+ * Copyright 2006 Endrelia Technologies Inc.
+ *
+ * Based on pxa2xx-pcm.c by:
+ *
+ * Author:     Nicolas Pitre
+ * Created:    Nov 30, 2004
+ * Copyright:  (C) 2004 MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/atmel_pdc.h>
+#include <linux/atmel-ssc.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include "atmel-pcm.h"
+
+
+/*--------------------------------------------------------------------------*\
+ * Hardware definition
+\*--------------------------------------------------------------------------*/
+/* TODO: These values were taken from the AT91 platform driver, check
+ *      them against real values for AT32
+ */
+static const struct snd_pcm_hardware atmel_pcm_hardware = {
+       .info                   = SNDRV_PCM_INFO_MMAP |
+                                 SNDRV_PCM_INFO_MMAP_VALID |
+                                 SNDRV_PCM_INFO_INTERLEAVED |
+                                 SNDRV_PCM_INFO_PAUSE,
+       .formats                = SNDRV_PCM_FMTBIT_S16_LE,
+       .period_bytes_min       = 32,
+       .period_bytes_max       = 8192,
+       .periods_min            = 2,
+       .periods_max            = 1024,
+       .buffer_bytes_max       = ATMEL_SSC_DMABUF_SIZE,
+};
+
+
+/*--------------------------------------------------------------------------*\
+ * Data types
+\*--------------------------------------------------------------------------*/
+struct atmel_runtime_data {
+       struct atmel_pcm_dma_params *params;
+       dma_addr_t dma_buffer;          /* physical address of dma buffer */
+       dma_addr_t dma_buffer_end;      /* first address beyond DMA buffer */
+       size_t period_size;
+
+       dma_addr_t period_ptr;          /* physical address of next period */
+
+       /* PDC register save */
+       u32 pdc_xpr_save;
+       u32 pdc_xcr_save;
+       u32 pdc_xnpr_save;
+       u32 pdc_xncr_save;
+};
+
+/*--------------------------------------------------------------------------*\
+ * ISR
+\*--------------------------------------------------------------------------*/
+static void atmel_pcm_dma_irq(u32 ssc_sr,
+       struct snd_pcm_substream *substream)
+{
+       struct atmel_runtime_data *prtd = substream->runtime->private_data;
+       struct atmel_pcm_dma_params *params = prtd->params;
+       static int count;
+
+       count++;
+
+       if (ssc_sr & params->mask->ssc_endbuf) {
+               pr_warn("atmel-pcm: buffer %s on %s (SSC_SR=%#x, count=%d)\n",
+                               substream->stream == SNDRV_PCM_STREAM_PLAYBACK
+                               ? "underrun" : "overrun",
+                               params->name, ssc_sr, count);
+
+               /* re-start the PDC */
+               ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
+                          params->mask->pdc_disable);
+               prtd->period_ptr += prtd->period_size;
+               if (prtd->period_ptr >= prtd->dma_buffer_end)
+                       prtd->period_ptr = prtd->dma_buffer;
+
+               ssc_writex(params->ssc->regs, params->pdc->xpr,
+                          prtd->period_ptr);
+               ssc_writex(params->ssc->regs, params->pdc->xcr,
+                          prtd->period_size / params->pdc_xfer_size);
+               ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
+                          params->mask->pdc_enable);
+       }
+
+       if (ssc_sr & params->mask->ssc_endx) {
+               /* Load the PDC next pointer and counter registers */
+               prtd->period_ptr += prtd->period_size;
+               if (prtd->period_ptr >= prtd->dma_buffer_end)
+                       prtd->period_ptr = prtd->dma_buffer;
+
+               ssc_writex(params->ssc->regs, params->pdc->xnpr,
+                          prtd->period_ptr);
+               ssc_writex(params->ssc->regs, params->pdc->xncr,
+                          prtd->period_size / params->pdc_xfer_size);
+       }
+
+       snd_pcm_period_elapsed(substream);
+}
+
+
+/*--------------------------------------------------------------------------*\
+ * PCM operations
+\*--------------------------------------------------------------------------*/
+static int atmel_pcm_hw_params(struct snd_pcm_substream *substream,
+       struct snd_pcm_hw_params *params)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct atmel_runtime_data *prtd = runtime->private_data;
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+
+       /* this may get called several times by oss emulation
+        * with different params */
+
+       snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
+       runtime->dma_bytes = params_buffer_bytes(params);
+
+       prtd->params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
+       prtd->params->dma_intr_handler = atmel_pcm_dma_irq;
+
+       prtd->dma_buffer = runtime->dma_addr;
+       prtd->dma_buffer_end = runtime->dma_addr + runtime->dma_bytes;
+       prtd->period_size = params_period_bytes(params);
+
+       pr_debug("atmel-pcm: "
+               "hw_params: DMA for %s initialized "
+               "(dma_bytes=%u, period_size=%u)\n",
+               prtd->params->name,
+               runtime->dma_bytes,
+               prtd->period_size);
+       return 0;
+}
+
+static int atmel_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+       struct atmel_runtime_data *prtd = substream->runtime->private_data;
+       struct atmel_pcm_dma_params *params = prtd->params;
+
+       if (params != NULL) {
+               ssc_writex(params->ssc->regs, SSC_PDC_PTCR,
+                          params->mask->pdc_disable);
+               prtd->params->dma_intr_handler = NULL;
+       }
+
+       return 0;
+}
+
+static int atmel_pcm_prepare(struct snd_pcm_substream *substream)
+{
+       struct atmel_runtime_data *prtd = substream->runtime->private_data;
+       struct atmel_pcm_dma_params *params = prtd->params;
+
+       ssc_writex(params->ssc->regs, SSC_IDR,
+                  params->mask->ssc_endx | params->mask->ssc_endbuf);
+       ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
+                  params->mask->pdc_disable);
+       return 0;
+}
+
+static int atmel_pcm_trigger(struct snd_pcm_substream *substream,
+       int cmd)
+{
+       struct snd_pcm_runtime *rtd = substream->runtime;
+       struct atmel_runtime_data *prtd = rtd->private_data;
+       struct atmel_pcm_dma_params *params = prtd->params;
+       int ret = 0;
+
+       pr_debug("atmel-pcm:buffer_size = %ld,"
+               "dma_area = %p, dma_bytes = %u\n",
+               rtd->buffer_size, rtd->dma_area, rtd->dma_bytes);
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+               prtd->period_ptr = prtd->dma_buffer;
+
+               ssc_writex(params->ssc->regs, params->pdc->xpr,
+                          prtd->period_ptr);
+               ssc_writex(params->ssc->regs, params->pdc->xcr,
+                          prtd->period_size / params->pdc_xfer_size);
+
+               prtd->period_ptr += prtd->period_size;
+               ssc_writex(params->ssc->regs, params->pdc->xnpr,
+                          prtd->period_ptr);
+               ssc_writex(params->ssc->regs, params->pdc->xncr,
+                          prtd->period_size / params->pdc_xfer_size);
+
+               pr_debug("atmel-pcm: trigger: "
+                       "period_ptr=%lx, xpr=%u, "
+                       "xcr=%u, xnpr=%u, xncr=%u\n",
+                       (unsigned long)prtd->period_ptr,
+                       ssc_readx(params->ssc->regs, params->pdc->xpr),
+                       ssc_readx(params->ssc->regs, params->pdc->xcr),
+                       ssc_readx(params->ssc->regs, params->pdc->xnpr),
+                       ssc_readx(params->ssc->regs, params->pdc->xncr));
+
+               ssc_writex(params->ssc->regs, SSC_IER,
+                          params->mask->ssc_endx | params->mask->ssc_endbuf);
+               ssc_writex(params->ssc->regs, SSC_PDC_PTCR,
+                          params->mask->pdc_enable);
+
+               pr_debug("sr=%u imr=%u\n",
+                       ssc_readx(params->ssc->regs, SSC_SR),
+                       ssc_readx(params->ssc->regs, SSC_IER));
+               break;          /* SNDRV_PCM_TRIGGER_START */
+
+       case SNDRV_PCM_TRIGGER_STOP:
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+               ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
+                          params->mask->pdc_disable);
+               break;
+
+       case SNDRV_PCM_TRIGGER_RESUME:
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+               ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
+                          params->mask->pdc_enable);
+               break;
+
+       default:
+               ret = -EINVAL;
+       }
+
+       return ret;
+}
+
+static snd_pcm_uframes_t atmel_pcm_pointer(
+       struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct atmel_runtime_data *prtd = runtime->private_data;
+       struct atmel_pcm_dma_params *params = prtd->params;
+       dma_addr_t ptr;
+       snd_pcm_uframes_t x;
+
+       ptr = (dma_addr_t) ssc_readx(params->ssc->regs, params->pdc->xpr);
+       x = bytes_to_frames(runtime, ptr - prtd->dma_buffer);
+
+       if (x == runtime->buffer_size)
+               x = 0;
+
+       return x;
+}
+
+static int atmel_pcm_open(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct atmel_runtime_data *prtd;
+       int ret = 0;
+
+       snd_soc_set_runtime_hwparams(substream, &atmel_pcm_hardware);
+
+       /* ensure that buffer size is a multiple of period size */
+       ret = snd_pcm_hw_constraint_integer(runtime,
+                                               SNDRV_PCM_HW_PARAM_PERIODS);
+       if (ret < 0)
+               goto out;
+
+       prtd = kzalloc(sizeof(struct atmel_runtime_data), GFP_KERNEL);
+       if (prtd == NULL) {
+               ret = -ENOMEM;
+               goto out;
+       }
+       runtime->private_data = prtd;
+
+ out:
+       return ret;
+}
+
+static int atmel_pcm_close(struct snd_pcm_substream *substream)
+{
+       struct atmel_runtime_data *prtd = substream->runtime->private_data;
+
+       kfree(prtd);
+       return 0;
+}
+
+static struct snd_pcm_ops atmel_pcm_ops = {
+       .open           = atmel_pcm_open,
+       .close          = atmel_pcm_close,
+       .ioctl          = snd_pcm_lib_ioctl,
+       .hw_params      = atmel_pcm_hw_params,
+       .hw_free        = atmel_pcm_hw_free,
+       .prepare        = atmel_pcm_prepare,
+       .trigger        = atmel_pcm_trigger,
+       .pointer        = atmel_pcm_pointer,
+       .mmap           = atmel_pcm_mmap,
+};
+
+
+/*--------------------------------------------------------------------------*\
+ * ASoC platform driver
+\*--------------------------------------------------------------------------*/
+#ifdef CONFIG_PM
+static int atmel_pcm_suspend(struct snd_soc_dai *dai)
+{
+       struct snd_pcm_runtime *runtime = dai->runtime;
+       struct atmel_runtime_data *prtd;
+       struct atmel_pcm_dma_params *params;
+
+       if (!runtime)
+               return 0;
+
+       prtd = runtime->private_data;
+       params = prtd->params;
+
+       /* disable the PDC and save the PDC registers */
+
+       ssc_writel(params->ssc->regs, PDC_PTCR, params->mask->pdc_disable);
+
+       prtd->pdc_xpr_save = ssc_readx(params->ssc->regs, params->pdc->xpr);
+       prtd->pdc_xcr_save = ssc_readx(params->ssc->regs, params->pdc->xcr);
+       prtd->pdc_xnpr_save = ssc_readx(params->ssc->regs, params->pdc->xnpr);
+       prtd->pdc_xncr_save = ssc_readx(params->ssc->regs, params->pdc->xncr);
+
+       return 0;
+}
+
+static int atmel_pcm_resume(struct snd_soc_dai *dai)
+{
+       struct snd_pcm_runtime *runtime = dai->runtime;
+       struct atmel_runtime_data *prtd;
+       struct atmel_pcm_dma_params *params;
+
+       if (!runtime)
+               return 0;
+
+       prtd = runtime->private_data;
+       params = prtd->params;
+
+       /* restore the PDC registers and enable the PDC */
+       ssc_writex(params->ssc->regs, params->pdc->xpr, prtd->pdc_xpr_save);
+       ssc_writex(params->ssc->regs, params->pdc->xcr, prtd->pdc_xcr_save);
+       ssc_writex(params->ssc->regs, params->pdc->xnpr, prtd->pdc_xnpr_save);
+       ssc_writex(params->ssc->regs, params->pdc->xncr, prtd->pdc_xncr_save);
+
+       ssc_writel(params->ssc->regs, PDC_PTCR, params->mask->pdc_enable);
+       return 0;
+}
+#else
+#define atmel_pcm_suspend      NULL
+#define atmel_pcm_resume       NULL
+#endif
+
+static struct snd_soc_platform_driver atmel_soc_platform = {
+       .ops            = &atmel_pcm_ops,
+       .pcm_new        = atmel_pcm_new,
+       .pcm_free       = atmel_pcm_free,
+       .suspend        = atmel_pcm_suspend,
+       .resume         = atmel_pcm_resume,
+};
+
+int atmel_pcm_pdc_platform_register(struct device *dev)
+{
+       return snd_soc_register_platform(dev, &atmel_soc_platform);
+}
+EXPORT_SYMBOL(atmel_pcm_pdc_platform_register);
+
+void atmel_pcm_pdc_platform_unregister(struct device *dev)
+{
+       snd_soc_unregister_platform(dev);
+}
+EXPORT_SYMBOL(atmel_pcm_pdc_platform_unregister);
+
+MODULE_AUTHOR("Sedji Gaouaou <sedji.gaouaou@atmel.com>");
+MODULE_DESCRIPTION("Atmel PCM module");
+MODULE_LICENSE("GPL");
index 9b84f985770ee4e09ca1d7a8ab04cbe410fda037..e99f1811300aef179a5c1d5c33dc702249175681 100644 (file)
  */
 
 #include <linux/module.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
 #include <linux/dma-mapping.h>
-#include <linux/atmel_pdc.h>
-#include <linux/atmel-ssc.h>
-
-#include <sound/core.h>
 #include <sound/pcm.h>
-#include <sound/pcm_params.h>
 #include <sound/soc.h>
-
 #include "atmel-pcm.h"
 
-
-/*--------------------------------------------------------------------------*\
- * Hardware definition
-\*--------------------------------------------------------------------------*/
-/* TODO: These values were taken from the AT91 platform driver, check
- *      them against real values for AT32
- */
-static const struct snd_pcm_hardware atmel_pcm_hardware = {
-       .info                   = SNDRV_PCM_INFO_MMAP |
-                                 SNDRV_PCM_INFO_MMAP_VALID |
-                                 SNDRV_PCM_INFO_INTERLEAVED |
-                                 SNDRV_PCM_INFO_PAUSE,
-       .formats                = SNDRV_PCM_FMTBIT_S16_LE,
-       .period_bytes_min       = 32,
-       .period_bytes_max       = 8192,
-       .periods_min            = 2,
-       .periods_max            = 1024,
-       .buffer_bytes_max       = 32 * 1024,
-};
-
-
-/*--------------------------------------------------------------------------*\
- * Data types
-\*--------------------------------------------------------------------------*/
-struct atmel_runtime_data {
-       struct atmel_pcm_dma_params *params;
-       dma_addr_t dma_buffer;          /* physical address of dma buffer */
-       dma_addr_t dma_buffer_end;      /* first address beyond DMA buffer */
-       size_t period_size;
-
-       dma_addr_t period_ptr;          /* physical address of next period */
-
-       /* PDC register save */
-       u32 pdc_xpr_save;
-       u32 pdc_xcr_save;
-       u32 pdc_xnpr_save;
-       u32 pdc_xncr_save;
-};
-
-
-/*--------------------------------------------------------------------------*\
- * Helper functions
-\*--------------------------------------------------------------------------*/
 static int atmel_pcm_preallocate_dma_buffer(struct snd_pcm *pcm,
        int stream)
 {
        struct snd_pcm_substream *substream = pcm->streams[stream].substream;
        struct snd_dma_buffer *buf = &substream->dma_buffer;
-       size_t size = atmel_pcm_hardware.buffer_bytes_max;
+       size_t size = ATMEL_SSC_DMABUF_SIZE;
 
        buf->dev.type = SNDRV_DMA_TYPE_DEV;
        buf->dev.dev = pcm->card->dev;
        buf->private_data = NULL;
        buf->area = dma_alloc_coherent(pcm->card->dev, size,
-                                         &buf->addr, GFP_KERNEL);
-       pr_debug("atmel-pcm:"
-               "preallocate_dma_buffer: area=%p, addr=%p, size=%d\n",
-               (void *) buf->area,
-               (void *) buf->addr,
-               size);
+                       &buf->addr, GFP_KERNEL);
+       pr_debug("atmel-pcm: alloc dma buffer: area=%p, addr=%p, size=%d\n",
+                       (void *)buf->area, (void *)buf->addr, size);
 
        if (!buf->area)
                return -ENOMEM;
@@ -113,258 +58,19 @@ static int atmel_pcm_preallocate_dma_buffer(struct snd_pcm *pcm,
        buf->bytes = size;
        return 0;
 }
-/*--------------------------------------------------------------------------*\
- * ISR
-\*--------------------------------------------------------------------------*/
-static void atmel_pcm_dma_irq(u32 ssc_sr,
-       struct snd_pcm_substream *substream)
-{
-       struct atmel_runtime_data *prtd = substream->runtime->private_data;
-       struct atmel_pcm_dma_params *params = prtd->params;
-       static int count;
-
-       count++;
-
-       if (ssc_sr & params->mask->ssc_endbuf) {
-               pr_warning("atmel-pcm: buffer %s on %s"
-                               " (SSC_SR=%#x, count=%d)\n",
-                               substream->stream == SNDRV_PCM_STREAM_PLAYBACK
-                               ? "underrun" : "overrun",
-                               params->name, ssc_sr, count);
-
-               /* re-start the PDC */
-               ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
-                          params->mask->pdc_disable);
-               prtd->period_ptr += prtd->period_size;
-               if (prtd->period_ptr >= prtd->dma_buffer_end)
-                       prtd->period_ptr = prtd->dma_buffer;
-
-               ssc_writex(params->ssc->regs, params->pdc->xpr,
-                          prtd->period_ptr);
-               ssc_writex(params->ssc->regs, params->pdc->xcr,
-                          prtd->period_size / params->pdc_xfer_size);
-               ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
-                          params->mask->pdc_enable);
-       }
-
-       if (ssc_sr & params->mask->ssc_endx) {
-               /* Load the PDC next pointer and counter registers */
-               prtd->period_ptr += prtd->period_size;
-               if (prtd->period_ptr >= prtd->dma_buffer_end)
-                       prtd->period_ptr = prtd->dma_buffer;
-
-               ssc_writex(params->ssc->regs, params->pdc->xnpr,
-                          prtd->period_ptr);
-               ssc_writex(params->ssc->regs, params->pdc->xncr,
-                          prtd->period_size / params->pdc_xfer_size);
-       }
-
-       snd_pcm_period_elapsed(substream);
-}
-
-
-/*--------------------------------------------------------------------------*\
- * PCM operations
-\*--------------------------------------------------------------------------*/
-static int atmel_pcm_hw_params(struct snd_pcm_substream *substream,
-       struct snd_pcm_hw_params *params)
-{
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       struct atmel_runtime_data *prtd = runtime->private_data;
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-
-       /* this may get called several times by oss emulation
-        * with different params */
-
-       snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
-       runtime->dma_bytes = params_buffer_bytes(params);
-
-       prtd->params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
-       prtd->params->dma_intr_handler = atmel_pcm_dma_irq;
-
-       prtd->dma_buffer = runtime->dma_addr;
-       prtd->dma_buffer_end = runtime->dma_addr + runtime->dma_bytes;
-       prtd->period_size = params_period_bytes(params);
-
-       pr_debug("atmel-pcm: "
-               "hw_params: DMA for %s initialized "
-               "(dma_bytes=%u, period_size=%u)\n",
-               prtd->params->name,
-               runtime->dma_bytes,
-               prtd->period_size);
-       return 0;
-}
-
-static int atmel_pcm_hw_free(struct snd_pcm_substream *substream)
-{
-       struct atmel_runtime_data *prtd = substream->runtime->private_data;
-       struct atmel_pcm_dma_params *params = prtd->params;
-
-       if (params != NULL) {
-               ssc_writex(params->ssc->regs, SSC_PDC_PTCR,
-                          params->mask->pdc_disable);
-               prtd->params->dma_intr_handler = NULL;
-       }
-
-       return 0;
-}
-
-static int atmel_pcm_prepare(struct snd_pcm_substream *substream)
-{
-       struct atmel_runtime_data *prtd = substream->runtime->private_data;
-       struct atmel_pcm_dma_params *params = prtd->params;
-
-       ssc_writex(params->ssc->regs, SSC_IDR,
-                  params->mask->ssc_endx | params->mask->ssc_endbuf);
-       ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
-                  params->mask->pdc_disable);
-       return 0;
-}
-
-static int atmel_pcm_trigger(struct snd_pcm_substream *substream,
-       int cmd)
-{
-       struct snd_pcm_runtime *rtd = substream->runtime;
-       struct atmel_runtime_data *prtd = rtd->private_data;
-       struct atmel_pcm_dma_params *params = prtd->params;
-       int ret = 0;
-
-       pr_debug("atmel-pcm:buffer_size = %ld,"
-               "dma_area = %p, dma_bytes = %u\n",
-               rtd->buffer_size, rtd->dma_area, rtd->dma_bytes);
-
-       switch (cmd) {
-       case SNDRV_PCM_TRIGGER_START:
-               prtd->period_ptr = prtd->dma_buffer;
-
-               ssc_writex(params->ssc->regs, params->pdc->xpr,
-                          prtd->period_ptr);
-               ssc_writex(params->ssc->regs, params->pdc->xcr,
-                          prtd->period_size / params->pdc_xfer_size);
-
-               prtd->period_ptr += prtd->period_size;
-               ssc_writex(params->ssc->regs, params->pdc->xnpr,
-                          prtd->period_ptr);
-               ssc_writex(params->ssc->regs, params->pdc->xncr,
-                          prtd->period_size / params->pdc_xfer_size);
-
-               pr_debug("atmel-pcm: trigger: "
-                       "period_ptr=%lx, xpr=%u, "
-                       "xcr=%u, xnpr=%u, xncr=%u\n",
-                       (unsigned long)prtd->period_ptr,
-                       ssc_readx(params->ssc->regs, params->pdc->xpr),
-                       ssc_readx(params->ssc->regs, params->pdc->xcr),
-                       ssc_readx(params->ssc->regs, params->pdc->xnpr),
-                       ssc_readx(params->ssc->regs, params->pdc->xncr));
-
-               ssc_writex(params->ssc->regs, SSC_IER,
-                          params->mask->ssc_endx | params->mask->ssc_endbuf);
-               ssc_writex(params->ssc->regs, SSC_PDC_PTCR,
-                          params->mask->pdc_enable);
-
-               pr_debug("sr=%u imr=%u\n",
-                       ssc_readx(params->ssc->regs, SSC_SR),
-                       ssc_readx(params->ssc->regs, SSC_IER));
-               break;          /* SNDRV_PCM_TRIGGER_START */
-
-       case SNDRV_PCM_TRIGGER_STOP:
-       case SNDRV_PCM_TRIGGER_SUSPEND:
-       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-               ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
-                          params->mask->pdc_disable);
-               break;
-
-       case SNDRV_PCM_TRIGGER_RESUME:
-       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-               ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
-                          params->mask->pdc_enable);
-               break;
-
-       default:
-               ret = -EINVAL;
-       }
 
-       return ret;
-}
-
-static snd_pcm_uframes_t atmel_pcm_pointer(
-       struct snd_pcm_substream *substream)
-{
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       struct atmel_runtime_data *prtd = runtime->private_data;
-       struct atmel_pcm_dma_params *params = prtd->params;
-       dma_addr_t ptr;
-       snd_pcm_uframes_t x;
-
-       ptr = (dma_addr_t) ssc_readx(params->ssc->regs, params->pdc->xpr);
-       x = bytes_to_frames(runtime, ptr - prtd->dma_buffer);
-
-       if (x == runtime->buffer_size)
-               x = 0;
-
-       return x;
-}
-
-static int atmel_pcm_open(struct snd_pcm_substream *substream)
-{
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       struct atmel_runtime_data *prtd;
-       int ret = 0;
-
-       snd_soc_set_runtime_hwparams(substream, &atmel_pcm_hardware);
-
-       /* ensure that buffer size is a multiple of period size */
-       ret = snd_pcm_hw_constraint_integer(runtime,
-                                               SNDRV_PCM_HW_PARAM_PERIODS);
-       if (ret < 0)
-               goto out;
-
-       prtd = kzalloc(sizeof(struct atmel_runtime_data), GFP_KERNEL);
-       if (prtd == NULL) {
-               ret = -ENOMEM;
-               goto out;
-       }
-       runtime->private_data = prtd;
-
- out:
-       return ret;
-}
-
-static int atmel_pcm_close(struct snd_pcm_substream *substream)
-{
-       struct atmel_runtime_data *prtd = substream->runtime->private_data;
-
-       kfree(prtd);
-       return 0;
-}
-
-static int atmel_pcm_mmap(struct snd_pcm_substream *substream,
+int atmel_pcm_mmap(struct snd_pcm_substream *substream,
        struct vm_area_struct *vma)
 {
        return remap_pfn_range(vma, vma->vm_start,
                       substream->dma_buffer.addr >> PAGE_SHIFT,
                       vma->vm_end - vma->vm_start, vma->vm_page_prot);
 }
+EXPORT_SYMBOL_GPL(atmel_pcm_mmap);
 
-static struct snd_pcm_ops atmel_pcm_ops = {
-       .open           = atmel_pcm_open,
-       .close          = atmel_pcm_close,
-       .ioctl          = snd_pcm_lib_ioctl,
-       .hw_params      = atmel_pcm_hw_params,
-       .hw_free        = atmel_pcm_hw_free,
-       .prepare        = atmel_pcm_prepare,
-       .trigger        = atmel_pcm_trigger,
-       .pointer        = atmel_pcm_pointer,
-       .mmap           = atmel_pcm_mmap,
-};
-
-
-/*--------------------------------------------------------------------------*\
- * ASoC platform driver
-\*--------------------------------------------------------------------------*/
 static u64 atmel_pcm_dmamask = DMA_BIT_MASK(32);
 
-static int atmel_pcm_new(struct snd_soc_pcm_runtime *rtd)
+int atmel_pcm_new(struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_card *card = rtd->card->snd_card;
        struct snd_pcm *pcm = rtd->pcm;
@@ -376,6 +82,7 @@ static int atmel_pcm_new(struct snd_soc_pcm_runtime *rtd)
                card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
 
        if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
+               pr_debug("atmel-pcm: allocating PCM playback DMA buffer\n");
                ret = atmel_pcm_preallocate_dma_buffer(pcm,
                        SNDRV_PCM_STREAM_PLAYBACK);
                if (ret)
@@ -383,8 +90,7 @@ static int atmel_pcm_new(struct snd_soc_pcm_runtime *rtd)
        }
 
        if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
-               pr_debug("atmel-pcm:"
-                               "Allocating PCM capture DMA buffer\n");
+               pr_debug("atmel-pcm: allocating PCM capture DMA buffer\n");
                ret = atmel_pcm_preallocate_dma_buffer(pcm,
                        SNDRV_PCM_STREAM_CAPTURE);
                if (ret)
@@ -393,8 +99,9 @@ static int atmel_pcm_new(struct snd_soc_pcm_runtime *rtd)
  out:
        return ret;
 }
+EXPORT_SYMBOL_GPL(atmel_pcm_new);
 
-static void atmel_pcm_free_dma_buffers(struct snd_pcm *pcm)
+void atmel_pcm_free(struct snd_pcm *pcm)
 {
        struct snd_pcm_substream *substream;
        struct snd_dma_buffer *buf;
@@ -413,89 +120,5 @@ static void atmel_pcm_free_dma_buffers(struct snd_pcm *pcm)
                buf->area = NULL;
        }
 }
+EXPORT_SYMBOL_GPL(atmel_pcm_free);
 
-#ifdef CONFIG_PM
-static int atmel_pcm_suspend(struct snd_soc_dai *dai)
-{
-       struct snd_pcm_runtime *runtime = dai->runtime;
-       struct atmel_runtime_data *prtd;
-       struct atmel_pcm_dma_params *params;
-
-       if (!runtime)
-               return 0;
-
-       prtd = runtime->private_data;
-       params = prtd->params;
-
-       /* disable the PDC and save the PDC registers */
-
-       ssc_writel(params->ssc->regs, PDC_PTCR, params->mask->pdc_disable);
-
-       prtd->pdc_xpr_save = ssc_readx(params->ssc->regs, params->pdc->xpr);
-       prtd->pdc_xcr_save = ssc_readx(params->ssc->regs, params->pdc->xcr);
-       prtd->pdc_xnpr_save = ssc_readx(params->ssc->regs, params->pdc->xnpr);
-       prtd->pdc_xncr_save = ssc_readx(params->ssc->regs, params->pdc->xncr);
-
-       return 0;
-}
-
-static int atmel_pcm_resume(struct snd_soc_dai *dai)
-{
-       struct snd_pcm_runtime *runtime = dai->runtime;
-       struct atmel_runtime_data *prtd;
-       struct atmel_pcm_dma_params *params;
-
-       if (!runtime)
-               return 0;
-
-       prtd = runtime->private_data;
-       params = prtd->params;
-
-       /* restore the PDC registers and enable the PDC */
-       ssc_writex(params->ssc->regs, params->pdc->xpr, prtd->pdc_xpr_save);
-       ssc_writex(params->ssc->regs, params->pdc->xcr, prtd->pdc_xcr_save);
-       ssc_writex(params->ssc->regs, params->pdc->xnpr, prtd->pdc_xnpr_save);
-       ssc_writex(params->ssc->regs, params->pdc->xncr, prtd->pdc_xncr_save);
-
-       ssc_writel(params->ssc->regs, PDC_PTCR, params->mask->pdc_enable);
-       return 0;
-}
-#else
-#define atmel_pcm_suspend      NULL
-#define atmel_pcm_resume       NULL
-#endif
-
-static struct snd_soc_platform_driver atmel_soc_platform = {
-       .ops            = &atmel_pcm_ops,
-       .pcm_new        = atmel_pcm_new,
-       .pcm_free       = atmel_pcm_free_dma_buffers,
-       .suspend        = atmel_pcm_suspend,
-       .resume         = atmel_pcm_resume,
-};
-
-static int __devinit atmel_soc_platform_probe(struct platform_device *pdev)
-{
-       return snd_soc_register_platform(&pdev->dev, &atmel_soc_platform);
-}
-
-static int __devexit atmel_soc_platform_remove(struct platform_device *pdev)
-{
-       snd_soc_unregister_platform(&pdev->dev);
-       return 0;
-}
-
-static struct platform_driver atmel_pcm_driver = {
-       .driver = {
-                       .name = "atmel-pcm-audio",
-                       .owner = THIS_MODULE,
-       },
-
-       .probe = atmel_soc_platform_probe,
-       .remove = __devexit_p(atmel_soc_platform_remove),
-};
-
-module_platform_driver(atmel_pcm_driver);
-
-MODULE_AUTHOR("Sedji Gaouaou <sedji.gaouaou@atmel.com>");
-MODULE_DESCRIPTION("Atmel PCM module");
-MODULE_LICENSE("GPL");
index 5e0a95e643298b8f5210e7619139b48a02ae939f..bb45d20e7250aeace79a2595f5f9676349ba05d9 100644 (file)
@@ -36,6 +36,8 @@
 
 #include <linux/atmel-ssc.h>
 
+#define ATMEL_SSC_DMABUF_SIZE  (64 * 1024)
+
 /*
  * Registers and status bits that are required by the PCM driver.
  */
@@ -50,6 +52,7 @@ struct atmel_pdc_regs {
 struct atmel_ssc_mask {
        u32     ssc_enable;             /* SSC recv/trans enable */
        u32     ssc_disable;            /* SSC recv/trans disable */
+       u32     ssc_error;              /* SSC error conditions */
        u32     ssc_endx;               /* SSC ENDTX or ENDRX */
        u32     ssc_endbuf;             /* SSC TXBUFE or RXBUFF */
        u32     pdc_enable;             /* PDC recv/trans enable */
@@ -80,4 +83,35 @@ struct atmel_pcm_dma_params {
 #define ssc_readx(base, reg)            (__raw_readl((base) + (reg)))
 #define ssc_writex(base, reg, value)    __raw_writel((value), (base) + (reg))
 
+int atmel_pcm_new(struct snd_soc_pcm_runtime *rtd);
+void atmel_pcm_free(struct snd_pcm *pcm);
+int atmel_pcm_mmap(struct snd_pcm_substream *substream,
+               struct vm_area_struct *vma);
+
+#ifdef CONFIG_SND_ATMEL_SOC_PDC
+int atmel_pcm_pdc_platform_register(struct device *dev);
+void atmel_pcm_pdc_platform_unregister(struct device *dev);
+#else
+static inline int atmel_pcm_pdc_platform_register(struct device *dev)
+{
+       return 0;
+}
+static inline void atmel_pcm_pdc_platform_unregister(struct device *dev)
+{
+}
+#endif
+
+#ifdef CONFIG_SND_ATMEL_SOC_DMA
+int atmel_pcm_dma_platform_register(struct device *dev);
+void atmel_pcm_dma_platform_unregister(struct device *dev);
+#else
+static inline int atmel_pcm_dma_platform_register(struct device *dev)
+{
+       return 0;
+}
+static inline void atmel_pcm_dma_platform_unregister(struct device *dev)
+{
+}
+#endif
+
 #endif /* _ATMEL_PCM_H */
index 354341ec0f42f1129adbaaf310366af46b866229..1c7663422054049265957743bad8c6f8678e9e17 100644 (file)
 #include "atmel_ssc_dai.h"
 
 
-#if defined(CONFIG_ARCH_AT91SAM9260) || defined(CONFIG_ARCH_AT91SAM9G20)
-#define NUM_SSC_DEVICES                1
-#else
 #define NUM_SSC_DEVICES                3
-#endif
 
 /*
  * SSC PDC registers required by the PCM DMA engine.
@@ -107,7 +103,6 @@ static struct atmel_pcm_dma_params ssc_dma_params[NUM_SSC_DEVICES][2] = {
        .pdc            = &pdc_rx_reg,
        .mask           = &ssc_rx_mask,
        } },
-#if NUM_SSC_DEVICES == 3
        {{
        .name           = "SSC1 PCM out",
        .pdc            = &pdc_tx_reg,
@@ -128,7 +123,6 @@ static struct atmel_pcm_dma_params ssc_dma_params[NUM_SSC_DEVICES][2] = {
        .pdc            = &pdc_rx_reg,
        .mask           = &ssc_rx_mask,
        } },
-#endif
 };
 
 
@@ -139,7 +133,6 @@ static struct atmel_ssc_info ssc_info[NUM_SSC_DEVICES] = {
        .dir_mask       = SSC_DIR_MASK_UNUSED,
        .initialized    = 0,
        },
-#if NUM_SSC_DEVICES == 3
        {
        .name           = "ssc1",
        .lock           = __SPIN_LOCK_UNLOCKED(ssc_info[1].lock),
@@ -152,7 +145,6 @@ static struct atmel_ssc_info ssc_info[NUM_SSC_DEVICES] = {
        .dir_mask       = SSC_DIR_MASK_UNUSED,
        .initialized    = 0,
        },
-#endif
 };
 
 
@@ -690,27 +682,9 @@ static int atmel_ssc_resume(struct snd_soc_dai *cpu_dai)
 static int atmel_ssc_probe(struct snd_soc_dai *dai)
 {
        struct atmel_ssc_info *ssc_p = &ssc_info[dai->id];
-       int ret = 0;
 
        snd_soc_dai_set_drvdata(dai, ssc_p);
 
-       /*
-        * Request SSC device
-        */
-       ssc_p->ssc = ssc_request(dai->id);
-       if (IS_ERR(ssc_p->ssc)) {
-               printk(KERN_ERR "ASoC: Failed to request SSC %d\n", dai->id);
-               ret = PTR_ERR(ssc_p->ssc);
-       }
-
-       return ret;
-}
-
-static int atmel_ssc_remove(struct snd_soc_dai *dai)
-{
-       struct atmel_ssc_info *ssc_p = snd_soc_dai_get_drvdata(dai);
-
-       ssc_free(ssc_p->ssc);
        return 0;
 }
 
@@ -728,30 +702,8 @@ static const struct snd_soc_dai_ops atmel_ssc_dai_ops = {
        .set_clkdiv     = atmel_ssc_set_dai_clkdiv,
 };
 
-static struct snd_soc_dai_driver atmel_ssc_dai[NUM_SSC_DEVICES] = {
-       {
-               .name = "atmel-ssc-dai.0",
-               .probe = atmel_ssc_probe,
-               .remove = atmel_ssc_remove,
-               .suspend = atmel_ssc_suspend,
-               .resume = atmel_ssc_resume,
-               .playback = {
-                       .channels_min = 1,
-                       .channels_max = 2,
-                       .rates = ATMEL_SSC_RATES,
-                       .formats = ATMEL_SSC_FORMATS,},
-               .capture = {
-                       .channels_min = 1,
-                       .channels_max = 2,
-                       .rates = ATMEL_SSC_RATES,
-                       .formats = ATMEL_SSC_FORMATS,},
-               .ops = &atmel_ssc_dai_ops,
-       },
-#if NUM_SSC_DEVICES == 3
-       {
-               .name = "atmel-ssc-dai.1",
+static struct snd_soc_dai_driver atmel_ssc_dai = {
                .probe = atmel_ssc_probe,
-               .remove = atmel_ssc_remove,
                .suspend = atmel_ssc_suspend,
                .resume = atmel_ssc_resume,
                .playback = {
@@ -765,50 +717,50 @@ static struct snd_soc_dai_driver atmel_ssc_dai[NUM_SSC_DEVICES] = {
                        .rates = ATMEL_SSC_RATES,
                        .formats = ATMEL_SSC_FORMATS,},
                .ops = &atmel_ssc_dai_ops,
-       },
-       {
-               .name = "atmel-ssc-dai.2",
-               .probe = atmel_ssc_probe,
-               .remove = atmel_ssc_remove,
-               .suspend = atmel_ssc_suspend,
-               .resume = atmel_ssc_resume,
-               .playback = {
-                       .channels_min = 1,
-                       .channels_max = 2,
-                       .rates = ATMEL_SSC_RATES,
-                       .formats = ATMEL_SSC_FORMATS,},
-               .capture = {
-                       .channels_min = 1,
-                       .channels_max = 2,
-                       .rates = ATMEL_SSC_RATES,
-                       .formats = ATMEL_SSC_FORMATS,},
-               .ops = &atmel_ssc_dai_ops,
-       },
-#endif
 };
 
-static __devinit int asoc_ssc_probe(struct platform_device *pdev)
+static int asoc_ssc_init(struct device *dev)
 {
-       BUG_ON(pdev->id < 0);
-       BUG_ON(pdev->id >= ARRAY_SIZE(atmel_ssc_dai));
-       return snd_soc_register_dai(&pdev->dev, &atmel_ssc_dai[pdev->id]);
-}
+       struct platform_device *pdev = to_platform_device(dev);
+       struct ssc_device *ssc = platform_get_drvdata(pdev);
+       int ret;
+
+       ret = snd_soc_register_dai(dev, &atmel_ssc_dai);
+       if (ret) {
+               dev_err(dev, "Could not register DAI: %d\n", ret);
+               goto err;
+       }
+
+       if (ssc->pdata->use_dma)
+               ret = atmel_pcm_dma_platform_register(dev);
+       else
+               ret = atmel_pcm_pdc_platform_register(dev);
+
+       if (ret) {
+               dev_err(dev, "Could not register PCM: %d\n", ret);
+               goto err_unregister_dai;
+       };
 
-static int __devexit asoc_ssc_remove(struct platform_device *pdev)
-{
-       snd_soc_unregister_dai(&pdev->dev);
        return 0;
+
+err_unregister_dai:
+       snd_soc_unregister_dai(dev);
+err:
+       return ret;
 }
 
-static struct platform_driver asoc_ssc_driver = {
-       .driver = {
-                       .name = "atmel-ssc-dai",
-                       .owner = THIS_MODULE,
-       },
+static void asoc_ssc_exit(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct ssc_device *ssc = platform_get_drvdata(pdev);
 
-       .probe = asoc_ssc_probe,
-       .remove = __devexit_p(asoc_ssc_remove),
-};
+       if (ssc->pdata->use_dma)
+               atmel_pcm_dma_platform_unregister(dev);
+       else
+               atmel_pcm_pdc_platform_unregister(dev);
+
+       snd_soc_unregister_dai(dev);
+}
 
 /**
  * atmel_ssc_set_audio - Allocate the specified SSC for audio use.
@@ -816,50 +768,32 @@ static struct platform_driver asoc_ssc_driver = {
 int atmel_ssc_set_audio(int ssc_id)
 {
        struct ssc_device *ssc;
-       static struct platform_device *dma_pdev;
-       struct platform_device *ssc_pdev;
        int ret;
 
-       if (ssc_id < 0 || ssc_id >= ARRAY_SIZE(atmel_ssc_dai))
-               return -EINVAL;
-
-       /* Allocate a dummy device for DMA if we don't have one already */
-       if (!dma_pdev) {
-               dma_pdev = platform_device_alloc("atmel-pcm-audio", -1);
-               if (!dma_pdev)
-                       return -ENOMEM;
-
-               ret = platform_device_add(dma_pdev);
-               if (ret < 0) {
-                       platform_device_put(dma_pdev);
-                       dma_pdev = NULL;
-                       return ret;
-               }
-       }
-
-       ssc_pdev = platform_device_alloc("atmel-ssc-dai", ssc_id);
-       if (!ssc_pdev)
-               return -ENOMEM;
-
        /* If we can grab the SSC briefly to parent the DAI device off it */
        ssc = ssc_request(ssc_id);
-       if (IS_ERR(ssc))
-               pr_warn("Unable to parent ASoC SSC DAI on SSC: %ld\n",
+       if (IS_ERR(ssc)) {
+               pr_err("Unable to parent ASoC SSC DAI on SSC: %ld\n",
                        PTR_ERR(ssc));
-       else {
-               ssc_pdev->dev.parent = &(ssc->pdev->dev);
-               ssc_free(ssc);
+               return PTR_ERR(ssc);
+       } else {
+               ssc_info[ssc_id].ssc = ssc;
        }
 
-       ret = platform_device_add(ssc_pdev);
-       if (ret < 0)
-               platform_device_put(ssc_pdev);
+       ret = asoc_ssc_init(&ssc->pdev->dev);
 
        return ret;
 }
 EXPORT_SYMBOL_GPL(atmel_ssc_set_audio);
 
-module_platform_driver(asoc_ssc_driver);
+void atmel_ssc_put_audio(int ssc_id)
+{
+       struct ssc_device *ssc = ssc_info[ssc_id].ssc;
+
+       ssc_free(ssc);
+       asoc_ssc_exit(&ssc->pdev->dev);
+}
+EXPORT_SYMBOL_GPL(atmel_ssc_put_audio);
 
 /* Module information */
 MODULE_AUTHOR("Sedji Gaouaou, sedji.gaouaou@atmel.com, www.atmel.com");
index 5d4f0f9b4d9a875eb935ec79488b76ff17073ab0..b1f08d51149526006021c7314aa4f3e15847de3d 100644 (file)
@@ -117,6 +117,7 @@ struct atmel_ssc_info {
        struct atmel_ssc_state ssc_state;
 };
 
-int atmel_ssc_set_audio(int ssc);
+int atmel_ssc_set_audio(int ssc_id);
+void atmel_ssc_put_audio(int ssc_id);
 
 #endif /* _AT91_SSC_DAI_H */
index c88351488f45c5c6adb0529a212ab257531a90fd..0744610e53dd97201d4a5e24099aa58e337b44fc 100644 (file)
@@ -38,6 +38,8 @@
 #include <linux/platform_device.h>
 #include <linux/i2c.h>
 
+#include <linux/pinctrl/consumer.h>
+
 #include <linux/atmel-ssc.h>
 
 #include <sound/core.h>
@@ -179,10 +181,10 @@ static int at91sam9g20ek_wm8731_init(struct snd_soc_pcm_runtime *rtd)
 static struct snd_soc_dai_link at91sam9g20ek_dai = {
        .name = "WM8731",
        .stream_name = "WM8731 PCM",
-       .cpu_dai_name = "atmel-ssc-dai.0",
+       .cpu_dai_name = "at91rm9200_ssc.0",
        .codec_dai_name = "wm8731-hifi",
        .init = at91sam9g20ek_wm8731_init,
-       .platform_name = "atmel-pcm-audio",
+       .platform_name = "at91rm9200_ssc.0",
        .codec_name = "wm8731.0-001b",
        .ops = &at91sam9g20ek_ops,
 };
@@ -195,20 +197,31 @@ static struct snd_soc_card snd_soc_at91sam9g20ek = {
        .set_bias_level = at91sam9g20ek_set_bias_level,
 };
 
-static struct platform_device *at91sam9g20ek_snd_device;
-
-static int __init at91sam9g20ek_init(void)
+static int __devinit at91sam9g20ek_audio_probe(struct platform_device *pdev)
 {
+       struct device_node *np = pdev->dev.of_node;
+       struct device_node *codec_np, *cpu_np;
        struct clk *pllb;
+       struct snd_soc_card *card = &snd_soc_at91sam9g20ek;
+       struct pinctrl *pinctrl;
        int ret;
 
-       if (!(machine_is_at91sam9g20ek() || machine_is_at91sam9g20ek_2mmc()))
-               return -ENODEV;
+       pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+       if (IS_ERR(pinctrl)) {
+               dev_err(&pdev->dev, "Failed to request pinctrl for mck\n");
+               return PTR_ERR(pinctrl);
+       }
+
+       if (!np) {
+               if (!(machine_is_at91sam9g20ek() ||
+                       machine_is_at91sam9g20ek_2mmc()))
+                       return -ENODEV;
+       }
 
        ret = atmel_ssc_set_audio(0);
-       if (ret != 0) {
-               pr_err("Failed to set SSC 0 for audio: %d\n", ret);
-               return ret;
+       if (ret) {
+               dev_err(&pdev->dev, "ssc channel is not valid\n");
+               return -EINVAL;
        }
 
        /*
@@ -236,45 +249,92 @@ static int __init at91sam9g20ek_init(void)
 
        clk_set_rate(mclk, MCLK_RATE);
 
-       at91sam9g20ek_snd_device = platform_device_alloc("soc-audio", -1);
-       if (!at91sam9g20ek_snd_device) {
-               printk(KERN_ERR "ASoC: Platform device allocation failed\n");
-               ret = -ENOMEM;
-               goto err_mclk;
+       card->dev = &pdev->dev;
+
+       /* Parse device node info */
+       if (np) {
+               ret = snd_soc_of_parse_card_name(card, "atmel,model");
+               if (ret)
+                       goto err;
+
+               ret = snd_soc_of_parse_audio_routing(card,
+                       "atmel,audio-routing");
+               if (ret)
+                       goto err;
+
+               /* Parse codec info */
+               at91sam9g20ek_dai.codec_name = NULL;
+               codec_np = of_parse_phandle(np, "atmel,audio-codec", 0);
+               if (!codec_np) {
+                       dev_err(&pdev->dev, "codec info missing\n");
+                       return -EINVAL;
+               }
+               at91sam9g20ek_dai.codec_of_node = codec_np;
+
+               /* Parse dai and platform info */
+               at91sam9g20ek_dai.cpu_dai_name = NULL;
+               at91sam9g20ek_dai.platform_name = NULL;
+               cpu_np = of_parse_phandle(np, "atmel,ssc-controller", 0);
+               if (!cpu_np) {
+                       dev_err(&pdev->dev, "dai and pcm info missing\n");
+                       return -EINVAL;
+               }
+               at91sam9g20ek_dai.cpu_of_node = cpu_np;
+               at91sam9g20ek_dai.platform_of_node = cpu_np;
+
+               of_node_put(codec_np);
+               of_node_put(cpu_np);
        }
 
-       platform_set_drvdata(at91sam9g20ek_snd_device,
-                       &snd_soc_at91sam9g20ek);
-
-       ret = platform_device_add(at91sam9g20ek_snd_device);
+       ret = snd_soc_register_card(card);
        if (ret) {
-               printk(KERN_ERR "ASoC: Platform device allocation failed\n");
-               goto err_device_add;
+               printk(KERN_ERR "ASoC: snd_soc_register_card() failed\n");
        }
 
        return ret;
 
-err_device_add:
-       platform_device_put(at91sam9g20ek_snd_device);
 err_mclk:
        clk_put(mclk);
        mclk = NULL;
 err:
+       atmel_ssc_put_audio(0);
        return ret;
 }
 
-static void __exit at91sam9g20ek_exit(void)
+static int __devexit at91sam9g20ek_audio_remove(struct platform_device *pdev)
 {
-       platform_device_unregister(at91sam9g20ek_snd_device);
-       at91sam9g20ek_snd_device = NULL;
+       struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+       atmel_ssc_put_audio(0);
+       snd_soc_unregister_card(card);
        clk_put(mclk);
        mclk = NULL;
+
+       return 0;
 }
 
-module_init(at91sam9g20ek_init);
-module_exit(at91sam9g20ek_exit);
+#ifdef CONFIG_OF
+static const struct of_device_id at91sam9g20ek_wm8731_dt_ids[] = {
+       { .compatible = "atmel,at91sam9g20ek-wm8731-audio", },
+       { }
+};
+MODULE_DEVICE_TABLE(of, at91sam9g20ek_wm8731_dt_ids);
+#endif
+
+static struct platform_driver at91sam9g20ek_audio_driver = {
+       .driver = {
+               .name   = "at91sam9g20ek-audio",
+               .owner  = THIS_MODULE,
+               .of_match_table = of_match_ptr(at91sam9g20ek_wm8731_dt_ids),
+       },
+       .probe  = at91sam9g20ek_audio_probe,
+       .remove = __devexit_p(at91sam9g20ek_audio_remove),
+};
+
+module_platform_driver(at91sam9g20ek_audio_driver);
 
 /* Module information */
 MODULE_AUTHOR("Sedji Gaouaou <sedji.gaouaou@atmel.com>");
 MODULE_DESCRIPTION("ALSA SoC AT91SAM9G20EK_WM8731");
+MODULE_ALIAS("platform:at91sam9g20ek-audio");
 MODULE_LICENSE("GPL");
index b92759a3936157e0884b98f752935ccbef7b8945..80799639814e1f668a63ea0b871f38474a1a69ef 100644 (file)
@@ -146,6 +146,13 @@ config SND_SOC_WM_HUBS
        default y if SND_SOC_WM8993=y || SND_SOC_WM8994=y
        default m if SND_SOC_WM8993=m || SND_SOC_WM8994=m
 
+config SND_SOC_WM_ADSP
+       tristate
+       default y if SND_SOC_WM5102=y
+       default y if SND_SOC_WM2200=y
+       default m if SND_SOC_WM5102=m
+       default m if SND_SOC_WM2200=m
+
 config SND_SOC_AB8500_CODEC
        tristate
 
index 9bd4d95aab4ffcecb9abf5bff4e0c94d7203adee..61633d5ff3da32f6114d06513205ed1e60cdb241 100644 (file)
@@ -62,6 +62,7 @@ snd-soc-twl6040-objs := twl6040.o
 snd-soc-uda134x-objs := uda134x.o
 snd-soc-uda1380-objs := uda1380.o
 snd-soc-wl1273-objs := wl1273.o
+snd-soc-wm-adsp-objs := wm_adsp.o
 snd-soc-wm0010-objs := wm0010.o
 snd-soc-wm1250-ev1-objs := wm1250-ev1.o
 snd-soc-wm2000-objs := wm2000.o
@@ -229,6 +230,7 @@ obj-$(CONFIG_SND_SOC_WM9090)        += snd-soc-wm9090.o
 obj-$(CONFIG_SND_SOC_WM9705)   += snd-soc-wm9705.o
 obj-$(CONFIG_SND_SOC_WM9712)   += snd-soc-wm9712.o
 obj-$(CONFIG_SND_SOC_WM9713)   += snd-soc-wm9713.o
+obj-$(CONFIG_SND_SOC_WM_ADSP)  += snd-soc-wm-adsp.o
 obj-$(CONFIG_SND_SOC_WM_HUBS)  += snd-soc-wm-hubs.o
 
 # Amp
index af547490b4f7f6e0b1dbada793259c64a513a203..4d96090db66297b44b10219f21f26e768c431935 100644 (file)
@@ -2356,7 +2356,7 @@ static int ab8500_codec_set_dai_tdm_slot(struct snd_soc_dai *dai,
        return 0;
 }
 
-struct snd_soc_dai_driver ab8500_codec_dai[] = {
+static struct snd_soc_dai_driver ab8500_codec_dai[] = {
        {
                .name = "ab8500-codec-dai.0",
                .id = 0,
index 31d4483245d0db951584a0e1619b91c8ac8fa726..4b11b82b227393c5d6a60311f417c7b846976bfa 100644 (file)
@@ -15,6 +15,8 @@
 #include <sound/soc.h>
 #include <sound/initval.h>
 #include <linux/spi/spi.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
 #include <sound/asoundef.h>
 
 /* AK4104 registers addresses */
@@ -98,14 +100,32 @@ static int ak4104_hw_params(struct snd_pcm_substream *substream,
        val = 0;
 
        switch (params_rate(params)) {
+       case 22050:
+               val |= IEC958_AES3_CON_FS_22050;
+               break;
+       case 24000:
+               val |= IEC958_AES3_CON_FS_24000;
+               break;
+       case 32000:
+               val |= IEC958_AES3_CON_FS_32000;
+               break;
        case 44100:
                val |= IEC958_AES3_CON_FS_44100;
                break;
        case 48000:
                val |= IEC958_AES3_CON_FS_48000;
                break;
-       case 32000:
-               val |= IEC958_AES3_CON_FS_32000;
+       case 88200:
+               val |= IEC958_AES3_CON_FS_88200;
+               break;
+       case 96000:
+               val |= IEC958_AES3_CON_FS_96000;
+               break;
+       case 176400:
+               val |= IEC958_AES3_CON_FS_176400;
+               break;
+       case 192000:
+               val |= IEC958_AES3_CON_FS_192000;
                break;
        default:
                dev_err(codec->dev, "unsupported sampling rate\n");
@@ -186,6 +206,7 @@ static const struct regmap_config ak4104_regmap = {
 
 static int ak4104_spi_probe(struct spi_device *spi)
 {
+       struct device_node *np = spi->dev.of_node;
        struct ak4104_private *ak4104;
        unsigned int val;
        int ret;
@@ -201,49 +222,59 @@ static int ak4104_spi_probe(struct spi_device *spi)
        if (ak4104 == NULL)
                return -ENOMEM;
 
-       ak4104->regmap = regmap_init_spi(spi, &ak4104_regmap);
+       ak4104->regmap = devm_regmap_init_spi(spi, &ak4104_regmap);
        if (IS_ERR(ak4104->regmap)) {
                ret = PTR_ERR(ak4104->regmap);
                return ret;
        }
 
+       if (np) {
+               enum of_gpio_flags flags;
+               int gpio = of_get_named_gpio_flags(np, "reset-gpio", 0, &flags);
+
+               if (gpio_is_valid(gpio)) {
+                       ret = devm_gpio_request_one(&spi->dev, gpio,
+                                    flags & OF_GPIO_ACTIVE_LOW ?
+                                       GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH,
+                                    "ak4104 reset");
+                       if (ret < 0)
+                               return ret;
+               }
+       }
+
        /* read the 'reserved' register - according to the datasheet, it
         * should contain 0x5b. Not a good way to verify the presence of
         * the device, but there is no hardware ID register. */
        ret = regmap_read(ak4104->regmap, AK4104_REG_RESERVED, &val);
        if (ret != 0)
-               goto err;
-       if (val != AK4104_RESERVED_VAL) {
-               ret = -ENODEV;
-               goto err;
-       }
+               return ret;
+       if (val != AK4104_RESERVED_VAL)
+               return -ENODEV;
 
        spi_set_drvdata(spi, ak4104);
 
        ret = snd_soc_register_codec(&spi->dev,
                        &soc_codec_device_ak4104, &ak4104_dai, 1);
-       if (ret != 0)
-               goto err;
-
-       return 0;
-
-err:
-       regmap_exit(ak4104->regmap);
        return ret;
 }
 
 static int __devexit ak4104_spi_remove(struct spi_device *spi)
 {
-       struct ak4104_private *ak4101 = spi_get_drvdata(spi);
-       regmap_exit(ak4101->regmap);
        snd_soc_unregister_codec(&spi->dev);
        return 0;
 }
 
+static const struct of_device_id ak4104_of_match[] = {
+       { .compatible = "asahi-kasei,ak4104", },
+       { }
+};
+MODULE_DEVICE_TABLE(of, ak4104_of_match);
+
 static struct spi_driver ak4104_spi_driver = {
        .driver  = {
                .name   = DRV_NAME,
                .owner  = THIS_MODULE,
+               .of_match_table = ak4104_of_match,
        },
        .probe  = ak4104_spi_probe,
        .remove = __devexit_p(ak4104_spi_remove),
index 618fdc30f73eb3889f2372e4bba9033d3675270d..fc5581063b2da414c789402648508cb5a1766796 100644 (file)
@@ -447,7 +447,7 @@ static __devinit int ak4535_i2c_probe(struct i2c_client *i2c,
        if (ak4535 == NULL)
                return -ENOMEM;
 
-       ak4535->regmap = regmap_init_i2c(i2c, &ak4535_regmap);
+       ak4535->regmap = devm_regmap_init_i2c(i2c, &ak4535_regmap);
        if (IS_ERR(ak4535->regmap)) {
                ret = PTR_ERR(ak4535->regmap);
                dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret);
@@ -458,18 +458,13 @@ static __devinit int ak4535_i2c_probe(struct i2c_client *i2c,
 
        ret = snd_soc_register_codec(&i2c->dev,
                        &soc_codec_dev_ak4535, &ak4535_dai, 1);
-       if (ret != 0)
-               regmap_exit(ak4535->regmap);
 
        return ret;
 }
 
 static __devexit int ak4535_i2c_remove(struct i2c_client *client)
 {
-       struct ak4535_priv *ak4535 = i2c_get_clientdata(client);
-
        snd_soc_unregister_codec(&client->dev);
-       regmap_exit(ak4535->regmap);
        return 0;
 }
 
index b3e24f289421a7fda3dda11043039179c4777535..546466abb77f74b6be5cad2395bbc5049a8bfb45 100644 (file)
@@ -194,12 +194,6 @@ static const struct snd_soc_dapm_route ak4642_intercon[] = {
        {"LINEOUT Mixer", "DACL", "DAC"},
 };
 
-/* codec private data */
-struct ak4642_priv {
-       unsigned int sysclk;
-       enum snd_soc_control_type control_type;
-};
-
 /*
  * ak4642 register cache
  */
@@ -468,10 +462,9 @@ static int ak4642_resume(struct snd_soc_codec *codec)
 
 static int ak4642_probe(struct snd_soc_codec *codec)
 {
-       struct ak4642_priv *ak4642 = snd_soc_codec_get_drvdata(codec);
        int ret;
 
-       ret = snd_soc_codec_set_cache_io(codec, 8, 8, ak4642->control_type);
+       ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C);
        if (ret < 0) {
                dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
                return ret;
@@ -523,21 +516,9 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4648 = {
 static __devinit int ak4642_i2c_probe(struct i2c_client *i2c,
                                      const struct i2c_device_id *id)
 {
-       struct ak4642_priv *ak4642;
-       int ret;
-
-       ak4642 = devm_kzalloc(&i2c->dev, sizeof(struct ak4642_priv),
-                             GFP_KERNEL);
-       if (!ak4642)
-               return -ENOMEM;
-
-       i2c_set_clientdata(i2c, ak4642);
-       ak4642->control_type = SND_SOC_I2C;
-
-       ret =  snd_soc_register_codec(&i2c->dev,
+       return snd_soc_register_codec(&i2c->dev,
                                (struct snd_soc_codec_driver *)id->driver_data,
                                &ak4642_dai, 1);
-       return ret;
 }
 
 static __devexit int ak4642_i2c_remove(struct i2c_client *client)
index c03b65af30598f8f03dfba2d7353913a33a0bfe9..adf397b9d0e650eb19768e7bc6c592352014a595 100644 (file)
@@ -226,6 +226,31 @@ EXPORT_SYMBOL_GPL(arizona_mixer_values);
 const DECLARE_TLV_DB_SCALE(arizona_mixer_tlv, -3200, 100, 0);
 EXPORT_SYMBOL_GPL(arizona_mixer_tlv);
 
+static const char *arizona_vol_ramp_text[] = {
+       "0ms/6dB", "0.5ms/6dB", "1ms/6dB", "2ms/6dB", "4ms/6dB", "8ms/6dB",
+       "15ms/6dB", "30ms/6dB",
+};
+
+const struct soc_enum arizona_in_vd_ramp =
+       SOC_ENUM_SINGLE(ARIZONA_INPUT_VOLUME_RAMP,
+                       ARIZONA_IN_VD_RAMP_SHIFT, 7, arizona_vol_ramp_text);
+EXPORT_SYMBOL_GPL(arizona_in_vd_ramp);
+
+const struct soc_enum arizona_in_vi_ramp =
+       SOC_ENUM_SINGLE(ARIZONA_INPUT_VOLUME_RAMP,
+                       ARIZONA_IN_VI_RAMP_SHIFT, 7, arizona_vol_ramp_text);
+EXPORT_SYMBOL_GPL(arizona_in_vi_ramp);
+
+const struct soc_enum arizona_out_vd_ramp =
+       SOC_ENUM_SINGLE(ARIZONA_OUTPUT_VOLUME_RAMP,
+                       ARIZONA_OUT_VD_RAMP_SHIFT, 7, arizona_vol_ramp_text);
+EXPORT_SYMBOL_GPL(arizona_out_vd_ramp);
+
+const struct soc_enum arizona_out_vi_ramp =
+       SOC_ENUM_SINGLE(ARIZONA_OUTPUT_VOLUME_RAMP,
+                       ARIZONA_OUT_VI_RAMP_SHIFT, 7, arizona_vol_ramp_text);
+EXPORT_SYMBOL_GPL(arizona_out_vi_ramp);
+
 static const char *arizona_lhpf_mode_text[] = {
        "Low-pass", "High-pass"
 };
@@ -268,7 +293,7 @@ EXPORT_SYMBOL_GPL(arizona_out_ev);
 static unsigned int arizona_sysclk_48k_rates[] = {
        6144000,
        12288000,
-       22579200,
+       24576000,
        49152000,
        73728000,
        98304000,
@@ -278,7 +303,7 @@ static unsigned int arizona_sysclk_48k_rates[] = {
 static unsigned int arizona_sysclk_44k1_rates[] = {
        5644800,
        11289600,
-       24576000,
+       22579200,
        45158400,
        67737600,
        90316800,
@@ -380,6 +405,18 @@ int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id,
        case 49152000:
                val |= 3 << ARIZONA_SYSCLK_FREQ_SHIFT;
                break;
+       case 67737600:
+       case 73728000:
+               val |= 4 << ARIZONA_SYSCLK_FREQ_SHIFT;
+               break;
+       case 90316800:
+       case 98304000:
+               val |= 5 << ARIZONA_SYSCLK_FREQ_SHIFT;
+               break;
+       case 135475200:
+       case 147456000:
+               val |= 6 << ARIZONA_SYSCLK_FREQ_SHIFT;
+               break;
        default:
                return -EINVAL;
        }
@@ -737,6 +774,9 @@ static int arizona_dai_set_sysclk(struct snd_soc_dai *dai,
                return -EBUSY;
        }
 
+       dev_dbg(codec->dev, "Setting AIF%d to %s\n", dai->id + 1,
+               arizona_dai_clk_str(clk_id));
+
        memset(&routes, 0, sizeof(routes));
        routes[0].sink = dai->driver->capture.stream_name;
        routes[1].sink = dai->driver->playback.stream_name;
@@ -749,6 +789,8 @@ static int arizona_dai_set_sysclk(struct snd_soc_dai *dai,
        routes[1].source = arizona_dai_clk_str(clk_id);
        snd_soc_dapm_add_routes(&codec->dapm, routes, ARRAY_SIZE(routes));
 
+       dai_priv->clk = clk_id;
+
        return snd_soc_dapm_sync(&codec->dapm);
 }
 
@@ -925,6 +967,9 @@ int arizona_set_fll(struct arizona_fll *fll, int source,
        bool ena;
        int ret;
 
+       if (fll->fref == Fref && fll->fout == Fout)
+               return 0;
+
        ret = regmap_read(arizona->regmap, fll->base + 1, &reg);
        if (ret != 0) {
                arizona_fll_err(fll, "Failed to read current state: %d\n",
@@ -970,6 +1015,9 @@ int arizona_set_fll(struct arizona_fll *fll, int source,
                if (ena)
                        pm_runtime_put_autosuspend(arizona->dev);
 
+               fll->fref = Fref;
+               fll->fout = Fout;
+
                return 0;
        }
 
@@ -998,10 +1046,13 @@ int arizona_set_fll(struct arizona_fll *fll, int source,
                                   ARIZONA_FLL1_SYNC_ENA);
 
        ret = wait_for_completion_timeout(&fll->ok,
-                                         msecs_to_jiffies(25));
+                                         msecs_to_jiffies(250));
        if (ret == 0)
                arizona_fll_warn(fll, "Timed out waiting for lock\n");
 
+       fll->fref = Fref;
+       fll->fout = Fout;
+
        return 0;
 }
 EXPORT_SYMBOL_GPL(arizona_set_fll);
index 36ec64946120077455ab218c85aef34eaa29ef9a..41dae1ed3b714a4734448b1d3c99938af1fe9d9a 100644 (file)
@@ -17,6 +17,8 @@
 
 #include <sound/soc.h>
 
+#include "wm_adsp.h"
+
 #define ARIZONA_CLK_SYSCLK         1
 #define ARIZONA_CLK_ASYNCCLK       2
 #define ARIZONA_CLK_OPCLK          3
 #define ARIZONA_MIXER_VOL_SHIFT                 1
 #define ARIZONA_MIXER_VOL_WIDTH                 7
 
-#define ARIZONA_MAX_DAI 3
+#define ARIZONA_MAX_DAI  4
+#define ARIZONA_MAX_ADSP 4
 
 struct arizona;
+struct wm_adsp;
 
 struct arizona_dai_priv {
        int clk;
 };
 
 struct arizona_priv {
+       struct wm_adsp adsp[ARIZONA_MAX_ADSP];
        struct arizona *arizona;
        int sysclk;
        int asyncclk;
@@ -89,19 +94,30 @@ extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS];
        const struct snd_kcontrol_new name##_mux =      \
                SOC_DAPM_VALUE_ENUM("Route", name##_enum)
 
+#define ARIZONA_MUX_ENUMS(name, base_reg) \
+       static ARIZONA_MUX_ENUM_DECL(name##_enum, base_reg);      \
+       static ARIZONA_MUX_CTL_DECL(name)
+
 #define ARIZONA_MIXER_ENUMS(name, base_reg) \
-       static ARIZONA_MUX_ENUM_DECL(name##_in1_enum, base_reg);      \
-       static ARIZONA_MUX_ENUM_DECL(name##_in2_enum, base_reg + 2);  \
-       static ARIZONA_MUX_ENUM_DECL(name##_in3_enum, base_reg + 4);  \
-       static ARIZONA_MUX_ENUM_DECL(name##_in4_enum, base_reg + 6);  \
-       static ARIZONA_MUX_CTL_DECL(name##_in1); \
-       static ARIZONA_MUX_CTL_DECL(name##_in2); \
-       static ARIZONA_MUX_CTL_DECL(name##_in3); \
-       static ARIZONA_MUX_CTL_DECL(name##_in4)
+       ARIZONA_MUX_ENUMS(name##_in1, base_reg);     \
+       ARIZONA_MUX_ENUMS(name##_in2, base_reg + 2); \
+       ARIZONA_MUX_ENUMS(name##_in3, base_reg + 4); \
+       ARIZONA_MUX_ENUMS(name##_in4, base_reg + 6)
+
+#define ARIZONA_DSP_AUX_ENUMS(name, base_reg) \
+       ARIZONA_MUX_ENUMS(name##_aux1, base_reg);       \
+       ARIZONA_MUX_ENUMS(name##_aux2, base_reg + 8);   \
+       ARIZONA_MUX_ENUMS(name##_aux3, base_reg + 16);  \
+       ARIZONA_MUX_ENUMS(name##_aux4, base_reg + 24);  \
+       ARIZONA_MUX_ENUMS(name##_aux5, base_reg + 32);  \
+       ARIZONA_MUX_ENUMS(name##_aux6, base_reg + 40)
 
 #define ARIZONA_MUX(name, ctrl) \
        SND_SOC_DAPM_VALUE_MUX(name, SND_SOC_NOPM, 0, 0, ctrl)
 
+#define ARIZONA_MUX_WIDGETS(name, name_str) \
+       ARIZONA_MUX(name_str " Input", &name##_mux)
+
 #define ARIZONA_MIXER_WIDGETS(name, name_str)  \
        ARIZONA_MUX(name_str " Input 1", &name##_in1_mux), \
        ARIZONA_MUX(name_str " Input 2", &name##_in2_mux), \
@@ -109,6 +125,19 @@ extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS];
        ARIZONA_MUX(name_str " Input 4", &name##_in4_mux), \
        SND_SOC_DAPM_MIXER(name_str " Mixer", SND_SOC_NOPM, 0, 0, NULL, 0)
 
+#define ARIZONA_DSP_WIDGETS(name, name_str) \
+       ARIZONA_MIXER_WIDGETS(name##L, name_str "L"), \
+       ARIZONA_MIXER_WIDGETS(name##R, name_str "R"), \
+       ARIZONA_MUX(name_str " Aux 1", &name##_aux1_mux), \
+       ARIZONA_MUX(name_str " Aux 2", &name##_aux2_mux), \
+       ARIZONA_MUX(name_str " Aux 3", &name##_aux3_mux), \
+       ARIZONA_MUX(name_str " Aux 4", &name##_aux4_mux), \
+       ARIZONA_MUX(name_str " Aux 5", &name##_aux5_mux), \
+       ARIZONA_MUX(name_str " Aux 6", &name##_aux6_mux)
+
+#define ARIZONA_MUX_ROUTES(name) \
+       ARIZONA_MIXER_INPUT_ROUTES(name " Input")
+
 #define ARIZONA_MIXER_ROUTES(widget, name) \
        { widget, NULL, name " Mixer" },         \
        { name " Mixer", NULL, name " Input 1" }, \
@@ -120,6 +149,28 @@ extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS];
        ARIZONA_MIXER_INPUT_ROUTES(name " Input 3"), \
        ARIZONA_MIXER_INPUT_ROUTES(name " Input 4")
 
+#define ARIZONA_DSP_ROUTES(name) \
+       { name, NULL, name " Aux 1" }, \
+       { name, NULL, name " Aux 2" }, \
+       { name, NULL, name " Aux 3" }, \
+       { name, NULL, name " Aux 4" }, \
+       { name, NULL, name " Aux 5" }, \
+       { name, NULL, name " Aux 6" }, \
+       ARIZONA_MIXER_INPUT_ROUTES(name " Aux 1"), \
+       ARIZONA_MIXER_INPUT_ROUTES(name " Aux 2"), \
+       ARIZONA_MIXER_INPUT_ROUTES(name " Aux 3"), \
+       ARIZONA_MIXER_INPUT_ROUTES(name " Aux 4"), \
+       ARIZONA_MIXER_INPUT_ROUTES(name " Aux 5"), \
+       ARIZONA_MIXER_INPUT_ROUTES(name " Aux 6"), \
+       ARIZONA_MIXER_ROUTES(name, name "L"), \
+       ARIZONA_MIXER_ROUTES(name, name "R")
+
+extern const struct soc_enum arizona_in_vi_ramp;
+extern const struct soc_enum arizona_in_vd_ramp;
+
+extern const struct soc_enum arizona_out_vi_ramp;
+extern const struct soc_enum arizona_out_vd_ramp;
+
 extern const struct soc_enum arizona_lhpf1_mode;
 extern const struct soc_enum arizona_lhpf2_mode;
 extern const struct soc_enum arizona_lhpf3_mode;
@@ -146,6 +197,8 @@ struct arizona_fll {
        unsigned int vco_mult;
        struct completion lock;
        struct completion ok;
+       unsigned int fref;
+       unsigned int fout;
 
        char lock_name[ARIZONA_FLL_NAME_LEN];
        char clock_ok_name[ARIZONA_FLL_NAME_LEN];
index f994af34f552f4b08c4e01880c3410a4890afb7c..6ad3878db8fcf4663cf948812f6b063a5993acfb 100644 (file)
@@ -474,18 +474,28 @@ static int cs4271_probe(struct snd_soc_codec *codec)
        struct cs4271_platform_data *cs4271plat = codec->dev->platform_data;
        int ret;
        int gpio_nreset = -EINVAL;
+       int amutec_eq_bmutec = 0;
 
 #ifdef CONFIG_OF
-       if (of_match_device(cs4271_dt_ids, codec->dev))
+       if (of_match_device(cs4271_dt_ids, codec->dev)) {
                gpio_nreset = of_get_named_gpio(codec->dev->of_node,
                                                "reset-gpio", 0);
+
+               if (!of_get_property(codec->dev->of_node,
+                                    "cirrus,amutec-eq-bmutec", NULL))
+                       amutec_eq_bmutec = 1;
+       }
 #endif
 
-       if (cs4271plat && gpio_is_valid(cs4271plat->gpio_nreset))
-               gpio_nreset = cs4271plat->gpio_nreset;
+       if (cs4271plat) {
+               if (gpio_is_valid(cs4271plat->gpio_nreset))
+                       gpio_nreset = cs4271plat->gpio_nreset;
+
+               amutec_eq_bmutec = cs4271plat->amutec_eq_bmutec;
+       }
 
        if (gpio_nreset >= 0)
-               if (gpio_request(gpio_nreset, "CS4271 Reset"))
+               if (devm_gpio_request(codec->dev, gpio_nreset, "CS4271 Reset"))
                        gpio_nreset = -EINVAL;
        if (gpio_nreset >= 0) {
                /* Reset codec */
@@ -528,6 +538,11 @@ static int cs4271_probe(struct snd_soc_codec *codec)
        /* Power-up sequence requires 85 uS */
        udelay(85);
 
+       if (amutec_eq_bmutec)
+               snd_soc_update_bits(codec, CS4271_MODE2,
+                                   CS4271_MODE2_MUTECAEQUB,
+                                   CS4271_MODE2_MUTECAEQUB);
+
        return snd_soc_add_codec_controls(codec, cs4271_snd_controls,
                ARRAY_SIZE(cs4271_snd_controls));
 }
@@ -535,15 +550,10 @@ static int cs4271_probe(struct snd_soc_codec *codec)
 static int cs4271_remove(struct snd_soc_codec *codec)
 {
        struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
-       int gpio_nreset;
-
-       gpio_nreset = cs4271->gpio_nreset;
 
-       if (gpio_is_valid(gpio_nreset)) {
+       if (gpio_is_valid(cs4271->gpio_nreset))
                /* Set codec to the reset state */
-               gpio_set_value(gpio_nreset, 0);
-               gpio_free(gpio_nreset);
-       }
+               gpio_set_value(cs4271->gpio_nreset, 0);
 
        return 0;
 };
index 61599298fb26c32bdb193e1be0ccb33d2490a0af..97a81051e88d125c9937057e3b51324a7bb0f9ae 100644 (file)
@@ -763,7 +763,7 @@ static int cs42l52_set_sysclk(struct snd_soc_dai *codec_dai,
        if ((freq >= CS42L52_MIN_CLK) && (freq <= CS42L52_MAX_CLK)) {
                cs42l52->sysclk = freq;
        } else {
-               dev_err(codec->dev, "Invalid freq paramter\n");
+               dev_err(codec->dev, "Invalid freq parameter\n");
                return -EINVAL;
        }
        return 0;
@@ -773,7 +773,6 @@ static int cs42l52_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
 {
        struct snd_soc_codec *codec = codec_dai->codec;
        struct cs42l52_private *cs42l52 = snd_soc_codec_get_drvdata(codec);
-       int ret = 0;
        u8 iface = 0;
 
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
@@ -822,7 +821,7 @@ static int cs42l52_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
        case SND_SOC_DAIFMT_NB_IF:
                break;
        default:
-               ret = -EINVAL;
+               return -EINVAL;
        }
        cs42l52->config.format = iface;
        snd_soc_write(codec, CS42L52_IFACE_CTL1, cs42l52->config.format);
index af5db70805199e81b06e7d48a8e844ae504489b2..843c1eb72faf54aca00be107a74a5a47b2cbf991 100644 (file)
@@ -1231,7 +1231,7 @@ static int __devinit da7210_i2c_probe(struct i2c_client *i2c,
 
        i2c_set_clientdata(i2c, da7210);
 
-       da7210->regmap = regmap_init_i2c(i2c, &da7210_regmap_config_i2c);
+       da7210->regmap = devm_regmap_init_i2c(i2c, &da7210_regmap_config_i2c);
        if (IS_ERR(da7210->regmap)) {
                ret = PTR_ERR(da7210->regmap);
                dev_err(&i2c->dev, "regmap_init() failed: %d\n", ret);
@@ -1245,24 +1245,15 @@ static int __devinit da7210_i2c_probe(struct i2c_client *i2c,
 
        ret =  snd_soc_register_codec(&i2c->dev,
                        &soc_codec_dev_da7210, &da7210_dai, 1);
-       if (ret < 0) {
+       if (ret < 0)
                dev_err(&i2c->dev, "Failed to register codec: %d\n", ret);
-               goto err_regmap;
-       }
-       return ret;
-
-err_regmap:
-       regmap_exit(da7210->regmap);
 
        return ret;
 }
 
 static int __devexit da7210_i2c_remove(struct i2c_client *client)
 {
-       struct da7210_priv *da7210 = i2c_get_clientdata(client);
-
        snd_soc_unregister_codec(&client->dev);
-       regmap_exit(da7210->regmap);
        return 0;
 }
 
@@ -1346,24 +1337,15 @@ static int __devinit da7210_spi_probe(struct spi_device *spi)
        if (ret != 0)
                dev_warn(&spi->dev, "Failed to apply regmap patch: %d\n", ret);
 
-       ret =  snd_soc_register_codec(&spi->dev,
+       ret = snd_soc_register_codec(&spi->dev,
                        &soc_codec_dev_da7210, &da7210_dai, 1);
-       if (ret < 0)
-               goto err_regmap;
-
-       return ret;
-
-err_regmap:
-       regmap_exit(da7210->regmap);
 
        return ret;
 }
 
 static int __devexit da7210_spi_remove(struct spi_device *spi)
 {
-       struct da7210_priv *da7210 = spi_get_drvdata(spi);
        snd_soc_unregister_codec(&spi->dev);
-       regmap_exit(da7210->regmap);
        return 0;
 }
 
index f379b085c39204dfeb2a6fc34d7c07d9f15c9f0b..d3a6de2e757b9f8d0b96fd2ac0f3444f2d017dc5 100644 (file)
 #define DA9055_AIF_FORMAT_I2S_MODE     (0 << 0)
 #define DA9055_AIF_FORMAT_LEFT_J       (1 << 0)
 #define DA9055_AIF_FORMAT_RIGHT_J      (2 << 0)
+#define DA9055_AIF_FORMAT_DSP          (3 << 0)
 #define DA9055_AIF_WORD_S16_LE         (0 << 2)
 #define DA9055_AIF_WORD_S20_3LE                (1 << 2)
 #define DA9055_AIF_WORD_S24_LE         (2 << 2)
@@ -752,6 +753,17 @@ static const struct snd_kcontrol_new da9055_dapm_mixoutr_controls[] = {
                        6, 1, 0),
 };
 
+/* Headphone Output Enable */
+static const struct snd_kcontrol_new da9055_dapm_hp_l_control =
+SOC_DAPM_SINGLE("Switch", DA9055_HP_L_CTRL, 3, 1, 0);
+
+static const struct snd_kcontrol_new da9055_dapm_hp_r_control =
+SOC_DAPM_SINGLE("Switch", DA9055_HP_R_CTRL, 3, 1, 0);
+
+/* Lineout Output Enable */
+static const struct snd_kcontrol_new da9055_dapm_lineout_control =
+SOC_DAPM_SINGLE("Switch", DA9055_LINE_CTRL, 3, 1, 0);
+
 /* DAPM widgets */
 static const struct snd_soc_dapm_widget da9055_dapm_widgets[] = {
        /* Input Side */
@@ -816,6 +828,14 @@ static const struct snd_soc_dapm_widget da9055_dapm_widgets[] = {
                           &da9055_dapm_mixoutr_controls[0],
                           ARRAY_SIZE(da9055_dapm_mixoutr_controls)),
 
+       /* Output Enable Switches */
+       SND_SOC_DAPM_SWITCH("Headphone Left Enable", SND_SOC_NOPM, 0, 0,
+                           &da9055_dapm_hp_l_control),
+       SND_SOC_DAPM_SWITCH("Headphone Right Enable", SND_SOC_NOPM, 0, 0,
+                           &da9055_dapm_hp_r_control),
+       SND_SOC_DAPM_SWITCH("Lineout Enable", SND_SOC_NOPM, 0, 0,
+                           &da9055_dapm_lineout_control),
+
        /* Output PGAs */
        SND_SOC_DAPM_PGA("MIXOUT Left", DA9055_MIXOUT_L_CTRL, 7, 0, NULL, 0),
        SND_SOC_DAPM_PGA("MIXOUT Right", DA9055_MIXOUT_R_CTRL, 7, 0, NULL, 0),
@@ -901,17 +921,20 @@ static const struct snd_soc_dapm_route da9055_audio_map[] = {
        {"Out Mixer Right", "DAC Right Switch", "DAC Right"},
 
        {"MIXOUT Left", NULL, "Out Mixer Left"},
-       {"Headphone Left", NULL, "MIXOUT Left"},
+       {"Headphone Left Enable", "Switch", "MIXOUT Left"},
+       {"Headphone Left", NULL, "Headphone Left Enable"},
        {"Headphone Left", NULL, "Charge Pump"},
        {"HPL", NULL, "Headphone Left"},
 
        {"MIXOUT Right", NULL, "Out Mixer Right"},
-       {"Headphone Right", NULL, "MIXOUT Right"},
+       {"Headphone Right Enable", "Switch", "MIXOUT Right"},
+       {"Headphone Right", NULL, "Headphone Right Enable"},
        {"Headphone Right", NULL, "Charge Pump"},
        {"HPR", NULL, "Headphone Right"},
 
        {"MIXOUT Right", NULL, "Out Mixer Right"},
-       {"Lineout", NULL, "MIXOUT Right"},
+       {"Lineout Enable", "Switch", "MIXOUT Right"},
+       {"Lineout", NULL, "Lineout Enable"},
        {"LINE", NULL, "Lineout"},
 };
 
@@ -1175,6 +1198,9 @@ static int da9055_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
        case SND_SOC_DAIFMT_RIGHT_J:
                aif_ctrl = DA9055_AIF_FORMAT_RIGHT_J;
                break;
+       case SND_SOC_DAIFMT_DSP_A:
+               aif_ctrl = DA9055_AIF_FORMAT_DSP;
+               break;
        default:
                return -EINVAL;
        }
@@ -1390,8 +1416,7 @@ static int da9055_probe(struct snd_soc_codec *codec)
                            DA9055_GAIN_RAMPING_EN, DA9055_GAIN_RAMPING_EN);
 
        /*
-        * There are two separate control bits for input and output mixers as
-        * well as headphone and line outs.
+        * There are two separate control bits for input and output mixers.
         * One to enable corresponding amplifier and other to enable its
         * output. As amplifier bits are related to power control, they are
         * being managed by DAPM while other (non power related) bits are
@@ -1407,14 +1432,6 @@ static int da9055_probe(struct snd_soc_codec *codec)
        snd_soc_update_bits(codec, DA9055_MIXOUT_R_CTRL,
                            DA9055_MIXOUT_R_MIX_EN, DA9055_MIXOUT_R_MIX_EN);
 
-       snd_soc_update_bits(codec, DA9055_HP_L_CTRL,
-                           DA9055_HP_L_AMP_OE, DA9055_HP_L_AMP_OE);
-       snd_soc_update_bits(codec, DA9055_HP_R_CTRL,
-                           DA9055_HP_R_AMP_OE, DA9055_HP_R_AMP_OE);
-
-       snd_soc_update_bits(codec, DA9055_LINE_CTRL,
-                           DA9055_LINE_AMP_OE, DA9055_LINE_AMP_OE);
-
        /* Set this as per your system configuration */
        snd_soc_write(codec, DA9055_PLL_CTRL, DA9055_PLL_INDIV_10_20_MHZ);
 
index eab64a193989ac2917773a4df7613cbf644dd58f..06d4e612a164e45505c664b1b6be455a85d9aaa3 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/pm.h>
+#include <linux/firmware.h>
 #include <linux/gcd.h>
 #include <linux/gpio.h>
 #include <linux/i2c.h>
 #include <sound/wm2200.h>
 
 #include "wm2200.h"
+#include "wmfw.h"
+
+#define WM2200_DSP_CONTROL_1                   0x00
+#define WM2200_DSP_CONTROL_2                   0x02
+#define WM2200_DSP_CONTROL_3                   0x03
+#define WM2200_DSP_CONTROL_4                   0x04
+#define WM2200_DSP_CONTROL_5                   0x06
+#define WM2200_DSP_CONTROL_6                   0x07
+#define WM2200_DSP_CONTROL_7                   0x08
+#define WM2200_DSP_CONTROL_8                   0x09
+#define WM2200_DSP_CONTROL_9                   0x0A
+#define WM2200_DSP_CONTROL_10                  0x0B
+#define WM2200_DSP_CONTROL_11                  0x0C
+#define WM2200_DSP_CONTROL_12                  0x0D
+#define WM2200_DSP_CONTROL_13                  0x0F
+#define WM2200_DSP_CONTROL_14                  0x10
+#define WM2200_DSP_CONTROL_15                  0x11
+#define WM2200_DSP_CONTROL_16                  0x12
+#define WM2200_DSP_CONTROL_17                  0x13
+#define WM2200_DSP_CONTROL_18                  0x14
+#define WM2200_DSP_CONTROL_19                  0x16
+#define WM2200_DSP_CONTROL_20                  0x17
+#define WM2200_DSP_CONTROL_21                  0x18
+#define WM2200_DSP_CONTROL_22                  0x1A
+#define WM2200_DSP_CONTROL_23                  0x1B
+#define WM2200_DSP_CONTROL_24                  0x1C
+#define WM2200_DSP_CONTROL_25                  0x1E
+#define WM2200_DSP_CONTROL_26                  0x20
+#define WM2200_DSP_CONTROL_27                  0x21
+#define WM2200_DSP_CONTROL_28                  0x22
+#define WM2200_DSP_CONTROL_29                  0x23
+#define WM2200_DSP_CONTROL_30                  0x24
+#define WM2200_DSP_CONTROL_31                  0x26
 
 /* The code assumes DCVDD is generated internally */
 #define WM2200_NUM_CORE_SUPPLIES 2
@@ -64,6 +98,66 @@ struct wm2200_priv {
        int sysclk;
 };
 
+#define WM2200_DSP_RANGE_BASE (WM2200_MAX_REGISTER + 1)
+#define WM2200_DSP_SPACING 12288
+
+#define WM2200_DSP1_DM_BASE (WM2200_DSP_RANGE_BASE + (0 * WM2200_DSP_SPACING))
+#define WM2200_DSP1_PM_BASE (WM2200_DSP_RANGE_BASE + (1 * WM2200_DSP_SPACING))
+#define WM2200_DSP1_ZM_BASE (WM2200_DSP_RANGE_BASE + (2 * WM2200_DSP_SPACING))
+#define WM2200_DSP2_DM_BASE (WM2200_DSP_RANGE_BASE + (3 * WM2200_DSP_SPACING))
+#define WM2200_DSP2_PM_BASE (WM2200_DSP_RANGE_BASE + (4 * WM2200_DSP_SPACING))
+#define WM2200_DSP2_ZM_BASE (WM2200_DSP_RANGE_BASE + (5 * WM2200_DSP_SPACING))
+
+static const struct regmap_range_cfg wm2200_ranges[] = {
+       /* DSP1 DM */
+       { .range_min = WM2200_DSP1_DM_BASE,
+         .range_max = WM2200_DSP1_DM_BASE + 12287,
+         .selector_reg = WM2200_DSP1_CONTROL_3,
+         .selector_mask = WM2200_DSP1_PAGE_BASE_DM_0_MASK,
+         .selector_shift = WM2200_DSP1_PAGE_BASE_DM_0_SHIFT,
+         .window_start = WM2200_DSP1_DM_0, .window_len = 2048, },
+
+       /* DSP1 PM */
+       { .range_min = WM2200_DSP1_PM_BASE,
+         .range_max = WM2200_DSP1_PM_BASE + 12287,
+         .selector_reg = WM2200_DSP1_CONTROL_2,
+         .selector_mask = WM2200_DSP1_PAGE_BASE_PM_0_MASK,
+         .selector_shift = WM2200_DSP1_PAGE_BASE_PM_0_SHIFT,
+         .window_start = WM2200_DSP1_PM_0, .window_len = 768, },
+
+       /* DSP1 ZM */
+       { .range_min = WM2200_DSP1_ZM_BASE,
+         .range_max = WM2200_DSP1_ZM_BASE + 2047,
+         .selector_reg = WM2200_DSP1_CONTROL_4,
+         .selector_mask = WM2200_DSP1_PAGE_BASE_ZM_0_MASK,
+         .selector_shift = WM2200_DSP1_PAGE_BASE_ZM_0_SHIFT,
+         .window_start = WM2200_DSP1_ZM_0, .window_len = 1024, },
+
+       /* DSP2 DM */
+       { .range_min = WM2200_DSP2_DM_BASE,
+         .range_max = WM2200_DSP2_DM_BASE + 4095,
+         .selector_reg = WM2200_DSP2_CONTROL_3,
+         .selector_mask = WM2200_DSP2_PAGE_BASE_DM_0_MASK,
+         .selector_shift = WM2200_DSP2_PAGE_BASE_DM_0_SHIFT,
+         .window_start = WM2200_DSP2_DM_0, .window_len = 2048, },
+
+       /* DSP2 PM */
+       { .range_min = WM2200_DSP2_PM_BASE,
+         .range_max = WM2200_DSP2_PM_BASE + 11287,
+         .selector_reg = WM2200_DSP2_CONTROL_2,
+         .selector_mask = WM2200_DSP2_PAGE_BASE_PM_0_MASK,
+         .selector_shift = WM2200_DSP2_PAGE_BASE_PM_0_SHIFT,
+         .window_start = WM2200_DSP2_PM_0, .window_len = 768, },
+
+       /* DSP2 ZM */
+       { .range_min = WM2200_DSP2_ZM_BASE,
+         .range_max = WM2200_DSP2_ZM_BASE + 2047,
+         .selector_reg = WM2200_DSP2_CONTROL_4,
+         .selector_mask = WM2200_DSP2_PAGE_BASE_ZM_0_MASK,
+         .selector_shift = WM2200_DSP2_PAGE_BASE_ZM_0_SHIFT,
+         .window_start = WM2200_DSP2_ZM_0, .window_len = 1024, },
+};
+
 static struct reg_default wm2200_reg_defaults[] = {
        { 0x000B, 0x0000 },   /* R11    - Tone Generator 1 */
        { 0x0102, 0x0000 },   /* R258   - Clocking 3 */
@@ -407,6 +501,16 @@ static struct reg_default wm2200_reg_defaults[] = {
 
 static bool wm2200_volatile_register(struct device *dev, unsigned int reg)
 {
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(wm2200_ranges); i++)
+               if ((reg >= wm2200_ranges[i].window_start &&
+                    reg <= wm2200_ranges[i].window_start +
+                    wm2200_ranges[i].window_len) ||
+                   (reg >= wm2200_ranges[i].range_min &&
+                    reg <= wm2200_ranges[i].range_max))
+                       return true;
+
        switch (reg) {
        case WM2200_SOFTWARE_RESET:
        case WM2200_DEVICE_REVISION:
@@ -423,6 +527,16 @@ static bool wm2200_volatile_register(struct device *dev, unsigned int reg)
 
 static bool wm2200_readable_register(struct device *dev, unsigned int reg)
 {
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(wm2200_ranges); i++)
+               if ((reg >= wm2200_ranges[i].window_start &&
+                    reg <= wm2200_ranges[i].window_start +
+                    wm2200_ranges[i].window_len) ||
+                   (reg >= wm2200_ranges[i].range_min &&
+                    reg <= wm2200_ranges[i].range_max))
+                       return true;
+
        switch (reg) {
        case WM2200_SOFTWARE_RESET:
        case WM2200_DEVICE_REVISION:
@@ -873,6 +987,400 @@ static int wm2200_reset(struct wm2200_priv *wm2200)
        }
 }
 
+static int wm2200_dsp_load(struct snd_soc_codec *codec, int base)
+{
+       const struct firmware *firmware;
+       struct regmap *regmap = codec->control_data;
+       unsigned int pos = 0;
+       const struct wmfw_header *header;
+       const struct wmfw_adsp1_sizes *adsp1_sizes;
+       const struct wmfw_footer *footer;
+       const struct wmfw_region *region;
+       const char *file, *region_name;
+       char *text;
+       unsigned int dm, pm, zm, reg;
+       int regions = 0;
+       int ret, offset, type;
+
+       switch (base) {
+       case WM2200_DSP1_CONTROL_1:
+               file = "wm2200-dsp1.wmfw";
+               dm = WM2200_DSP1_DM_BASE;
+               pm = WM2200_DSP1_PM_BASE;
+               zm = WM2200_DSP1_ZM_BASE;
+               break;
+       case WM2200_DSP2_CONTROL_1:
+               file = "wm2200-dsp2.wmfw";
+               dm = WM2200_DSP2_DM_BASE;
+               pm = WM2200_DSP2_PM_BASE;
+               zm = WM2200_DSP2_ZM_BASE;
+               break;
+       default:
+               dev_err(codec->dev, "BASE %x\n", base);
+               BUG_ON(1);
+               return -EINVAL;
+       }
+
+       ret = request_firmware(&firmware, file, codec->dev);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to request '%s'\n", file);
+               return ret;
+       }
+
+       pos = sizeof(*header) + sizeof(*adsp1_sizes) + sizeof(*footer);
+       if (pos >= firmware->size) {
+               dev_err(codec->dev, "%s: file too short, %d bytes\n",
+                       file, firmware->size);
+               return -EINVAL;
+       }
+
+       header = (void*)&firmware->data[0];
+
+       if (memcmp(&header->magic[0], "WMFW", 4) != 0) {
+               dev_err(codec->dev, "%s: invalid magic\n", file);
+               return -EINVAL;
+       }
+
+       if (header->ver != 0) {
+               dev_err(codec->dev, "%s: unknown file format %d\n",
+                       file, header->ver);
+               return -EINVAL;
+       }
+
+       if (le32_to_cpu(header->len) != sizeof(*header) +
+           sizeof(*adsp1_sizes) + sizeof(*footer)) {
+               dev_err(codec->dev, "%s: unexpected header length %d\n",
+                       file, le32_to_cpu(header->len));
+               return -EINVAL;
+       }
+
+       if (header->core != WMFW_ADSP1) {
+               dev_err(codec->dev, "%s: invalid core %d\n",
+                       file, header->core);
+               return -EINVAL;
+       }
+
+       adsp1_sizes = (void *)&(header[1]);
+       footer = (void *)&(adsp1_sizes[1]);
+
+       dev_dbg(codec->dev, "%s: %d DM, %d PM, %d ZM\n",
+               file, le32_to_cpu(adsp1_sizes->dm),
+               le32_to_cpu(adsp1_sizes->pm), le32_to_cpu(adsp1_sizes->zm));
+
+       dev_dbg(codec->dev, "%s: timestamp %llu\n", file,
+               le64_to_cpu(footer->timestamp));
+
+       while (pos < firmware->size &&
+              pos - firmware->size > sizeof(*region)) {
+               region = (void *)&(firmware->data[pos]);
+               region_name = "Unknown";
+               reg = 0;
+               text = NULL;
+               offset = le32_to_cpu(region->offset) & 0xffffff;
+               type = be32_to_cpu(region->type) & 0xff;
+               
+               switch (type) {
+               case WMFW_NAME_TEXT:
+                       region_name = "Firmware name";
+                       text = kzalloc(le32_to_cpu(region->len) + 1,
+                                      GFP_KERNEL);
+                       break;
+               case WMFW_INFO_TEXT:
+                       region_name = "Information";
+                       text = kzalloc(le32_to_cpu(region->len) + 1,
+                                      GFP_KERNEL);
+                       break;
+               case WMFW_ABSOLUTE:
+                       region_name = "Absolute";
+                       reg = offset;
+                       break;
+               case WMFW_ADSP1_PM:
+                       region_name = "PM";
+                       reg = pm + (offset * 3);
+                       break;
+               case WMFW_ADSP1_DM:
+                       region_name = "DM";
+                       reg = dm + (offset * 2);
+                       break;
+               case WMFW_ADSP1_ZM:
+                       region_name = "ZM";
+                       reg = zm + (offset * 2);
+                       break;
+               default:
+                       dev_warn(codec->dev,
+                                "%s.%d: Unknown region type %x at %d(%x)\n",
+                                file, regions, type, pos, pos);
+                       break;
+               }
+
+               dev_dbg(codec->dev, "%s.%d: %d bytes at %d in %s\n", file,
+                       regions, le32_to_cpu(region->len), offset,
+                       region_name);
+
+               if (text) {
+                       memcpy(text, region->data, le32_to_cpu(region->len));
+                       dev_info(codec->dev, "%s: %s\n", file, text);
+                       kfree(text);
+               }
+
+               if (reg) {
+                       ret = regmap_raw_write(regmap, reg, region->data,
+                                              le32_to_cpu(region->len));
+                       if (ret != 0) {
+                               dev_err(codec->dev,
+                                       "%s.%d: Failed to write %d bytes at %d in %s: %d\n",
+                                       file, regions,
+                                       le32_to_cpu(region->len), offset,
+                                       region_name, ret);
+                               goto out;
+                       }
+               }
+
+               pos += le32_to_cpu(region->len) + sizeof(*region);
+               regions++;
+       }
+
+       if (pos > firmware->size)
+               dev_warn(codec->dev, "%s.%d: %d bytes at end of file\n",
+                        file, regions, pos - firmware->size);
+
+out:
+       release_firmware(firmware);
+       
+       return ret;
+}
+
+static int wm2200_setup_algs(struct snd_soc_codec *codec, int base)
+{
+       struct regmap *regmap = codec->control_data;
+       struct wmfw_adsp1_id_hdr id;
+       struct wmfw_adsp1_alg_hdr *alg;
+       size_t algs;
+       int zm, dm, pm, ret, i;
+       __be32 val;
+
+       switch (base) {
+       case WM2200_DSP1_CONTROL_1:
+               dm = WM2200_DSP1_DM_BASE;
+               pm = WM2200_DSP1_PM_BASE;
+               zm = WM2200_DSP1_ZM_BASE;
+               break;
+       case WM2200_DSP2_CONTROL_1:
+               dm = WM2200_DSP2_DM_BASE;
+               pm = WM2200_DSP2_PM_BASE;
+               zm = WM2200_DSP2_ZM_BASE;
+               break;
+       default:
+               dev_err(codec->dev, "BASE %x\n", base);
+               BUG_ON(1);
+               return -EINVAL;
+       }
+
+       ret = regmap_raw_read(regmap, dm, &id, sizeof(id));
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to read algorithm info: %d\n",
+                       ret);
+               return ret;
+       }
+
+       algs = be32_to_cpu(id.algs);
+       dev_info(codec->dev, "Firmware: %x v%d.%d.%d, %d algorithms\n",
+                be32_to_cpu(id.fw.id),
+                (be32_to_cpu(id.fw.ver) & 0xff000) >> 16,
+                (be32_to_cpu(id.fw.ver) & 0xff00) >> 8,
+                be32_to_cpu(id.fw.ver) & 0xff,
+                algs);
+
+       /* Read the terminator first to validate the length */
+       ret = regmap_raw_read(regmap, dm +
+                             (sizeof(id) + (algs * sizeof(*alg))) / 2,
+                             &val, sizeof(val));
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to read algorithm list end: %d\n",
+                       ret);
+               return ret;
+       }
+
+       if (be32_to_cpu(val) != 0xbedead)
+               dev_warn(codec->dev, "Algorithm list end %x 0x%x != 0xbeadead\n",
+                        (sizeof(id) + (algs * sizeof(*alg))) / 2,
+                        be32_to_cpu(val));
+
+       alg = kzalloc(sizeof(*alg) * algs, GFP_KERNEL);
+       if (!alg)
+               return -ENOMEM;
+
+       ret = regmap_raw_read(regmap, dm + (sizeof(id) / 2),
+                             alg, algs * sizeof(*alg));
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to read algorithm list: %d\n",
+                       ret);
+               goto out;
+       }
+
+       for (i = 0; i < algs; i++) {
+               dev_info(codec->dev, "%d: ID %x v%d.%d.%d\n",
+                        i, be32_to_cpu(alg[i].alg.id),
+                        (be32_to_cpu(alg[i].alg.ver) & 0xff000) >> 16,
+                        (be32_to_cpu(alg[i].alg.ver) & 0xff00) >> 8,
+                        be32_to_cpu(alg[i].alg.ver) & 0xff);
+       }
+
+out:
+       kfree(alg);
+       return ret;
+}
+
+static int wm2200_load_coeff(struct snd_soc_codec *codec, int base)
+{
+       struct regmap *regmap = codec->control_data;
+       struct wmfw_coeff_hdr *hdr;
+       struct wmfw_coeff_item *blk;
+       const struct firmware *firmware;
+       const char *file, *region_name;
+       int ret, dm, pm, zm, pos, blocks, type, offset, reg;
+
+       switch (base) {
+       case WM2200_DSP1_CONTROL_1:
+               file = "wm2200-dsp1.bin";
+               dm = WM2200_DSP1_DM_BASE;
+               pm = WM2200_DSP1_PM_BASE;
+               zm = WM2200_DSP1_ZM_BASE;
+               break;
+       case WM2200_DSP2_CONTROL_1:
+               file = "wm2200-dsp2.bin";
+               dm = WM2200_DSP2_DM_BASE;
+               pm = WM2200_DSP2_PM_BASE;
+               zm = WM2200_DSP2_ZM_BASE;
+               break;
+       default:
+               dev_err(codec->dev, "BASE %x\n", base);
+               BUG_ON(1);
+               return -EINVAL;
+       }
+
+       ret = request_firmware(&firmware, file, codec->dev);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to request '%s'\n", file);
+               return ret;
+       }
+
+       if (sizeof(*hdr) >= firmware->size) {
+               dev_err(codec->dev, "%s: file too short, %d bytes\n",
+                       file, firmware->size);
+               return -EINVAL;
+       }
+
+       hdr = (void*)&firmware->data[0];
+       if (memcmp(hdr->magic, "WMDR", 4) != 0) {
+               dev_err(codec->dev, "%s: invalid magic\n", file);
+               return -EINVAL;
+       }
+
+       dev_dbg(codec->dev, "%s: v%d.%d.%d\n", file,
+               (le32_to_cpu(hdr->ver) >> 16) & 0xff,
+               (le32_to_cpu(hdr->ver) >>  8) & 0xff,
+               le32_to_cpu(hdr->ver) & 0xff);
+
+       pos = le32_to_cpu(hdr->len);
+
+       blocks = 0;
+       while (pos < firmware->size &&
+              pos - firmware->size > sizeof(*blk)) {
+               blk = (void*)(&firmware->data[pos]);
+
+               type = be32_to_cpu(blk->type) & 0xff;
+               offset = le32_to_cpu(blk->offset) & 0xffffff;
+
+               dev_dbg(codec->dev, "%s.%d: %x v%d.%d.%d\n",
+                       file, blocks, le32_to_cpu(blk->id),
+                       (le32_to_cpu(blk->ver) >> 16) & 0xff,
+                       (le32_to_cpu(blk->ver) >>  8) & 0xff,
+                       le32_to_cpu(blk->ver) & 0xff);
+               dev_dbg(codec->dev, "%s.%d: %d bytes at 0x%x in %x\n",
+                       file, blocks, le32_to_cpu(blk->len), offset, type);
+
+               reg = 0;
+               region_name = "Unknown";
+               switch (type) {
+               case WMFW_NAME_TEXT:
+               case WMFW_INFO_TEXT:
+                       break;
+               case WMFW_ABSOLUTE:
+                       region_name = "register";
+                       reg = offset;
+                       break;
+               default:
+                       dev_err(codec->dev, "Unknown region type %x\n", type);
+                       break;
+               }
+
+               if (reg) {
+                       ret = regmap_raw_write(regmap, reg, blk->data,
+                                              le32_to_cpu(blk->len));
+                       if (ret != 0) {
+                               dev_err(codec->dev,
+                                       "%s.%d: Failed to write to %x in %s\n",
+                                       file, blocks, reg, region_name);
+                       }
+               }
+
+               pos += le32_to_cpu(blk->len) + sizeof(*blk);
+               blocks++;
+       }
+
+       if (pos > firmware->size)
+               dev_warn(codec->dev, "%s.%d: %d bytes at end of file\n",
+                        file, blocks, pos - firmware->size);
+
+       return 0;
+}
+
+static int wm2200_dsp_ev(struct snd_soc_dapm_widget *w,
+                        struct snd_kcontrol *kcontrol,
+                        int event)
+{
+       struct snd_soc_codec *codec = w->codec;
+       int base = w->reg - WM2200_DSP_CONTROL_30;
+       int ret;
+
+       switch (event) {
+       case SND_SOC_DAPM_POST_PMU:
+               ret = wm2200_dsp_load(codec, base);
+               if (ret != 0)
+                       return ret;
+
+               ret = wm2200_setup_algs(codec, base);
+               if (ret != 0)
+                       return ret;
+
+               ret = wm2200_load_coeff(codec, base);
+               if (ret != 0)
+                       return ret;
+
+               /* Start the core running */
+               snd_soc_update_bits(codec, w->reg,
+                                   WM2200_DSP1_CORE_ENA | WM2200_DSP1_START,
+                                   WM2200_DSP1_CORE_ENA | WM2200_DSP1_START);
+               break;
+
+       case SND_SOC_DAPM_PRE_PMD:
+               /* Halt the core */
+               snd_soc_update_bits(codec, w->reg,
+                                   WM2200_DSP1_CORE_ENA | WM2200_DSP1_START,
+                                   0);
+
+               snd_soc_update_bits(codec, base + WM2200_DSP_CONTROL_19,
+                                   WM2200_DSP1_WDMA_BUFFER_LENGTH_MASK, 0);
+               break;
+
+       default:
+               break;
+       }
+
+       return 0;
+}
+
 static DECLARE_TLV_DB_SCALE(in_tlv, -6300, 100, 0);
 static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0);
 static DECLARE_TLV_DB_SCALE(out_tlv, -6400, 100, 0);
@@ -880,7 +1388,7 @@ static DECLARE_TLV_DB_SCALE(out_tlv, -6400, 100, 0);
 static const char *wm2200_mixer_texts[] = {
        "None",
        "Tone Generator",
-       "AEC loopback",
+       "AEC Loopback",
        "IN1L",
        "IN1R",
        "IN2L",
@@ -976,6 +1484,20 @@ static int wm2200_mixer_values[] = {
        static WM2200_MUX_CTL_DECL(name##_in3); \
        static WM2200_MUX_CTL_DECL(name##_in4)
 
+#define WM2200_DSP_ENUMS(name, base_reg) \
+       static WM2200_MUX_ENUM_DECL(name##_aux1_enum, base_reg);     \
+       static WM2200_MUX_ENUM_DECL(name##_aux2_enum, base_reg + 1); \
+       static WM2200_MUX_ENUM_DECL(name##_aux3_enum, base_reg + 2); \
+       static WM2200_MUX_ENUM_DECL(name##_aux4_enum, base_reg + 3); \
+       static WM2200_MUX_ENUM_DECL(name##_aux5_enum, base_reg + 4); \
+       static WM2200_MUX_ENUM_DECL(name##_aux6_enum, base_reg + 5); \
+       static WM2200_MUX_CTL_DECL(name##_aux1); \
+       static WM2200_MUX_CTL_DECL(name##_aux2); \
+       static WM2200_MUX_CTL_DECL(name##_aux3); \
+       static WM2200_MUX_CTL_DECL(name##_aux4); \
+       static WM2200_MUX_CTL_DECL(name##_aux5); \
+       static WM2200_MUX_CTL_DECL(name##_aux6);
+
 static const struct snd_kcontrol_new wm2200_snd_controls[] = {
 SOC_SINGLE("IN1 High Performance Switch", WM2200_IN1L_CONTROL,
           WM2200_IN1_OSR_SHIFT, 1, 0),
@@ -1051,6 +1573,9 @@ WM2200_MIXER_ENUMS(DSP1R, WM2200_DSP1RMIX_INPUT_1_SOURCE);
 WM2200_MIXER_ENUMS(DSP2L, WM2200_DSP2LMIX_INPUT_1_SOURCE);
 WM2200_MIXER_ENUMS(DSP2R, WM2200_DSP2RMIX_INPUT_1_SOURCE);
 
+WM2200_DSP_ENUMS(DSP1, WM2200_DSP1AUX1MIX_INPUT_1_SOURCE);
+WM2200_DSP_ENUMS(DSP2, WM2200_DSP2AUX1MIX_INPUT_1_SOURCE);
+
 WM2200_MIXER_ENUMS(LHPF1, WM2200_LHPF1MIX_INPUT_1_SOURCE);
 WM2200_MIXER_ENUMS(LHPF2, WM2200_LHPF2MIX_INPUT_1_SOURCE);
 
@@ -1064,8 +1589,19 @@ WM2200_MIXER_ENUMS(LHPF2, WM2200_LHPF2MIX_INPUT_1_SOURCE);
        WM2200_MUX(name_str " Input 4", &name##_in4_mux), \
        SND_SOC_DAPM_MIXER(name_str " Mixer", SND_SOC_NOPM, 0, 0, NULL, 0)
 
+#define WM2200_DSP_WIDGETS(name, name_str) \
+       WM2200_MIXER_WIDGETS(name##L, name_str "L"), \
+       WM2200_MIXER_WIDGETS(name##R, name_str "R"), \
+       WM2200_MUX(name_str " Aux 1", &name##_aux1_mux), \
+       WM2200_MUX(name_str " Aux 2", &name##_aux2_mux), \
+       WM2200_MUX(name_str " Aux 3", &name##_aux3_mux), \
+       WM2200_MUX(name_str " Aux 4", &name##_aux4_mux), \
+       WM2200_MUX(name_str " Aux 5", &name##_aux5_mux), \
+       WM2200_MUX(name_str " Aux 6", &name##_aux6_mux)
+
 #define WM2200_MIXER_INPUT_ROUTES(name)        \
        { name, "Tone Generator", "Tone Generator" }, \
+       { name, "AEC Loopback", "AEC Loopback" }, \
         { name, "IN1L", "IN1L PGA" }, \
         { name, "IN1R", "IN1R PGA" }, \
         { name, "IN2L", "IN2L PGA" }, \
@@ -1106,6 +1642,33 @@ WM2200_MIXER_ENUMS(LHPF2, WM2200_LHPF2MIX_INPUT_1_SOURCE);
        WM2200_MIXER_INPUT_ROUTES(name " Input 3"), \
        WM2200_MIXER_INPUT_ROUTES(name " Input 4")
 
+#define WM2200_DSP_AUX_ROUTES(name) \
+       { name, NULL, name " Aux 1" }, \
+       { name, NULL, name " Aux 2" }, \
+       { name, NULL, name " Aux 3" }, \
+       { name, NULL, name " Aux 4" }, \
+       { name, NULL, name " Aux 5" }, \
+       { name, NULL, name " Aux 6" }, \
+       WM2200_MIXER_INPUT_ROUTES(name " Aux 1"), \
+       WM2200_MIXER_INPUT_ROUTES(name " Aux 2"), \
+       WM2200_MIXER_INPUT_ROUTES(name " Aux 3"), \
+       WM2200_MIXER_INPUT_ROUTES(name " Aux 4"), \
+       WM2200_MIXER_INPUT_ROUTES(name " Aux 5"), \
+       WM2200_MIXER_INPUT_ROUTES(name " Aux 6")
+
+static const char *wm2200_aec_loopback_texts[] = {
+       "OUT1L", "OUT1R", "OUT2L", "OUT2R",
+};
+
+static const struct soc_enum wm2200_aec_loopback =
+       SOC_ENUM_SINGLE(WM2200_DAC_AEC_CONTROL_1,
+                       WM2200_AEC_LOOPBACK_SRC_SHIFT,
+                       ARRAY_SIZE(wm2200_aec_loopback_texts),
+                       wm2200_aec_loopback_texts);
+
+static const struct snd_kcontrol_new wm2200_aec_loopback_mux =
+       SOC_DAPM_ENUM("AEC Loopback", wm2200_aec_loopback);
+
 static const struct snd_soc_dapm_widget wm2200_dapm_widgets[] = {
 SND_SOC_DAPM_SUPPLY("SYSCLK", WM2200_CLOCKING_3, WM2200_SYSCLK_ENA_SHIFT, 0,
                    NULL, 0),
@@ -1165,8 +1728,12 @@ SND_SOC_DAPM_PGA("LHPF1", WM2200_HPLPF1_1, WM2200_LHPF1_ENA_SHIFT, 0,
 SND_SOC_DAPM_PGA("LHPF2", WM2200_HPLPF2_1, WM2200_LHPF2_ENA_SHIFT, 0,
                 NULL, 0),
 
-SND_SOC_DAPM_PGA_E("DSP1", SND_SOC_NOPM, 0, 0, NULL, 0, NULL, 0),
-SND_SOC_DAPM_PGA_E("DSP2", SND_SOC_NOPM, 1, 0, NULL, 0, NULL, 0),
+SND_SOC_DAPM_PGA_E("DSP1", WM2200_DSP1_CONTROL_30, WM2200_DSP1_SYS_ENA_SHIFT,
+                  0, NULL, 0, wm2200_dsp_ev,
+                  SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+SND_SOC_DAPM_PGA_E("DSP2", WM2200_DSP2_CONTROL_30, WM2200_DSP2_SYS_ENA_SHIFT,
+                  0, NULL, 0, wm2200_dsp_ev,
+                  SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
 
 SND_SOC_DAPM_AIF_OUT("AIF1TX1", "Capture", 0,
                    WM2200_AUDIO_IF_1_22, WM2200_AIF1TX1_ENA_SHIFT, 0),
@@ -1181,6 +1748,9 @@ SND_SOC_DAPM_AIF_OUT("AIF1TX5", "Capture", 4,
 SND_SOC_DAPM_AIF_OUT("AIF1TX6", "Capture", 5,
                    WM2200_AUDIO_IF_1_22, WM2200_AIF1TX6_ENA_SHIFT, 0),
 
+SND_SOC_DAPM_MUX("AEC Loopback", WM2200_DAC_AEC_CONTROL_1,
+                WM2200_AEC_LOOPBACK_ENA_SHIFT, 0, &wm2200_aec_loopback_mux),
+
 SND_SOC_DAPM_PGA_S("OUT1L", 0, WM2200_OUTPUT_ENABLES,
                   WM2200_OUT1L_ENA_SHIFT, 0, NULL, 0),
 SND_SOC_DAPM_PGA_S("OUT1R", 0, WM2200_OUTPUT_ENABLES,
@@ -1231,10 +1801,8 @@ WM2200_MIXER_WIDGETS(EQR, "EQR"),
 WM2200_MIXER_WIDGETS(LHPF1, "LHPF1"),
 WM2200_MIXER_WIDGETS(LHPF2, "LHPF2"),
 
-WM2200_MIXER_WIDGETS(DSP1L, "DSP1L"),
-WM2200_MIXER_WIDGETS(DSP1R, "DSP1R"),
-WM2200_MIXER_WIDGETS(DSP2L, "DSP2L"),
-WM2200_MIXER_WIDGETS(DSP2R, "DSP2R"),
+WM2200_DSP_WIDGETS(DSP1, "DSP1"),
+WM2200_DSP_WIDGETS(DSP2, "DSP2"),
 
 WM2200_MIXER_WIDGETS(AIF1TX1, "AIF1TX1"),
 WM2200_MIXER_WIDGETS(AIF1TX2, "AIF1TX2"),
@@ -1326,11 +1894,19 @@ static const struct snd_soc_dapm_route wm2200_dapm_routes[] = {
        { "SPK", NULL, "OUT2L" },
        { "SPK", NULL, "OUT2R" },
 
+       { "AEC Loopback", "OUT1L", "OUT1L" },
+       { "AEC Loopback", "OUT1R", "OUT1R" },
+       { "AEC Loopback", "OUT2L", "OUT2L" },
+       { "AEC Loopback", "OUT2R", "OUT2R" },
+
        WM2200_MIXER_ROUTES("DSP1", "DSP1L"),
        WM2200_MIXER_ROUTES("DSP1", "DSP1R"),
        WM2200_MIXER_ROUTES("DSP2", "DSP2L"),
        WM2200_MIXER_ROUTES("DSP2", "DSP2R"),
 
+       WM2200_DSP_AUX_ROUTES("DSP1"),
+       WM2200_DSP_AUX_ROUTES("DSP2"),
+
        WM2200_MIXER_ROUTES("OUT1L", "OUT1L"),
        WM2200_MIXER_ROUTES("OUT1R", "OUT1R"),
        WM2200_MIXER_ROUTES("OUT2L", "OUT2L"),
@@ -1968,12 +2544,15 @@ static const struct regmap_config wm2200_regmap = {
        .reg_bits = 16,
        .val_bits = 16,
 
-       .max_register = WM2200_MAX_REGISTER,
+       .max_register = WM2200_MAX_REGISTER + (ARRAY_SIZE(wm2200_ranges) *
+                                              WM2200_DSP_SPACING),
        .reg_defaults = wm2200_reg_defaults,
        .num_reg_defaults = ARRAY_SIZE(wm2200_reg_defaults),
        .volatile_reg = wm2200_volatile_register,
        .readable_reg = wm2200_readable_register,
        .cache_type = REGCACHE_RBTREE,
+       .ranges = wm2200_ranges,
+       .num_ranges = ARRAY_SIZE(wm2200_ranges),
 };
 
 static const unsigned int wm2200_dig_vu[] = {
@@ -2011,7 +2590,7 @@ static __devinit int wm2200_i2c_probe(struct i2c_client *i2c,
        wm2200->dev = &i2c->dev;
        init_completion(&wm2200->fll_lock);
 
-       wm2200->regmap = regmap_init_i2c(i2c, &wm2200_regmap);
+       wm2200->regmap = devm_regmap_init_i2c(i2c, &wm2200_regmap);
        if (IS_ERR(wm2200->regmap)) {
                ret = PTR_ERR(wm2200->regmap);
                dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
@@ -2027,8 +2606,9 @@ static __devinit int wm2200_i2c_probe(struct i2c_client *i2c,
        for (i = 0; i < ARRAY_SIZE(wm2200->core_supplies); i++)
                wm2200->core_supplies[i].supply = wm2200_core_supply_names[i];
 
-       ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm2200->core_supplies),
-                                wm2200->core_supplies);
+       ret = devm_regulator_bulk_get(&i2c->dev,
+                                     ARRAY_SIZE(wm2200->core_supplies),
+                                     wm2200->core_supplies);
        if (ret != 0) {
                dev_err(&i2c->dev, "Failed to request core supplies: %d\n",
                        ret);
@@ -2044,8 +2624,9 @@ static __devinit int wm2200_i2c_probe(struct i2c_client *i2c,
        }
 
        if (wm2200->pdata.ldo_ena) {
-               ret = gpio_request_one(wm2200->pdata.ldo_ena,
-                                      GPIOF_OUT_INIT_HIGH, "WM2200 LDOENA");
+               ret = devm_gpio_request_one(&i2c->dev, wm2200->pdata.ldo_ena,
+                                           GPIOF_OUT_INIT_HIGH,
+                                           "WM2200 LDOENA");
                if (ret < 0) {
                        dev_err(&i2c->dev, "Failed to request LDOENA %d: %d\n",
                                wm2200->pdata.ldo_ena, ret);
@@ -2055,8 +2636,9 @@ static __devinit int wm2200_i2c_probe(struct i2c_client *i2c,
        }
 
        if (wm2200->pdata.reset) {
-               ret = gpio_request_one(wm2200->pdata.reset,
-                                      GPIOF_OUT_INIT_HIGH, "WM2200 /RESET");
+               ret = devm_gpio_request_one(&i2c->dev, wm2200->pdata.reset,
+                                           GPIOF_OUT_INIT_HIGH,
+                                           "WM2200 /RESET");
                if (ret < 0) {
                        dev_err(&i2c->dev, "Failed to request /RESET %d: %d\n",
                                wm2200->pdata.reset, ret);
@@ -2166,23 +2748,16 @@ static __devinit int wm2200_i2c_probe(struct i2c_client *i2c,
 err_pm_runtime:
        pm_runtime_disable(&i2c->dev);
 err_reset:
-       if (wm2200->pdata.reset) {
+       if (wm2200->pdata.reset)
                gpio_set_value_cansleep(wm2200->pdata.reset, 0);
-               gpio_free(wm2200->pdata.reset);
-       }
 err_ldo:
-       if (wm2200->pdata.ldo_ena) {
+       if (wm2200->pdata.ldo_ena)
                gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 0);
-               gpio_free(wm2200->pdata.ldo_ena);
-       }
 err_enable:
        regulator_bulk_disable(ARRAY_SIZE(wm2200->core_supplies),
                               wm2200->core_supplies);
 err_core:
-       regulator_bulk_free(ARRAY_SIZE(wm2200->core_supplies),
-                           wm2200->core_supplies);
 err_regmap:
-       regmap_exit(wm2200->regmap);
 err:
        return ret;
 }
@@ -2194,17 +2769,10 @@ static __devexit int wm2200_i2c_remove(struct i2c_client *i2c)
        snd_soc_unregister_codec(&i2c->dev);
        if (i2c->irq)
                free_irq(i2c->irq, wm2200);
-       if (wm2200->pdata.reset) {
+       if (wm2200->pdata.reset)
                gpio_set_value_cansleep(wm2200->pdata.reset, 0);
-               gpio_free(wm2200->pdata.reset);
-       }
-       if (wm2200->pdata.ldo_ena) {
+       if (wm2200->pdata.ldo_ena)
                gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 0);
-               gpio_free(wm2200->pdata.ldo_ena);
-       }
-       regulator_bulk_free(ARRAY_SIZE(wm2200->core_supplies),
-                           wm2200->core_supplies);
-       regmap_exit(wm2200->regmap);
 
        return 0;
 }
index 1722b586bdba65bde94d9d3cb5cc1ca51cd44aee..27f7e38e7ecac3984a2a454ff7f6bf5a4593a622 100644 (file)
@@ -31,6 +31,7 @@
 
 #include "arizona.h"
 #include "wm5102.h"
+#include "wm_adsp.h"
 
 struct wm5102_priv {
        struct arizona_priv core;
@@ -42,6 +43,563 @@ static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
 static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0);
 static DECLARE_TLV_DB_SCALE(noise_tlv, 0, 600, 0);
 
+static const struct wm_adsp_region wm5102_dsp1_regions[] = {
+       { .type = WMFW_ADSP2_PM, .base = 0x100000 },
+       { .type = WMFW_ADSP2_ZM, .base = 0x180000 },
+       { .type = WMFW_ADSP2_XM, .base = 0x190000 },
+       { .type = WMFW_ADSP2_YM, .base = 0x1a8000 },
+};
+
+static const struct reg_default wm5102_sysclk_reva_patch[] = {
+       { 0x3000, 0x2225 },
+       { 0x3001, 0x3a03 },
+       { 0x3002, 0x0225 },
+       { 0x3003, 0x0801 },
+       { 0x3004, 0x6249 },
+       { 0x3005, 0x0c04 },
+       { 0x3006, 0x0225 },
+       { 0x3007, 0x5901 },
+       { 0x3008, 0xe249 },
+       { 0x3009, 0x030d },
+       { 0x300a, 0x0249 },
+       { 0x300b, 0x2c01 },
+       { 0x300c, 0xe249 },
+       { 0x300d, 0x4342 },
+       { 0x300e, 0xe249 },
+       { 0x300f, 0x73c0 },
+       { 0x3010, 0x4249 },
+       { 0x3011, 0x0c00 },
+       { 0x3012, 0x0225 },
+       { 0x3013, 0x1f01 },
+       { 0x3014, 0x0225 },
+       { 0x3015, 0x1e01 },
+       { 0x3016, 0x0225 },
+       { 0x3017, 0xfa00 },
+       { 0x3018, 0x0000 },
+       { 0x3019, 0xf000 },
+       { 0x301a, 0x0000 },
+       { 0x301b, 0xf000 },
+       { 0x301c, 0x0000 },
+       { 0x301d, 0xf000 },
+       { 0x301e, 0x0000 },
+       { 0x301f, 0xf000 },
+       { 0x3020, 0x0000 },
+       { 0x3021, 0xf000 },
+       { 0x3022, 0x0000 },
+       { 0x3023, 0xf000 },
+       { 0x3024, 0x0000 },
+       { 0x3025, 0xf000 },
+       { 0x3026, 0x0000 },
+       { 0x3027, 0xf000 },
+       { 0x3028, 0x0000 },
+       { 0x3029, 0xf000 },
+       { 0x302a, 0x0000 },
+       { 0x302b, 0xf000 },
+       { 0x302c, 0x0000 },
+       { 0x302d, 0xf000 },
+       { 0x302e, 0x0000 },
+       { 0x302f, 0xf000 },
+       { 0x3030, 0x0225 },
+       { 0x3031, 0x1a01 },
+       { 0x3032, 0x0225 },
+       { 0x3033, 0x1e00 },
+       { 0x3034, 0x0225 },
+       { 0x3035, 0x1f00 },
+       { 0x3036, 0x6225 },
+       { 0x3037, 0xf800 },
+       { 0x3038, 0x0000 },
+       { 0x3039, 0xf000 },
+       { 0x303a, 0x0000 },
+       { 0x303b, 0xf000 },
+       { 0x303c, 0x0000 },
+       { 0x303d, 0xf000 },
+       { 0x303e, 0x0000 },
+       { 0x303f, 0xf000 },
+       { 0x3040, 0x2226 },
+       { 0x3041, 0x3a03 },
+       { 0x3042, 0x0226 },
+       { 0x3043, 0x0801 },
+       { 0x3044, 0x6249 },
+       { 0x3045, 0x0c06 },
+       { 0x3046, 0x0226 },
+       { 0x3047, 0x5901 },
+       { 0x3048, 0xe249 },
+       { 0x3049, 0x030d },
+       { 0x304a, 0x0249 },
+       { 0x304b, 0x2c01 },
+       { 0x304c, 0xe249 },
+       { 0x304d, 0x4342 },
+       { 0x304e, 0xe249 },
+       { 0x304f, 0x73c0 },
+       { 0x3050, 0x4249 },
+       { 0x3051, 0x0c00 },
+       { 0x3052, 0x0226 },
+       { 0x3053, 0x1f01 },
+       { 0x3054, 0x0226 },
+       { 0x3055, 0x1e01 },
+       { 0x3056, 0x0226 },
+       { 0x3057, 0xfa00 },
+       { 0x3058, 0x0000 },
+       { 0x3059, 0xf000 },
+       { 0x305a, 0x0000 },
+       { 0x305b, 0xf000 },
+       { 0x305c, 0x0000 },
+       { 0x305d, 0xf000 },
+       { 0x305e, 0x0000 },
+       { 0x305f, 0xf000 },
+       { 0x3060, 0x0000 },
+       { 0x3061, 0xf000 },
+       { 0x3062, 0x0000 },
+       { 0x3063, 0xf000 },
+       { 0x3064, 0x0000 },
+       { 0x3065, 0xf000 },
+       { 0x3066, 0x0000 },
+       { 0x3067, 0xf000 },
+       { 0x3068, 0x0000 },
+       { 0x3069, 0xf000 },
+       { 0x306a, 0x0000 },
+       { 0x306b, 0xf000 },
+       { 0x306c, 0x0000 },
+       { 0x306d, 0xf000 },
+       { 0x306e, 0x0000 },
+       { 0x306f, 0xf000 },
+       { 0x3070, 0x0226 },
+       { 0x3071, 0x1a01 },
+       { 0x3072, 0x0226 },
+       { 0x3073, 0x1e00 },
+       { 0x3074, 0x0226 },
+       { 0x3075, 0x1f00 },
+       { 0x3076, 0x6226 },
+       { 0x3077, 0xf800 },
+       { 0x3078, 0x0000 },
+       { 0x3079, 0xf000 },
+       { 0x307a, 0x0000 },
+       { 0x307b, 0xf000 },
+       { 0x307c, 0x0000 },
+       { 0x307d, 0xf000 },
+       { 0x307e, 0x0000 },
+       { 0x307f, 0xf000 },
+       { 0x3080, 0x2227 },
+       { 0x3081, 0x3a03 },
+       { 0x3082, 0x0227 },
+       { 0x3083, 0x0801 },
+       { 0x3084, 0x6255 },
+       { 0x3085, 0x0c04 },
+       { 0x3086, 0x0227 },
+       { 0x3087, 0x5901 },
+       { 0x3088, 0xe255 },
+       { 0x3089, 0x030d },
+       { 0x308a, 0x0255 },
+       { 0x308b, 0x2c01 },
+       { 0x308c, 0xe255 },
+       { 0x308d, 0x4342 },
+       { 0x308e, 0xe255 },
+       { 0x308f, 0x73c0 },
+       { 0x3090, 0x4255 },
+       { 0x3091, 0x0c00 },
+       { 0x3092, 0x0227 },
+       { 0x3093, 0x1f01 },
+       { 0x3094, 0x0227 },
+       { 0x3095, 0x1e01 },
+       { 0x3096, 0x0227 },
+       { 0x3097, 0xfa00 },
+       { 0x3098, 0x0000 },
+       { 0x3099, 0xf000 },
+       { 0x309a, 0x0000 },
+       { 0x309b, 0xf000 },
+       { 0x309c, 0x0000 },
+       { 0x309d, 0xf000 },
+       { 0x309e, 0x0000 },
+       { 0x309f, 0xf000 },
+       { 0x30a0, 0x0000 },
+       { 0x30a1, 0xf000 },
+       { 0x30a2, 0x0000 },
+       { 0x30a3, 0xf000 },
+       { 0x30a4, 0x0000 },
+       { 0x30a5, 0xf000 },
+       { 0x30a6, 0x0000 },
+       { 0x30a7, 0xf000 },
+       { 0x30a8, 0x0000 },
+       { 0x30a9, 0xf000 },
+       { 0x30aa, 0x0000 },
+       { 0x30ab, 0xf000 },
+       { 0x30ac, 0x0000 },
+       { 0x30ad, 0xf000 },
+       { 0x30ae, 0x0000 },
+       { 0x30af, 0xf000 },
+       { 0x30b0, 0x0227 },
+       { 0x30b1, 0x1a01 },
+       { 0x30b2, 0x0227 },
+       { 0x30b3, 0x1e00 },
+       { 0x30b4, 0x0227 },
+       { 0x30b5, 0x1f00 },
+       { 0x30b6, 0x6227 },
+       { 0x30b7, 0xf800 },
+       { 0x30b8, 0x0000 },
+       { 0x30b9, 0xf000 },
+       { 0x30ba, 0x0000 },
+       { 0x30bb, 0xf000 },
+       { 0x30bc, 0x0000 },
+       { 0x30bd, 0xf000 },
+       { 0x30be, 0x0000 },
+       { 0x30bf, 0xf000 },
+       { 0x30c0, 0x2228 },
+       { 0x30c1, 0x3a03 },
+       { 0x30c2, 0x0228 },
+       { 0x30c3, 0x0801 },
+       { 0x30c4, 0x6255 },
+       { 0x30c5, 0x0c06 },
+       { 0x30c6, 0x0228 },
+       { 0x30c7, 0x5901 },
+       { 0x30c8, 0xe255 },
+       { 0x30c9, 0x030d },
+       { 0x30ca, 0x0255 },
+       { 0x30cb, 0x2c01 },
+       { 0x30cc, 0xe255 },
+       { 0x30cd, 0x4342 },
+       { 0x30ce, 0xe255 },
+       { 0x30cf, 0x73c0 },
+       { 0x30d0, 0x4255 },
+       { 0x30d1, 0x0c00 },
+       { 0x30d2, 0x0228 },
+       { 0x30d3, 0x1f01 },
+       { 0x30d4, 0x0228 },
+       { 0x30d5, 0x1e01 },
+       { 0x30d6, 0x0228 },
+       { 0x30d7, 0xfa00 },
+       { 0x30d8, 0x0000 },
+       { 0x30d9, 0xf000 },
+       { 0x30da, 0x0000 },
+       { 0x30db, 0xf000 },
+       { 0x30dc, 0x0000 },
+       { 0x30dd, 0xf000 },
+       { 0x30de, 0x0000 },
+       { 0x30df, 0xf000 },
+       { 0x30e0, 0x0000 },
+       { 0x30e1, 0xf000 },
+       { 0x30e2, 0x0000 },
+       { 0x30e3, 0xf000 },
+       { 0x30e4, 0x0000 },
+       { 0x30e5, 0xf000 },
+       { 0x30e6, 0x0000 },
+       { 0x30e7, 0xf000 },
+       { 0x30e8, 0x0000 },
+       { 0x30e9, 0xf000 },
+       { 0x30ea, 0x0000 },
+       { 0x30eb, 0xf000 },
+       { 0x30ec, 0x0000 },
+       { 0x30ed, 0xf000 },
+       { 0x30ee, 0x0000 },
+       { 0x30ef, 0xf000 },
+       { 0x30f0, 0x0228 },
+       { 0x30f1, 0x1a01 },
+       { 0x30f2, 0x0228 },
+       { 0x30f3, 0x1e00 },
+       { 0x30f4, 0x0228 },
+       { 0x30f5, 0x1f00 },
+       { 0x30f6, 0x6228 },
+       { 0x30f7, 0xf800 },
+       { 0x30f8, 0x0000 },
+       { 0x30f9, 0xf000 },
+       { 0x30fa, 0x0000 },
+       { 0x30fb, 0xf000 },
+       { 0x30fc, 0x0000 },
+       { 0x30fd, 0xf000 },
+       { 0x30fe, 0x0000 },
+       { 0x30ff, 0xf000 },
+       { 0x3100, 0x222b },
+       { 0x3101, 0x3a03 },
+       { 0x3102, 0x222b },
+       { 0x3103, 0x5803 },
+       { 0x3104, 0xe26f },
+       { 0x3105, 0x030d },
+       { 0x3106, 0x626f },
+       { 0x3107, 0x2c01 },
+       { 0x3108, 0xe26f },
+       { 0x3109, 0x4342 },
+       { 0x310a, 0xe26f },
+       { 0x310b, 0x73c0 },
+       { 0x310c, 0x026f },
+       { 0x310d, 0x0c00 },
+       { 0x310e, 0x022b },
+       { 0x310f, 0x1f01 },
+       { 0x3110, 0x022b },
+       { 0x3111, 0x1e01 },
+       { 0x3112, 0x022b },
+       { 0x3113, 0xfa00 },
+       { 0x3114, 0x0000 },
+       { 0x3115, 0xf000 },
+       { 0x3116, 0x0000 },
+       { 0x3117, 0xf000 },
+       { 0x3118, 0x0000 },
+       { 0x3119, 0xf000 },
+       { 0x311a, 0x0000 },
+       { 0x311b, 0xf000 },
+       { 0x311c, 0x0000 },
+       { 0x311d, 0xf000 },
+       { 0x311e, 0x0000 },
+       { 0x311f, 0xf000 },
+       { 0x3120, 0x022b },
+       { 0x3121, 0x0a01 },
+       { 0x3122, 0x022b },
+       { 0x3123, 0x1e00 },
+       { 0x3124, 0x022b },
+       { 0x3125, 0x1f00 },
+       { 0x3126, 0x622b },
+       { 0x3127, 0xf800 },
+       { 0x3128, 0x0000 },
+       { 0x3129, 0xf000 },
+       { 0x312a, 0x0000 },
+       { 0x312b, 0xf000 },
+       { 0x312c, 0x0000 },
+       { 0x312d, 0xf000 },
+       { 0x312e, 0x0000 },
+       { 0x312f, 0xf000 },
+       { 0x3130, 0x0000 },
+       { 0x3131, 0xf000 },
+       { 0x3132, 0x0000 },
+       { 0x3133, 0xf000 },
+       { 0x3134, 0x0000 },
+       { 0x3135, 0xf000 },
+       { 0x3136, 0x0000 },
+       { 0x3137, 0xf000 },
+       { 0x3138, 0x0000 },
+       { 0x3139, 0xf000 },
+       { 0x313a, 0x0000 },
+       { 0x313b, 0xf000 },
+       { 0x313c, 0x0000 },
+       { 0x313d, 0xf000 },
+       { 0x313e, 0x0000 },
+       { 0x313f, 0xf000 },
+       { 0x3140, 0x0000 },
+       { 0x3141, 0xf000 },
+       { 0x3142, 0x0000 },
+       { 0x3143, 0xf000 },
+       { 0x3144, 0x0000 },
+       { 0x3145, 0xf000 },
+       { 0x3146, 0x0000 },
+       { 0x3147, 0xf000 },
+       { 0x3148, 0x0000 },
+       { 0x3149, 0xf000 },
+       { 0x314a, 0x0000 },
+       { 0x314b, 0xf000 },
+       { 0x314c, 0x0000 },
+       { 0x314d, 0xf000 },
+       { 0x314e, 0x0000 },
+       { 0x314f, 0xf000 },
+       { 0x3150, 0x0000 },
+       { 0x3151, 0xf000 },
+       { 0x3152, 0x0000 },
+       { 0x3153, 0xf000 },
+       { 0x3154, 0x0000 },
+       { 0x3155, 0xf000 },
+       { 0x3156, 0x0000 },
+       { 0x3157, 0xf000 },
+       { 0x3158, 0x0000 },
+       { 0x3159, 0xf000 },
+       { 0x315a, 0x0000 },
+       { 0x315b, 0xf000 },
+       { 0x315c, 0x0000 },
+       { 0x315d, 0xf000 },
+       { 0x315e, 0x0000 },
+       { 0x315f, 0xf000 },
+       { 0x3160, 0x0000 },
+       { 0x3161, 0xf000 },
+       { 0x3162, 0x0000 },
+       { 0x3163, 0xf000 },
+       { 0x3164, 0x0000 },
+       { 0x3165, 0xf000 },
+       { 0x3166, 0x0000 },
+       { 0x3167, 0xf000 },
+       { 0x3168, 0x0000 },
+       { 0x3169, 0xf000 },
+       { 0x316a, 0x0000 },
+       { 0x316b, 0xf000 },
+       { 0x316c, 0x0000 },
+       { 0x316d, 0xf000 },
+       { 0x316e, 0x0000 },
+       { 0x316f, 0xf000 },
+       { 0x3170, 0x0000 },
+       { 0x3171, 0xf000 },
+       { 0x3172, 0x0000 },
+       { 0x3173, 0xf000 },
+       { 0x3174, 0x0000 },
+       { 0x3175, 0xf000 },
+       { 0x3176, 0x0000 },
+       { 0x3177, 0xf000 },
+       { 0x3178, 0x0000 },
+       { 0x3179, 0xf000 },
+       { 0x317a, 0x0000 },
+       { 0x317b, 0xf000 },
+       { 0x317c, 0x0000 },
+       { 0x317d, 0xf000 },
+       { 0x317e, 0x0000 },
+       { 0x317f, 0xf000 },
+       { 0x3180, 0x2001 },
+       { 0x3181, 0xf101 },
+       { 0x3182, 0x0000 },
+       { 0x3183, 0xf000 },
+       { 0x3184, 0x0000 },
+       { 0x3185, 0xf000 },
+       { 0x3186, 0x0000 },
+       { 0x3187, 0xf000 },
+       { 0x3188, 0x0000 },
+       { 0x3189, 0xf000 },
+       { 0x318a, 0x0000 },
+       { 0x318b, 0xf000 },
+       { 0x318c, 0x0000 },
+       { 0x318d, 0xf000 },
+       { 0x318e, 0x0000 },
+       { 0x318f, 0xf000 },
+       { 0x3190, 0x0000 },
+       { 0x3191, 0xf000 },
+       { 0x3192, 0x0000 },
+       { 0x3193, 0xf000 },
+       { 0x3194, 0x0000 },
+       { 0x3195, 0xf000 },
+       { 0x3196, 0x0000 },
+       { 0x3197, 0xf000 },
+       { 0x3198, 0x0000 },
+       { 0x3199, 0xf000 },
+       { 0x319a, 0x0000 },
+       { 0x319b, 0xf000 },
+       { 0x319c, 0x0000 },
+       { 0x319d, 0xf000 },
+       { 0x319e, 0x0000 },
+       { 0x319f, 0xf000 },
+       { 0x31a0, 0x0000 },
+       { 0x31a1, 0xf000 },
+       { 0x31a2, 0x0000 },
+       { 0x31a3, 0xf000 },
+       { 0x31a4, 0x0000 },
+       { 0x31a5, 0xf000 },
+       { 0x31a6, 0x0000 },
+       { 0x31a7, 0xf000 },
+       { 0x31a8, 0x0000 },
+       { 0x31a9, 0xf000 },
+       { 0x31aa, 0x0000 },
+       { 0x31ab, 0xf000 },
+       { 0x31ac, 0x0000 },
+       { 0x31ad, 0xf000 },
+       { 0x31ae, 0x0000 },
+       { 0x31af, 0xf000 },
+       { 0x31b0, 0x0000 },
+       { 0x31b1, 0xf000 },
+       { 0x31b2, 0x0000 },
+       { 0x31b3, 0xf000 },
+       { 0x31b4, 0x0000 },
+       { 0x31b5, 0xf000 },
+       { 0x31b6, 0x0000 },
+       { 0x31b7, 0xf000 },
+       { 0x31b8, 0x0000 },
+       { 0x31b9, 0xf000 },
+       { 0x31ba, 0x0000 },
+       { 0x31bb, 0xf000 },
+       { 0x31bc, 0x0000 },
+       { 0x31bd, 0xf000 },
+       { 0x31be, 0x0000 },
+       { 0x31bf, 0xf000 },
+       { 0x31c0, 0x0000 },
+       { 0x31c1, 0xf000 },
+       { 0x31c2, 0x0000 },
+       { 0x31c3, 0xf000 },
+       { 0x31c4, 0x0000 },
+       { 0x31c5, 0xf000 },
+       { 0x31c6, 0x0000 },
+       { 0x31c7, 0xf000 },
+       { 0x31c8, 0x0000 },
+       { 0x31c9, 0xf000 },
+       { 0x31ca, 0x0000 },
+       { 0x31cb, 0xf000 },
+       { 0x31cc, 0x0000 },
+       { 0x31cd, 0xf000 },
+       { 0x31ce, 0x0000 },
+       { 0x31cf, 0xf000 },
+       { 0x31d0, 0x0000 },
+       { 0x31d1, 0xf000 },
+       { 0x31d2, 0x0000 },
+       { 0x31d3, 0xf000 },
+       { 0x31d4, 0x0000 },
+       { 0x31d5, 0xf000 },
+       { 0x31d6, 0x0000 },
+       { 0x31d7, 0xf000 },
+       { 0x31d8, 0x0000 },
+       { 0x31d9, 0xf000 },
+       { 0x31da, 0x0000 },
+       { 0x31db, 0xf000 },
+       { 0x31dc, 0x0000 },
+       { 0x31dd, 0xf000 },
+       { 0x31de, 0x0000 },
+       { 0x31df, 0xf000 },
+       { 0x31e0, 0x0000 },
+       { 0x31e1, 0xf000 },
+       { 0x31e2, 0x0000 },
+       { 0x31e3, 0xf000 },
+       { 0x31e4, 0x0000 },
+       { 0x31e5, 0xf000 },
+       { 0x31e6, 0x0000 },
+       { 0x31e7, 0xf000 },
+       { 0x31e8, 0x0000 },
+       { 0x31e9, 0xf000 },
+       { 0x31ea, 0x0000 },
+       { 0x31eb, 0xf000 },
+       { 0x31ec, 0x0000 },
+       { 0x31ed, 0xf000 },
+       { 0x31ee, 0x0000 },
+       { 0x31ef, 0xf000 },
+       { 0x31f0, 0x0000 },
+       { 0x31f1, 0xf000 },
+       { 0x31f2, 0x0000 },
+       { 0x31f3, 0xf000 },
+       { 0x31f4, 0x0000 },
+       { 0x31f5, 0xf000 },
+       { 0x31f6, 0x0000 },
+       { 0x31f7, 0xf000 },
+       { 0x31f8, 0x0000 },
+       { 0x31f9, 0xf000 },
+       { 0x31fa, 0x0000 },
+       { 0x31fb, 0xf000 },
+       { 0x31fc, 0x0000 },
+       { 0x31fd, 0xf000 },
+       { 0x31fe, 0x0000 },
+       { 0x31ff, 0xf000 },
+       { 0x024d, 0xff50 },
+       { 0x0252, 0xff50 },
+       { 0x0259, 0x0112 },
+       { 0x025e, 0x0112 },
+};
+
+static int wm5102_sysclk_ev(struct snd_soc_dapm_widget *w,
+                           struct snd_kcontrol *kcontrol, int event)
+{
+       struct snd_soc_codec *codec = w->codec;
+       struct arizona *arizona = dev_get_drvdata(codec->dev);
+       struct regmap *regmap = codec->control_data;
+       const struct reg_default *patch = NULL;
+       int i, patch_size;
+
+       switch (arizona->rev) {
+       case 0:
+               patch = wm5102_sysclk_reva_patch;
+               patch_size = ARRAY_SIZE(wm5102_sysclk_reva_patch);
+               break;
+       }
+
+       switch (event) {
+       case SND_SOC_DAPM_POST_PMU:
+               if (patch)
+                       for (i = 0; i < patch_size; i++)
+                               regmap_write(regmap, patch[i].reg,
+                                            patch[i].def);
+               break;
+
+       default:
+               break;
+       }
+
+       return 0;
+}
+
 static const struct snd_kcontrol_new wm5102_snd_controls[] = {
 SOC_SINGLE("IN1 High Performance Switch", ARIZONA_IN1L_CONTROL,
           ARIZONA_IN1_OSR_SHIFT, 1, 0),
@@ -77,11 +635,23 @@ SOC_DOUBLE_R_TLV("IN3 Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_3L,
                 ARIZONA_ADC_DIGITAL_VOLUME_3R, ARIZONA_IN3L_DIG_VOL_SHIFT,
                 0xbf, 0, digital_tlv),
 
+SOC_ENUM("Input Ramp Up", arizona_in_vi_ramp),
+SOC_ENUM("Input Ramp Down", arizona_in_vd_ramp),
+
 ARIZONA_MIXER_CONTROLS("EQ1", ARIZONA_EQ1MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE),
 
+SND_SOC_BYTES_MASK("EQ1 Coefficeints", ARIZONA_EQ1_1, 21,
+                  ARIZONA_EQ1_ENA_MASK),
+SND_SOC_BYTES_MASK("EQ2 Coefficeints", ARIZONA_EQ2_1, 21,
+                  ARIZONA_EQ2_ENA_MASK),
+SND_SOC_BYTES_MASK("EQ3 Coefficeints", ARIZONA_EQ3_1, 21,
+                  ARIZONA_EQ3_ENA_MASK),
+SND_SOC_BYTES_MASK("EQ4 Coefficeints", ARIZONA_EQ4_1, 21,
+                  ARIZONA_EQ4_ENA_MASK),
+
 SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT,
               24, 0, eq_tlv),
 SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT,
@@ -137,6 +707,14 @@ ARIZONA_MIXER_CONTROLS("LHPF2", ARIZONA_HPLP2MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("LHPF3", ARIZONA_HPLP3MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("LHPF4", ARIZONA_HPLP4MIX_INPUT_1_SOURCE),
 
+SND_SOC_BYTES("LHPF1 Coefficients", ARIZONA_HPLPF1_2, 1),
+SND_SOC_BYTES("LHPF2 Coefficients", ARIZONA_HPLPF2_2, 1),
+SND_SOC_BYTES("LHPF3 Coefficients", ARIZONA_HPLPF3_2, 1),
+SND_SOC_BYTES("LHPF4 Coefficients", ARIZONA_HPLPF4_2, 1),
+
+ARIZONA_MIXER_CONTROLS("DSP1L", ARIZONA_DSP1LMIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("DSP1R", ARIZONA_DSP1RMIX_INPUT_1_SOURCE),
+
 SOC_ENUM("LHPF1 Mode", arizona_lhpf1_mode),
 SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode),
 SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode),
@@ -158,14 +736,6 @@ ARIZONA_MIXER_CONTROLS("SPKOUTR", ARIZONA_OUT4RMIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("SPKDAT1L", ARIZONA_OUT5LMIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("SPKDAT1R", ARIZONA_OUT5RMIX_INPUT_1_SOURCE),
 
-SOC_SINGLE("HPOUT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_1L,
-          ARIZONA_OUT1_OSR_SHIFT, 1, 0),
-SOC_SINGLE("OUT2 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_2L,
-          ARIZONA_OUT2_OSR_SHIFT, 1, 0),
-SOC_SINGLE("EPOUT High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_3L,
-          ARIZONA_OUT3_OSR_SHIFT, 1, 0),
-SOC_SINGLE("Speaker High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_4L,
-          ARIZONA_OUT4_OSR_SHIFT, 1, 0),
 SOC_SINGLE("SPKDAT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_5L,
           ARIZONA_OUT5_OSR_SHIFT, 1, 0),
 
@@ -195,16 +765,8 @@ SOC_DOUBLE_R_TLV("SPKDAT1 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_5L,
                 ARIZONA_DAC_DIGITAL_VOLUME_5R, ARIZONA_OUT5L_VOL_SHIFT,
                 0xbf, 0, digital_tlv),
 
-SOC_DOUBLE_R_RANGE_TLV("HPOUT1 Volume", ARIZONA_OUTPUT_PATH_CONFIG_1L,
-                      ARIZONA_OUTPUT_PATH_CONFIG_1R,
-                      ARIZONA_OUT1L_PGA_VOL_SHIFT,
-                      0x34, 0x40, 0, ana_tlv),
-SOC_DOUBLE_R_RANGE_TLV("OUT2 Volume", ARIZONA_OUTPUT_PATH_CONFIG_2L,
-                      ARIZONA_OUTPUT_PATH_CONFIG_2R,
-                      ARIZONA_OUT2L_PGA_VOL_SHIFT,
-                      0x34, 0x40, 0, ana_tlv),
-SOC_SINGLE_RANGE_TLV("EPOUT Volume", ARIZONA_OUTPUT_PATH_CONFIG_3L,
-                    ARIZONA_OUT3L_PGA_VOL_SHIFT, 0x34, 0x40, 0, ana_tlv),
+SOC_ENUM("Output Ramp Up", arizona_out_vi_ramp),
+SOC_ENUM("Output Ramp Down", arizona_out_vd_ramp),
 
 SOC_DOUBLE("SPKDAT1 Switch", ARIZONA_PDM_SPK1_CTRL_1, ARIZONA_SPK1L_MUTE_SHIFT,
           ARIZONA_SPK1R_MUTE_SHIFT, 1, 1),
@@ -269,11 +831,15 @@ ARIZONA_MIXER_ENUMS(AIF2TX2, ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE);
 ARIZONA_MIXER_ENUMS(AIF3TX1, ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE);
 ARIZONA_MIXER_ENUMS(AIF3TX2, ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE);
 
-ARIZONA_MIXER_ENUMS(ASRC1L, ARIZONA_ASRC1LMIX_INPUT_1_SOURCE);
-ARIZONA_MIXER_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE);
-ARIZONA_MIXER_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE);
-ARIZONA_MIXER_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ASRC1L, ARIZONA_ASRC1LMIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE);
+
+ARIZONA_MIXER_ENUMS(DSP1L, ARIZONA_DSP1LMIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(DSP1R, ARIZONA_DSP1RMIX_INPUT_1_SOURCE);
 
+ARIZONA_DSP_AUX_ENUMS(DSP1, ARIZONA_DSP1AUX1MIX_INPUT_1_SOURCE);
 
 static const char *wm5102_aec_loopback_texts[] = {
        "HPOUT1L", "HPOUT1R", "HPOUT2L", "HPOUT2R", "EPOUT",
@@ -297,7 +863,7 @@ static const struct snd_kcontrol_new wm5102_aec_loopback_mux =
 
 static const struct snd_soc_dapm_widget wm5102_dapm_widgets[] = {
 SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT,
-                   0, NULL, 0),
+                   0, wm5102_sysclk_ev, SND_SOC_DAPM_POST_PMU),
 SND_SOC_DAPM_SUPPLY("ASYNCCLK", ARIZONA_ASYNC_CLOCK_1,
                    ARIZONA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0),
 SND_SOC_DAPM_SUPPLY("OPCLK", ARIZONA_OUTPUT_SYSTEM_CLOCK,
@@ -314,6 +880,7 @@ SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDR", 0, 0),
 
 SND_SOC_DAPM_SIGGEN("TONE"),
 SND_SOC_DAPM_SIGGEN("NOISE"),
+SND_SOC_DAPM_SIGGEN("HAPTICS"),
 
 SND_SOC_DAPM_INPUT("IN1L"),
 SND_SOC_DAPM_INPUT("IN1R"),
@@ -344,9 +911,9 @@ SND_SOC_DAPM_PGA_E("IN3R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3R_ENA_SHIFT,
 SND_SOC_DAPM_SUPPLY("MICBIAS1", ARIZONA_MIC_BIAS_CTRL_1,
                    ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0),
 SND_SOC_DAPM_SUPPLY("MICBIAS2", ARIZONA_MIC_BIAS_CTRL_2,
-                   ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0),
+                   ARIZONA_MICB2_ENA_SHIFT, 0, NULL, 0),
 SND_SOC_DAPM_SUPPLY("MICBIAS3", ARIZONA_MIC_BIAS_CTRL_3,
-                   ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0),
+                   ARIZONA_MICB3_ENA_SHIFT, 0, NULL, 0),
 
 SND_SOC_DAPM_PGA("Noise Generator", ARIZONA_COMFORT_NOISE_GENERATOR,
                 ARIZONA_NOISE_GEN_ENA_SHIFT, 0, NULL, 0),
@@ -446,6 +1013,8 @@ SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0,
 SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0,
                    ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX2_ENA_SHIFT, 0),
 
+ARIZONA_DSP_WIDGETS(DSP1, "DSP1"),
+
 SND_SOC_DAPM_VALUE_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1,
                       ARIZONA_AEC_LOOPBACK_ENA, 0, &wm5102_aec_loopback_mux),
 
@@ -521,10 +1090,12 @@ ARIZONA_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"),
 ARIZONA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"),
 ARIZONA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"),
 
-ARIZONA_MIXER_WIDGETS(ASRC1L, "ASRC1L"),
-ARIZONA_MIXER_WIDGETS(ASRC1R, "ASRC1R"),
-ARIZONA_MIXER_WIDGETS(ASRC2L, "ASRC2L"),
-ARIZONA_MIXER_WIDGETS(ASRC2R, "ASRC2R"),
+ARIZONA_MUX_WIDGETS(ASRC1L, "ASRC1L"),
+ARIZONA_MUX_WIDGETS(ASRC1R, "ASRC1R"),
+ARIZONA_MUX_WIDGETS(ASRC2L, "ASRC2L"),
+ARIZONA_MUX_WIDGETS(ASRC2R, "ASRC2R"),
+
+WM_ADSP2("DSP1", 0),
 
 SND_SOC_DAPM_OUTPUT("HPOUT1L"),
 SND_SOC_DAPM_OUTPUT("HPOUT1R"),
@@ -544,6 +1115,7 @@ SND_SOC_DAPM_OUTPUT("SPKDAT1R"),
        { name, "Noise Generator", "Noise Generator" }, \
        { name, "Tone Generator 1", "Tone Generator 1" }, \
        { name, "Tone Generator 2", "Tone Generator 2" }, \
+       { name, "Haptics", "HAPTICS" }, \
        { name, "AEC", "AEC Loopback" }, \
        { name, "IN1L", "IN1L PGA" }, \
        { name, "IN1R", "IN1R PGA" }, \
@@ -577,7 +1149,13 @@ SND_SOC_DAPM_OUTPUT("SPKDAT1R"),
        { name, "ASRC1L", "ASRC1L" }, \
        { name, "ASRC1R", "ASRC1R" }, \
        { name, "ASRC2L", "ASRC2L" }, \
-       { name, "ASRC2R", "ASRC2R" }
+       { name, "ASRC2R", "ASRC2R" }, \
+       { name, "DSP1.1", "DSP1" }, \
+       { name, "DSP1.2", "DSP1" }, \
+       { name, "DSP1.3", "DSP1" }, \
+       { name, "DSP1.4", "DSP1" }, \
+       { name, "DSP1.5", "DSP1" }, \
+       { name, "DSP1.6", "DSP1" }
 
 static const struct snd_soc_dapm_route wm5102_dapm_routes[] = {
        { "AIF2 Capture", NULL, "DBVDD2" },
@@ -663,6 +1241,11 @@ static const struct snd_soc_dapm_route wm5102_dapm_routes[] = {
        { "IN3L PGA", NULL, "IN3L" },
        { "IN3R PGA", NULL, "IN3R" },
 
+       { "ASRC1L", NULL, "ASRC1L Input" },
+       { "ASRC1R", NULL, "ASRC1R Input" },
+       { "ASRC2L", NULL, "ASRC2L Input" },
+       { "ASRC2R", NULL, "ASRC2R Input" },
+
        ARIZONA_MIXER_ROUTES("OUT1L", "HPOUT1L"),
        ARIZONA_MIXER_ROUTES("OUT1R", "HPOUT1R"),
        ARIZONA_MIXER_ROUTES("OUT2L", "HPOUT2L"),
@@ -705,10 +1288,12 @@ static const struct snd_soc_dapm_route wm5102_dapm_routes[] = {
        ARIZONA_MIXER_ROUTES("LHPF3", "LHPF3"),
        ARIZONA_MIXER_ROUTES("LHPF4", "LHPF4"),
 
-       ARIZONA_MIXER_ROUTES("ASRC1L", "ASRC1L"),
-       ARIZONA_MIXER_ROUTES("ASRC1R", "ASRC1R"),
-       ARIZONA_MIXER_ROUTES("ASRC2L", "ASRC2L"),
-       ARIZONA_MIXER_ROUTES("ASRC2R", "ASRC2R"),
+       ARIZONA_MUX_ROUTES("ASRC1L"),
+       ARIZONA_MUX_ROUTES("ASRC1R"),
+       ARIZONA_MUX_ROUTES("ASRC2L"),
+       ARIZONA_MUX_ROUTES("ASRC2R"),
+
+       ARIZONA_DSP_ROUTES("DSP1"),
 
        { "AEC Loopback", "HPOUT1L", "OUT1L" },
        { "AEC Loopback", "HPOUT1R", "OUT1R" },
@@ -827,9 +1412,28 @@ static struct snd_soc_dai_driver wm5102_dai[] = {
 static int wm5102_codec_probe(struct snd_soc_codec *codec)
 {
        struct wm5102_priv *priv = snd_soc_codec_get_drvdata(codec);
+       int ret;
 
        codec->control_data = priv->core.arizona->regmap;
-       return snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP);
+
+       ret = snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP);
+       if (ret != 0)
+               return ret;
+
+       snd_soc_dapm_disable_pin(&codec->dapm, "HAPTICS");
+
+       priv->core.arizona->dapm = &codec->dapm;
+
+       return 0;
+}
+
+static int wm5102_codec_remove(struct snd_soc_codec *codec)
+{
+       struct wm5102_priv *priv = snd_soc_codec_get_drvdata(codec);
+
+       priv->core.arizona->dapm = NULL;
+
+       return 0;
 }
 
 #define WM5102_DIG_VU 0x0200
@@ -856,6 +1460,7 @@ static unsigned int wm5102_digital_vu[] = {
 
 static struct snd_soc_codec_driver soc_codec_dev_wm5102 = {
        .probe = wm5102_codec_probe,
+       .remove = wm5102_codec_remove,
 
        .idle_bias_off = true,
 
@@ -874,7 +1479,7 @@ static int __devinit wm5102_probe(struct platform_device *pdev)
 {
        struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
        struct wm5102_priv *wm5102;
-       int i;
+       int i, ret;
 
        wm5102 = devm_kzalloc(&pdev->dev, sizeof(struct wm5102_priv),
                              GFP_KERNEL);
@@ -884,6 +1489,19 @@ static int __devinit wm5102_probe(struct platform_device *pdev)
 
        wm5102->core.arizona = arizona;
 
+       wm5102->core.adsp[0].part = "wm5102";
+       wm5102->core.adsp[0].num = 1;
+       wm5102->core.adsp[0].type = WMFW_ADSP2;
+       wm5102->core.adsp[0].base = ARIZONA_DSP1_CONTROL_1;
+       wm5102->core.adsp[0].dev = arizona->dev;
+       wm5102->core.adsp[0].regmap = arizona->regmap;
+       wm5102->core.adsp[0].mem = wm5102_dsp1_regions;
+       wm5102->core.adsp[0].num_mems = ARRAY_SIZE(wm5102_dsp1_regions);
+
+       ret = wm_adsp2_init(&wm5102->core.adsp[0], true);
+       if (ret != 0)
+               return ret;
+
        for (i = 0; i < ARRAY_SIZE(wm5102->fll); i++)
                wm5102->fll[i].vco_mult = 1;
 
index 9211e4192f710b305ca46420e0be64037a0f6967..c57dc7468300b7d8082dae3fcf266a12d20922a8 100644 (file)
@@ -84,11 +84,23 @@ SOC_DOUBLE_R_TLV("IN4 Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_4L,
                 ARIZONA_ADC_DIGITAL_VOLUME_4R, ARIZONA_IN4L_DIG_VOL_SHIFT,
                 0xbf, 0, digital_tlv),
 
+SOC_ENUM("Input Ramp Up", arizona_in_vi_ramp),
+SOC_ENUM("Input Ramp Down", arizona_in_vd_ramp),
+
 ARIZONA_MIXER_CONTROLS("EQ1", ARIZONA_EQ1MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE),
 
+SND_SOC_BYTES_MASK("EQ1 Coefficeints", ARIZONA_EQ1_1, 21,
+                  ARIZONA_EQ1_ENA_MASK),
+SND_SOC_BYTES_MASK("EQ2 Coefficeints", ARIZONA_EQ2_1, 21,
+                  ARIZONA_EQ2_ENA_MASK),
+SND_SOC_BYTES_MASK("EQ3 Coefficeints", ARIZONA_EQ3_1, 21,
+                  ARIZONA_EQ3_ENA_MASK),
+SND_SOC_BYTES_MASK("EQ4 Coefficeints", ARIZONA_EQ4_1, 21,
+                  ARIZONA_EQ4_ENA_MASK),
+
 SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT,
               24, 0, eq_tlv),
 SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT,
@@ -148,6 +160,11 @@ ARIZONA_MIXER_CONTROLS("LHPF2", ARIZONA_HPLP2MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("LHPF3", ARIZONA_HPLP3MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("LHPF4", ARIZONA_HPLP4MIX_INPUT_1_SOURCE),
 
+SND_SOC_BYTES("LHPF1 Coefficients", ARIZONA_HPLPF1_2, 1),
+SND_SOC_BYTES("LHPF2 Coefficients", ARIZONA_HPLPF2_2, 1),
+SND_SOC_BYTES("LHPF3 Coefficients", ARIZONA_HPLPF3_2, 1),
+SND_SOC_BYTES("LHPF4 Coefficients", ARIZONA_HPLPF4_2, 1),
+
 SOC_ENUM("LHPF1 Mode", arizona_lhpf1_mode),
 SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode),
 SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode),
@@ -243,6 +260,9 @@ SOC_DOUBLE("SPKDAT1 Switch", ARIZONA_PDM_SPK1_CTRL_1, ARIZONA_SPK1L_MUTE_SHIFT,
 SOC_DOUBLE("SPKDAT2 Switch", ARIZONA_PDM_SPK2_CTRL_1, ARIZONA_SPK2L_MUTE_SHIFT,
           ARIZONA_SPK2R_MUTE_SHIFT, 1, 1),
 
+SOC_ENUM("Output Ramp Up", arizona_out_vi_ramp),
+SOC_ENUM("Output Ramp Down", arizona_out_vd_ramp),
+
 ARIZONA_MIXER_CONTROLS("AIF1TX1", ARIZONA_AIF1TX1MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("AIF1TX2", ARIZONA_AIF1TX2MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("AIF1TX3", ARIZONA_AIF1TX3MIX_INPUT_1_SOURCE),
@@ -308,10 +328,10 @@ ARIZONA_MIXER_ENUMS(AIF2TX2, ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE);
 ARIZONA_MIXER_ENUMS(AIF3TX1, ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE);
 ARIZONA_MIXER_ENUMS(AIF3TX2, ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE);
 
-ARIZONA_MIXER_ENUMS(ASRC1L, ARIZONA_ASRC1LMIX_INPUT_1_SOURCE);
-ARIZONA_MIXER_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE);
-ARIZONA_MIXER_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE);
-ARIZONA_MIXER_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ASRC1L, ARIZONA_ASRC1LMIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE);
 
 static const char *wm5110_aec_loopback_texts[] = {
        "HPOUT1L", "HPOUT1R", "HPOUT2L", "HPOUT2R", "HPOUT3L", "HPOUT3R",
@@ -352,6 +372,7 @@ SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDR", 0, 0),
 
 SND_SOC_DAPM_SIGGEN("TONE"),
 SND_SOC_DAPM_SIGGEN("NOISE"),
+SND_SOC_DAPM_SIGGEN("HAPTICS"),
 
 SND_SOC_DAPM_INPUT("IN1L"),
 SND_SOC_DAPM_INPUT("IN1R"),
@@ -585,10 +606,10 @@ ARIZONA_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"),
 ARIZONA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"),
 ARIZONA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"),
 
-ARIZONA_MIXER_WIDGETS(ASRC1L, "ASRC1L"),
-ARIZONA_MIXER_WIDGETS(ASRC1R, "ASRC1R"),
-ARIZONA_MIXER_WIDGETS(ASRC2L, "ASRC2L"),
-ARIZONA_MIXER_WIDGETS(ASRC2R, "ASRC2R"),
+ARIZONA_MUX_WIDGETS(ASRC1L, "ASRC1L"),
+ARIZONA_MUX_WIDGETS(ASRC1R, "ASRC1R"),
+ARIZONA_MUX_WIDGETS(ASRC2L, "ASRC2L"),
+ARIZONA_MUX_WIDGETS(ASRC2R, "ASRC2R"),
 
 SND_SOC_DAPM_OUTPUT("HPOUT1L"),
 SND_SOC_DAPM_OUTPUT("HPOUT1R"),
@@ -610,6 +631,7 @@ SND_SOC_DAPM_OUTPUT("SPKDAT2R"),
        { name, "Noise Generator", "Noise Generator" }, \
        { name, "Tone Generator 1", "Tone Generator 1" }, \
        { name, "Tone Generator 2", "Tone Generator 2" }, \
+       { name, "Haptics", "HAPTICS" }, \
        { name, "AEC", "AEC Loopback" }, \
        { name, "IN1L", "IN1L PGA" }, \
        { name, "IN1R", "IN1R PGA" }, \
@@ -786,10 +808,10 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = {
        ARIZONA_MIXER_ROUTES("LHPF3", "LHPF3"),
        ARIZONA_MIXER_ROUTES("LHPF4", "LHPF4"),
 
-       ARIZONA_MIXER_ROUTES("ASRC1L", "ASRC1L"),
-       ARIZONA_MIXER_ROUTES("ASRC1R", "ASRC1R"),
-       ARIZONA_MIXER_ROUTES("ASRC2L", "ASRC2L"),
-       ARIZONA_MIXER_ROUTES("ASRC2R", "ASRC2R"),
+       ARIZONA_MUX_ROUTES("ASRC1L"),
+       ARIZONA_MUX_ROUTES("ASRC1R"),
+       ARIZONA_MUX_ROUTES("ASRC2L"),
+       ARIZONA_MUX_ROUTES("ASRC2R"),
 
        { "HPOUT1L", NULL, "OUT1L" },
        { "HPOUT1R", NULL, "OUT1R" },
@@ -902,9 +924,29 @@ static struct snd_soc_dai_driver wm5110_dai[] = {
 static int wm5110_codec_probe(struct snd_soc_codec *codec)
 {
        struct wm5110_priv *priv = snd_soc_codec_get_drvdata(codec);
+       int ret;
 
        codec->control_data = priv->core.arizona->regmap;
-       return snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP);
+       priv->core.arizona->dapm = &codec->dapm;
+
+       ret = snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP);
+       if (ret != 0)
+               return ret;
+
+       snd_soc_dapm_disable_pin(&codec->dapm, "HAPTICS");
+
+       priv->core.arizona->dapm = &codec->dapm;
+
+       return 0;
+}
+
+static int wm5110_codec_remove(struct snd_soc_codec *codec)
+{
+       struct wm5110_priv *priv = snd_soc_codec_get_drvdata(codec);
+
+       priv->core.arizona->dapm = NULL;
+
+       return 0;
 }
 
 #define WM5110_DIG_VU 0x0200
@@ -935,6 +977,7 @@ static unsigned int wm5110_digital_vu[] = {
 
 static struct snd_soc_codec_driver soc_codec_dev_wm5110 = {
        .probe = wm5110_codec_probe,
+       .remove = wm5110_codec_remove,
 
        .idle_bias_off = true,
 
index 5421fd9fbcb5d37954e77f88962c31e9d953e2dc..4c0a8e496131c1cc2bf9933605dee7664928520d 100644 (file)
@@ -782,7 +782,7 @@ static int wm8978_hw_params(struct snd_pcm_substream *substream,
                wm8978->mclk_idx = -1;
                f_sel = wm8978->f_mclk;
        } else {
-               if (!wm8978->f_pllout) {
+               if (!wm8978->f_opclk) {
                        /* We only enter here, if OPCLK is not used */
                        int ret = wm8978_configure_pll(codec);
                        if (ret < 0)
index 2b2dadc54dac5cfe729ddc2fd402e748195a6882..b2b2b37131bddc4acfb8fb0e51a9bba220da9907 100644 (file)
@@ -1045,6 +1045,7 @@ static int aif1clk_ev(struct snd_soc_dapm_widget *w,
                      struct snd_kcontrol *kcontrol, int event)
 {
        struct snd_soc_codec *codec = w->codec;
+       struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
        struct wm8994 *control = codec->control_data;
        int mask = WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA;
        int i;
@@ -1063,6 +1064,10 @@ static int aif1clk_ev(struct snd_soc_dapm_widget *w,
 
        switch (event) {
        case SND_SOC_DAPM_PRE_PMU:
+               /* Don't enable timeslot 2 if not in use */
+               if (wm8994->channels[0] <= 2)
+                       mask &= ~(WM8994_AIF1DAC2L_ENA | WM8994_AIF1DAC2R_ENA);
+
                val = snd_soc_read(codec, WM8994_AIF1_CONTROL_1);
                if ((val & WM8994_AIF1ADCL_SRC) &&
                    (val & WM8994_AIF1ADCR_SRC))
@@ -2687,7 +2692,7 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream,
                return -EINVAL;
        }
 
-       bclk_rate = params_rate(params) * 4;
+       bclk_rate = params_rate(params);
        switch (params_format(params)) {
        case SNDRV_PCM_FORMAT_S16_LE:
                bclk_rate *= 16;
@@ -2708,6 +2713,17 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream,
                return -EINVAL;
        }
 
+       wm8994->channels[id] = params_channels(params);
+       switch (params_channels(params)) {
+       case 1:
+       case 2:
+               bclk_rate *= 2;
+               break;
+       default:
+               bclk_rate *= 4;
+               break;
+       }
+
        /* Try to find an appropriate sample rate; look for an exact match. */
        for (i = 0; i < ARRAY_SIZE(srs); i++)
                if (srs[i].rate == params_rate(params))
@@ -3706,7 +3722,7 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data)
        } while (count--);
 
        if (count == 0)
-               dev_warn(codec->dev, "No impedence range reported for jack\n");
+               dev_warn(codec->dev, "No impedance range reported for jack\n");
 
 #ifndef CONFIG_SND_SOC_WM8994_MODULE
        trace_snd_soc_jack_irq(dev_name(codec->dev));
index f142ec198db3dabfcfc5d1e20a51cdfd5e42874b..ccbce5791e95829b5d98ce472ac50d922e6e4703 100644 (file)
@@ -77,6 +77,7 @@ struct wm8994_priv {
        int sysclk_rate[2];
        int mclk[2];
        int aifclk[2];
+       int channels[2];
        struct wm8994_fll_config fll[2], fll_suspend[2];
        struct completion fll_locked[2];
        bool fll_locked_irq;
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
new file mode 100644 (file)
index 0000000..ffc89fa
--- /dev/null
@@ -0,0 +1,699 @@
+/*
+ * wm_adsp.c  --  Wolfson ADSP support
+ *
+ * Copyright 2012 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/jack.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include <linux/mfd/arizona/registers.h>
+
+#include "wm_adsp.h"
+
+#define adsp_crit(_dsp, fmt, ...) \
+       dev_crit(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
+#define adsp_err(_dsp, fmt, ...) \
+       dev_err(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
+#define adsp_warn(_dsp, fmt, ...) \
+       dev_warn(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
+#define adsp_info(_dsp, fmt, ...) \
+       dev_info(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
+#define adsp_dbg(_dsp, fmt, ...) \
+       dev_dbg(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
+
+#define ADSP1_CONTROL_1                   0x00
+#define ADSP1_CONTROL_2                   0x02
+#define ADSP1_CONTROL_3                   0x03
+#define ADSP1_CONTROL_4                   0x04
+#define ADSP1_CONTROL_5                   0x06
+#define ADSP1_CONTROL_6                   0x07
+#define ADSP1_CONTROL_7                   0x08
+#define ADSP1_CONTROL_8                   0x09
+#define ADSP1_CONTROL_9                   0x0A
+#define ADSP1_CONTROL_10                  0x0B
+#define ADSP1_CONTROL_11                  0x0C
+#define ADSP1_CONTROL_12                  0x0D
+#define ADSP1_CONTROL_13                  0x0F
+#define ADSP1_CONTROL_14                  0x10
+#define ADSP1_CONTROL_15                  0x11
+#define ADSP1_CONTROL_16                  0x12
+#define ADSP1_CONTROL_17                  0x13
+#define ADSP1_CONTROL_18                  0x14
+#define ADSP1_CONTROL_19                  0x16
+#define ADSP1_CONTROL_20                  0x17
+#define ADSP1_CONTROL_21                  0x18
+#define ADSP1_CONTROL_22                  0x1A
+#define ADSP1_CONTROL_23                  0x1B
+#define ADSP1_CONTROL_24                  0x1C
+#define ADSP1_CONTROL_25                  0x1E
+#define ADSP1_CONTROL_26                  0x20
+#define ADSP1_CONTROL_27                  0x21
+#define ADSP1_CONTROL_28                  0x22
+#define ADSP1_CONTROL_29                  0x23
+#define ADSP1_CONTROL_30                  0x24
+#define ADSP1_CONTROL_31                  0x26
+
+/*
+ * ADSP1 Control 19
+ */
+#define ADSP1_WDMA_BUFFER_LENGTH_MASK     0x00FF  /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
+#define ADSP1_WDMA_BUFFER_LENGTH_SHIFT         0  /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
+#define ADSP1_WDMA_BUFFER_LENGTH_WIDTH         8  /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
+
+
+/*
+ * ADSP1 Control 30
+ */
+#define ADSP1_DBG_CLK_ENA                 0x0008  /* DSP1_DBG_CLK_ENA */
+#define ADSP1_DBG_CLK_ENA_MASK            0x0008  /* DSP1_DBG_CLK_ENA */
+#define ADSP1_DBG_CLK_ENA_SHIFT                3  /* DSP1_DBG_CLK_ENA */
+#define ADSP1_DBG_CLK_ENA_WIDTH                1  /* DSP1_DBG_CLK_ENA */
+#define ADSP1_SYS_ENA                     0x0004  /* DSP1_SYS_ENA */
+#define ADSP1_SYS_ENA_MASK                0x0004  /* DSP1_SYS_ENA */
+#define ADSP1_SYS_ENA_SHIFT                    2  /* DSP1_SYS_ENA */
+#define ADSP1_SYS_ENA_WIDTH                    1  /* DSP1_SYS_ENA */
+#define ADSP1_CORE_ENA                    0x0002  /* DSP1_CORE_ENA */
+#define ADSP1_CORE_ENA_MASK               0x0002  /* DSP1_CORE_ENA */
+#define ADSP1_CORE_ENA_SHIFT                   1  /* DSP1_CORE_ENA */
+#define ADSP1_CORE_ENA_WIDTH                   1  /* DSP1_CORE_ENA */
+#define ADSP1_START                       0x0001  /* DSP1_START */
+#define ADSP1_START_MASK                  0x0001  /* DSP1_START */
+#define ADSP1_START_SHIFT                      0  /* DSP1_START */
+#define ADSP1_START_WIDTH                      1  /* DSP1_START */
+
+#define ADSP2_CONTROL  0
+#define ADSP2_CLOCKING 1
+#define ADSP2_STATUS1  4
+
+/*
+ * ADSP2 Control
+ */
+
+#define ADSP2_MEM_ENA                     0x0010  /* DSP1_MEM_ENA */
+#define ADSP2_MEM_ENA_MASK                0x0010  /* DSP1_MEM_ENA */
+#define ADSP2_MEM_ENA_SHIFT                    4  /* DSP1_MEM_ENA */
+#define ADSP2_MEM_ENA_WIDTH                    1  /* DSP1_MEM_ENA */
+#define ADSP2_SYS_ENA                     0x0004  /* DSP1_SYS_ENA */
+#define ADSP2_SYS_ENA_MASK                0x0004  /* DSP1_SYS_ENA */
+#define ADSP2_SYS_ENA_SHIFT                    2  /* DSP1_SYS_ENA */
+#define ADSP2_SYS_ENA_WIDTH                    1  /* DSP1_SYS_ENA */
+#define ADSP2_CORE_ENA                    0x0002  /* DSP1_CORE_ENA */
+#define ADSP2_CORE_ENA_MASK               0x0002  /* DSP1_CORE_ENA */
+#define ADSP2_CORE_ENA_SHIFT                   1  /* DSP1_CORE_ENA */
+#define ADSP2_CORE_ENA_WIDTH                   1  /* DSP1_CORE_ENA */
+#define ADSP2_START                       0x0001  /* DSP1_START */
+#define ADSP2_START_MASK                  0x0001  /* DSP1_START */
+#define ADSP2_START_SHIFT                      0  /* DSP1_START */
+#define ADSP2_START_WIDTH                      1  /* DSP1_START */
+
+/*
+ * ADSP2 clocking
+ */
+#define ADSP2_CLK_SEL_MASK                0x0007  /* CLK_SEL_ENA */
+#define ADSP2_CLK_SEL_SHIFT                    0  /* CLK_SEL_ENA */
+#define ADSP2_CLK_SEL_WIDTH                    3  /* CLK_SEL_ENA */
+
+/*
+ * ADSP2 Status 1
+ */
+#define ADSP2_RAM_RDY                     0x0001
+#define ADSP2_RAM_RDY_MASK                0x0001
+#define ADSP2_RAM_RDY_SHIFT                    0
+#define ADSP2_RAM_RDY_WIDTH                    1
+
+
+static struct wm_adsp_region const *wm_adsp_find_region(struct wm_adsp *dsp,
+                                                       int type)
+{
+       int i;
+
+       for (i = 0; i < dsp->num_mems; i++)
+               if (dsp->mem[i].type == type)
+                       return &dsp->mem[i];
+
+       return NULL;
+}
+
+static int wm_adsp_load(struct wm_adsp *dsp)
+{
+       const struct firmware *firmware;
+       struct regmap *regmap = dsp->regmap;
+       unsigned int pos = 0;
+       const struct wmfw_header *header;
+       const struct wmfw_adsp1_sizes *adsp1_sizes;
+       const struct wmfw_adsp2_sizes *adsp2_sizes;
+       const struct wmfw_footer *footer;
+       const struct wmfw_region *region;
+       const struct wm_adsp_region *mem;
+       const char *region_name;
+       char *file, *text;
+       unsigned int reg;
+       int regions = 0;
+       int ret, offset, type, sizes;
+
+       file = kzalloc(PAGE_SIZE, GFP_KERNEL);
+       if (file == NULL)
+               return -ENOMEM;
+
+       snprintf(file, PAGE_SIZE, "%s-dsp%d.wmfw", dsp->part, dsp->num);
+       file[PAGE_SIZE - 1] = '\0';
+
+       ret = request_firmware(&firmware, file, dsp->dev);
+       if (ret != 0) {
+               adsp_err(dsp, "Failed to request '%s'\n", file);
+               goto out;
+       }
+       ret = -EINVAL;
+
+       pos = sizeof(*header) + sizeof(*adsp1_sizes) + sizeof(*footer);
+       if (pos >= firmware->size) {
+               adsp_err(dsp, "%s: file too short, %zu bytes\n",
+                        file, firmware->size);
+               goto out_fw;
+       }
+
+       header = (void*)&firmware->data[0];
+
+       if (memcmp(&header->magic[0], "WMFW", 4) != 0) {
+               adsp_err(dsp, "%s: invalid magic\n", file);
+               goto out_fw;
+       }
+
+       if (header->ver != 0) {
+               adsp_err(dsp, "%s: unknown file format %d\n",
+                        file, header->ver);
+               goto out_fw;
+       }
+
+       if (header->core != dsp->type) {
+               adsp_err(dsp, "%s: invalid core %d != %d\n",
+                        file, header->core, dsp->type);
+               goto out_fw;
+       }
+
+       switch (dsp->type) {
+       case WMFW_ADSP1:
+               pos = sizeof(*header) + sizeof(*adsp1_sizes) + sizeof(*footer);
+               adsp1_sizes = (void *)&(header[1]);
+               footer = (void *)&(adsp1_sizes[1]);
+               sizes = sizeof(*adsp1_sizes);
+
+               adsp_dbg(dsp, "%s: %d DM, %d PM, %d ZM\n",
+                        file, le32_to_cpu(adsp1_sizes->dm),
+                        le32_to_cpu(adsp1_sizes->pm),
+                        le32_to_cpu(adsp1_sizes->zm));
+               break;
+
+       case WMFW_ADSP2:
+               pos = sizeof(*header) + sizeof(*adsp2_sizes) + sizeof(*footer);
+               adsp2_sizes = (void *)&(header[1]);
+               footer = (void *)&(adsp2_sizes[1]);
+               sizes = sizeof(*adsp2_sizes);
+
+               adsp_dbg(dsp, "%s: %d XM, %d YM %d PM, %d ZM\n",
+                        file, le32_to_cpu(adsp2_sizes->xm),
+                        le32_to_cpu(adsp2_sizes->ym),
+                        le32_to_cpu(adsp2_sizes->pm),
+                        le32_to_cpu(adsp2_sizes->zm));
+               break;
+
+       default:
+               BUG_ON(NULL == "Unknown DSP type");
+               goto out_fw;
+       }
+
+       if (le32_to_cpu(header->len) != sizeof(*header) +
+           sizes + sizeof(*footer)) {
+               adsp_err(dsp, "%s: unexpected header length %d\n",
+                        file, le32_to_cpu(header->len));
+               goto out_fw;
+       }
+
+       adsp_dbg(dsp, "%s: timestamp %llu\n", file,
+                le64_to_cpu(footer->timestamp));
+
+       while (pos < firmware->size &&
+              pos - firmware->size > sizeof(*region)) {
+               region = (void *)&(firmware->data[pos]);
+               region_name = "Unknown";
+               reg = 0;
+               text = NULL;
+               offset = le32_to_cpu(region->offset) & 0xffffff;
+               type = be32_to_cpu(region->type) & 0xff;
+               mem = wm_adsp_find_region(dsp, type);
+               
+               switch (type) {
+               case WMFW_NAME_TEXT:
+                       region_name = "Firmware name";
+                       text = kzalloc(le32_to_cpu(region->len) + 1,
+                                      GFP_KERNEL);
+                       break;
+               case WMFW_INFO_TEXT:
+                       region_name = "Information";
+                       text = kzalloc(le32_to_cpu(region->len) + 1,
+                                      GFP_KERNEL);
+                       break;
+               case WMFW_ABSOLUTE:
+                       region_name = "Absolute";
+                       reg = offset;
+                       break;
+               case WMFW_ADSP1_PM:
+                       BUG_ON(!mem);
+                       region_name = "PM";
+                       reg = mem->base + (offset * 3);
+                       break;
+               case WMFW_ADSP1_DM:
+                       BUG_ON(!mem);
+                       region_name = "DM";
+                       reg = mem->base + (offset * 2);
+                       break;
+               case WMFW_ADSP2_XM:
+                       BUG_ON(!mem);
+                       region_name = "XM";
+                       reg = mem->base + (offset * 2);
+                       break;
+               case WMFW_ADSP2_YM:
+                       BUG_ON(!mem);
+                       region_name = "YM";
+                       reg = mem->base + (offset * 2);
+                       break;
+               case WMFW_ADSP1_ZM:
+                       BUG_ON(!mem);
+                       region_name = "ZM";
+                       reg = mem->base + (offset * 2);
+                       break;
+               default:
+                       adsp_warn(dsp,
+                                 "%s.%d: Unknown region type %x at %d(%x)\n",
+                                 file, regions, type, pos, pos);
+                       break;
+               }
+
+               adsp_dbg(dsp, "%s.%d: %d bytes at %d in %s\n", file,
+                        regions, le32_to_cpu(region->len), offset,
+                        region_name);
+
+               if (text) {
+                       memcpy(text, region->data, le32_to_cpu(region->len));
+                       adsp_info(dsp, "%s: %s\n", file, text);
+                       kfree(text);
+               }
+
+               if (reg) {
+                       ret = regmap_raw_write(regmap, reg, region->data,
+                                              le32_to_cpu(region->len));
+                       if (ret != 0) {
+                               adsp_err(dsp,
+                                       "%s.%d: Failed to write %d bytes at %d in %s: %d\n",
+                                       file, regions,
+                                       le32_to_cpu(region->len), offset,
+                                       region_name, ret);
+                               goto out_fw;
+                       }
+               }
+
+               pos += le32_to_cpu(region->len) + sizeof(*region);
+               regions++;
+       }
+       
+       if (pos > firmware->size)
+               adsp_warn(dsp, "%s.%d: %zu bytes at end of file\n",
+                         file, regions, pos - firmware->size);
+
+out_fw:
+       release_firmware(firmware);
+out:
+       kfree(file);
+
+       return ret;
+}
+
+static int wm_adsp_load_coeff(struct wm_adsp *dsp)
+{
+       struct regmap *regmap = dsp->regmap;
+       struct wmfw_coeff_hdr *hdr;
+       struct wmfw_coeff_item *blk;
+       const struct firmware *firmware;
+       const char *region_name;
+       int ret, pos, blocks, type, offset, reg;
+       char *file;
+
+       file = kzalloc(PAGE_SIZE, GFP_KERNEL);
+       if (file == NULL)
+               return -ENOMEM;
+
+       snprintf(file, PAGE_SIZE, "%s-dsp%d.bin", dsp->part, dsp->num);
+       file[PAGE_SIZE - 1] = '\0';
+
+       ret = request_firmware(&firmware, file, dsp->dev);
+       if (ret != 0) {
+               adsp_warn(dsp, "Failed to request '%s'\n", file);
+               ret = 0;
+               goto out;
+       }
+       ret = -EINVAL;
+
+       if (sizeof(*hdr) >= firmware->size) {
+               adsp_err(dsp, "%s: file too short, %zu bytes\n",
+                       file, firmware->size);
+               goto out_fw;
+       }
+
+       hdr = (void*)&firmware->data[0];
+       if (memcmp(hdr->magic, "WMDR", 4) != 0) {
+               adsp_err(dsp, "%s: invalid magic\n", file);
+               return -EINVAL;
+       }
+
+       adsp_dbg(dsp, "%s: v%d.%d.%d\n", file,
+               (le32_to_cpu(hdr->ver) >> 16) & 0xff,
+               (le32_to_cpu(hdr->ver) >>  8) & 0xff,
+               le32_to_cpu(hdr->ver) & 0xff);
+
+       pos = le32_to_cpu(hdr->len);
+
+       blocks = 0;
+       while (pos < firmware->size &&
+              pos - firmware->size > sizeof(*blk)) {
+               blk = (void*)(&firmware->data[pos]);
+
+               type = be32_to_cpu(blk->type) & 0xff;
+               offset = le32_to_cpu(blk->offset) & 0xffffff;
+
+               adsp_dbg(dsp, "%s.%d: %x v%d.%d.%d\n",
+                        file, blocks, le32_to_cpu(blk->id),
+                        (le32_to_cpu(blk->ver) >> 16) & 0xff,
+                        (le32_to_cpu(blk->ver) >>  8) & 0xff,
+                        le32_to_cpu(blk->ver) & 0xff);
+               adsp_dbg(dsp, "%s.%d: %d bytes at 0x%x in %x\n",
+                        file, blocks, le32_to_cpu(blk->len), offset, type);
+
+               reg = 0;
+               region_name = "Unknown";
+               switch (type) {
+               case WMFW_NAME_TEXT:
+               case WMFW_INFO_TEXT:
+                       break;
+               case WMFW_ABSOLUTE:
+                       region_name = "register";
+                       reg = offset;
+                       break;
+               default:
+                       adsp_err(dsp, "Unknown region type %x\n", type);
+                       break;
+               }
+
+               if (reg) {
+                       ret = regmap_raw_write(regmap, reg, blk->data,
+                                              le32_to_cpu(blk->len));
+                       if (ret != 0) {
+                               adsp_err(dsp,
+                                       "%s.%d: Failed to write to %x in %s\n",
+                                       file, blocks, reg, region_name);
+                       }
+               }
+
+               pos += le32_to_cpu(blk->len) + sizeof(*blk);
+               blocks++;
+       }
+
+       if (pos > firmware->size)
+               adsp_warn(dsp, "%s.%d: %zu bytes at end of file\n",
+                         file, blocks, pos - firmware->size);
+
+out_fw:
+       release_firmware(firmware);
+out:
+       kfree(file);
+       return 0;
+}
+
+int wm_adsp1_event(struct snd_soc_dapm_widget *w,
+                  struct snd_kcontrol *kcontrol,
+                  int event)
+{
+       struct snd_soc_codec *codec = w->codec;
+       struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec);
+       struct wm_adsp *dsp = &dsps[w->shift];
+       int ret;
+
+       switch (event) {
+       case SND_SOC_DAPM_POST_PMU:
+               regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
+                                  ADSP1_SYS_ENA, ADSP1_SYS_ENA);
+
+               ret = wm_adsp_load(dsp);
+               if (ret != 0)
+                       goto err;
+
+               ret = wm_adsp_load_coeff(dsp);
+               if (ret != 0)
+                       goto err;
+
+               /* Start the core running */
+               regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
+                                  ADSP1_CORE_ENA | ADSP1_START,
+                                  ADSP1_CORE_ENA | ADSP1_START);
+               break;
+
+       case SND_SOC_DAPM_PRE_PMD:
+               /* Halt the core */
+               regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
+                                  ADSP1_CORE_ENA | ADSP1_START, 0);
+
+               regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_19,
+                                  ADSP1_WDMA_BUFFER_LENGTH_MASK, 0);
+
+               regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
+                                  ADSP1_SYS_ENA, 0);
+               break;
+
+       default:
+               break;
+       }
+
+       return 0;
+
+err:
+       regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
+                          ADSP1_SYS_ENA, 0);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(wm_adsp1_event);
+
+static int wm_adsp2_ena(struct wm_adsp *dsp)
+{
+       unsigned int val;
+       int ret, count;
+
+       ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
+                                ADSP2_SYS_ENA, ADSP2_SYS_ENA);
+       if (ret != 0)
+               return ret;
+
+       /* Wait for the RAM to start, should be near instantaneous */
+       count = 0;
+       do {
+               ret = regmap_read(dsp->regmap, dsp->base + ADSP2_STATUS1,
+                                 &val);
+               if (ret != 0)
+                       return ret;
+       } while (!(val & ADSP2_RAM_RDY) && ++count < 10);
+
+       if (!(val & ADSP2_RAM_RDY)) {
+               adsp_err(dsp, "Failed to start DSP RAM\n");
+               return -EBUSY;
+       }
+
+       adsp_dbg(dsp, "RAM ready after %d polls\n", count);
+       adsp_info(dsp, "RAM ready after %d polls\n", count);
+
+       return 0;
+}
+
+int wm_adsp2_event(struct snd_soc_dapm_widget *w,
+                  struct snd_kcontrol *kcontrol, int event)
+{
+       struct snd_soc_codec *codec = w->codec;
+       struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec);
+       struct wm_adsp *dsp = &dsps[w->shift];
+       unsigned int val;
+       int ret;
+
+       switch (event) {
+       case SND_SOC_DAPM_POST_PMU:
+               /*
+                * For simplicity set the DSP clock rate to be the
+                * SYSCLK rate rather than making it configurable.
+                */
+               ret = regmap_read(dsp->regmap, ARIZONA_SYSTEM_CLOCK_1, &val);
+               if (ret != 0) {
+                       adsp_err(dsp, "Failed to read SYSCLK state: %d\n",
+                                ret);
+                       return ret;
+               }
+               val = (val & ARIZONA_SYSCLK_FREQ_MASK)
+                       >> ARIZONA_SYSCLK_FREQ_SHIFT;
+
+               ret = regmap_update_bits(dsp->regmap,
+                                        dsp->base + ADSP2_CLOCKING,
+                                        ADSP2_CLK_SEL_MASK, val);
+               if (ret != 0) {
+                       adsp_err(dsp, "Failed to set clock rate: %d\n",
+                                ret);
+                       return ret;
+               }
+
+               if (dsp->dvfs) {
+                       ret = regmap_read(dsp->regmap,
+                                         dsp->base + ADSP2_CLOCKING, &val);
+                       if (ret != 0) {
+                               dev_err(dsp->dev,
+                                       "Failed to read clocking: %d\n", ret);
+                               return ret;
+                       }
+
+                       if ((val & ADSP2_CLK_SEL_MASK) >= 3) {
+                               ret = regulator_enable(dsp->dvfs);
+                               if (ret != 0) {
+                                       dev_err(dsp->dev,
+                                               "Failed to enable supply: %d\n",
+                                               ret);
+                                       return ret;
+                               }
+
+                               ret = regulator_set_voltage(dsp->dvfs,
+                                                           1800000,
+                                                           1800000);
+                               if (ret != 0) {
+                                       dev_err(dsp->dev,
+                                               "Failed to raise supply: %d\n",
+                                               ret);
+                                       return ret;
+                               }
+                       }
+               }
+
+               ret = wm_adsp2_ena(dsp);
+               if (ret != 0)
+                       return ret;
+
+               ret = wm_adsp_load(dsp);
+               if (ret != 0)
+                       goto err;
+
+               ret = wm_adsp_load_coeff(dsp);
+               if (ret != 0)
+                       goto err;
+
+               ret = regmap_update_bits(dsp->regmap,
+                                        dsp->base + ADSP2_CONTROL,
+                                        ADSP2_CORE_ENA | ADSP2_START,
+                                        ADSP2_CORE_ENA | ADSP2_START);
+               if (ret != 0)
+                       goto err;
+               break;
+
+       case SND_SOC_DAPM_PRE_PMD:
+               regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
+                                  ADSP2_SYS_ENA | ADSP2_CORE_ENA |
+                                  ADSP2_START, 0);
+
+               if (dsp->dvfs) {
+                       ret = regulator_set_voltage(dsp->dvfs, 1200000,
+                                                   1800000);
+                       if (ret != 0)
+                               dev_warn(dsp->dev,
+                                        "Failed to lower supply: %d\n",
+                                        ret);
+
+                       ret = regulator_disable(dsp->dvfs);
+                       if (ret != 0)
+                               dev_err(dsp->dev,
+                                       "Failed to enable supply: %d\n",
+                                       ret);
+               }
+               break;
+
+       default:
+               break;
+       }
+
+       return 0;
+err:
+       regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
+                          ADSP2_SYS_ENA | ADSP2_CORE_ENA | ADSP2_START, 0);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(wm_adsp2_event);
+
+int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs)
+{
+       int ret;
+
+       /*
+        * Disable the DSP memory by default when in reset for a small
+        * power saving.
+        */
+       ret = regmap_update_bits(adsp->regmap, adsp->base + ADSP2_CONTROL,
+                                ADSP2_MEM_ENA, 0);
+       if (ret != 0) {
+               adsp_err(adsp, "Failed to clear memory retention: %d\n", ret);
+               return ret;
+       }
+
+       if (dvfs) {
+               adsp->dvfs = devm_regulator_get(adsp->dev, "DCVDD");
+               if (IS_ERR(adsp->dvfs)) {
+                       ret = PTR_ERR(adsp->dvfs);
+                       dev_err(adsp->dev, "Failed to get DCVDD: %d\n", ret);
+                       return ret;
+               }
+
+               ret = regulator_enable(adsp->dvfs);
+               if (ret != 0) {
+                       dev_err(adsp->dev, "Failed to enable DCVDD: %d\n",
+                               ret);
+                       return ret;
+               }
+
+               ret = regulator_set_voltage(adsp->dvfs, 1200000, 1800000);
+               if (ret != 0) {
+                       dev_err(adsp->dev, "Failed to initialise DVFS: %d\n",
+                               ret);
+                       return ret;
+               }
+
+               ret = regulator_disable(adsp->dvfs);
+               if (ret != 0) {
+                       dev_err(adsp->dev, "Failed to disable DCVDD: %d\n",
+                               ret);
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(wm_adsp2_init);
diff --git a/sound/soc/codecs/wm_adsp.h b/sound/soc/codecs/wm_adsp.h
new file mode 100644 (file)
index 0000000..ffd29a4
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * wm_adsp.h  --  Wolfson ADSP support
+ *
+ * Copyright 2012 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __WM_ADSP_H
+#define __WM_ADSP_H
+
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include "wmfw.h"
+
+struct regulator;
+
+struct wm_adsp_region {
+       int type;
+       unsigned int base;
+};
+
+struct wm_adsp {
+       const char *part;
+       int num;
+       int type;
+       struct device *dev;
+       struct regmap *regmap;
+
+       int base;
+
+       const struct wm_adsp_region *mem;
+       int num_mems;
+
+       struct regulator *dvfs;
+};
+
+#define WM_ADSP1(wname, num) \
+       { .id = snd_soc_dapm_pga, .name = wname, .reg = SND_SOC_NOPM, \
+       .shift = num, .event = wm_adsp1_event, \
+       .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD }
+
+#define WM_ADSP2(wname, num) \
+{      .id = snd_soc_dapm_pga, .name = wname, .reg = SND_SOC_NOPM, \
+       .shift = num, .event = wm_adsp2_event, \
+       .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD }
+
+int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs);
+int wm_adsp1_event(struct snd_soc_dapm_widget *w,
+                  struct snd_kcontrol *kcontrol, int event);
+int wm_adsp2_event(struct snd_soc_dapm_widget *w,
+                  struct snd_kcontrol *kcontrol, int event);
+
+#endif
diff --git a/sound/soc/codecs/wmfw.h b/sound/soc/codecs/wmfw.h
new file mode 100644 (file)
index 0000000..5632ded
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * wmfw.h - Wolfson firmware format information
+ *
+ * Copyright 2012 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __WMFW_H
+#define __WMFW_H
+
+#include <linux/types.h>
+
+struct wmfw_header {
+       char magic[4];
+       __le32 len;
+       __le16 rev;
+       u8 core;
+       u8 ver;
+} __packed;
+
+struct wmfw_footer {
+       __le64 timestamp;
+       __le32 checksum;
+} __packed;
+
+struct wmfw_adsp1_sizes {
+       __le32 dm;
+       __le32 pm;
+       __le32 zm;
+} __packed;
+
+struct wmfw_adsp2_sizes {
+       __le32 xm;
+       __le32 ym;
+       __le32 pm;
+       __le32 zm;
+} __packed;
+
+struct wmfw_region {
+       union {
+               __be32 type;
+               __le32 offset;
+       };
+       __le32 len;
+       u8 data[];
+} __packed;
+
+struct wmfw_id_hdr {
+       __be32 core_id;
+       __be32 core_rev;
+       __be32 id;
+       __be32 ver;
+} __packed;
+
+struct wmfw_adsp1_id_hdr {
+       struct wmfw_id_hdr fw;
+       __be32 zm;
+       __be32 dm;
+       __be32 algs;
+} __packed;
+
+struct wmfw_adsp2_id_hdr {
+       struct wmfw_id_hdr fw;
+       __be32 zm;
+       __be32 xm;
+       __be32 ym;
+       __be32 algs;
+} __packed;
+
+struct wmfw_alg_hdr {
+       __be32 id;
+       __be32 ver;
+} __packed;
+
+struct wmfw_adsp1_alg_hdr {
+       struct wmfw_alg_hdr alg;
+       __be32 zm;
+       __be32 dm;
+} __packed;
+
+struct wmfw_adsp2_alg_hdr {
+       struct wmfw_alg_hdr alg;
+       __be32 zm;
+       __be32 xm;
+       __be32 ym;
+} __packed;
+
+struct wmfw_coeff_hdr {
+       u8 magic[4];
+       __le32 len;
+       __le32 ver;
+       u8 data[];
+} __packed;
+
+struct wmfw_coeff_item {
+       union {
+               __be32 type;
+               __le32 offset;
+       };
+       __le32 id;
+       __le32 ver;
+       __le32 sr;
+       __le32 len;
+       u8 data[];
+} __packed;
+
+#define WMFW_ADSP1 1
+#define WMFW_ADSP2 2
+
+#define WMFW_ABSOLUTE  0xf0
+#define WMFW_NAME_TEXT 0xfe
+#define WMFW_INFO_TEXT 0xff
+
+#define WMFW_ADSP1_PM 2
+#define WMFW_ADSP1_DM 3
+#define WMFW_ADSP1_ZM 4
+
+#define WMFW_ADSP2_PM 2
+#define WMFW_ADSP2_ZM 4
+#define WMFW_ADSP2_XM 5
+#define WMFW_ADSP2_YM 6
+
+#endif
index 6fac5af13298ffa2c64ebf5bad1b5fde6a0ac6f6..d55e6477bff0c9a855379d26db50538ff7b5e178 100644 (file)
@@ -71,6 +71,11 @@ static int evm_hw_params(struct snd_pcm_substream *substream,
        if (ret < 0)
                return ret;
 
+       /* set the CPU system clock */
+       ret = snd_soc_dai_set_sysclk(cpu_dai, 0, sysclk, SND_SOC_CLOCK_OUT);
+       if (ret < 0)
+               return ret;
+
        return 0;
 }
 
index 714e51e5be5bd2c7038f1965a74545a01c5a268c..55e2bf652beff53d6694e3cf20d2d2e4d6f17393 100644 (file)
 #define ACLKXE         BIT(5)
 #define TX_ASYNC       BIT(6)
 #define ACLKXPOL       BIT(7)
+#define ACLKXDIV_MASK  0x1f
 
 /*
  * DAVINCI_MCASP_ACLKRCTL_REG Receive Clock Control Register Bits
 #define ACLKRE         BIT(5)
 #define RX_ASYNC       BIT(6)
 #define ACLKRPOL       BIT(7)
+#define ACLKRDIV_MASK  0x1f
 
 /*
  * DAVINCI_MCASP_AHCLKXCTL_REG - High Frequency Transmit Clock Control
 #define AHCLKXDIV(val) (val)
 #define AHCLKXPOL      BIT(14)
 #define AHCLKXE                BIT(15)
+#define AHCLKXDIV_MASK 0xfff
 
 /*
  * DAVINCI_MCASP_AHCLKRCTL_REG - High Frequency Receive Clock Control
 #define AHCLKRDIV(val) (val)
 #define AHCLKRPOL      BIT(14)
 #define AHCLKRE                BIT(15)
+#define AHCLKRDIV_MASK 0xfff
 
 /*
  * DAVINCI_MCASP_XRSRCTL_BASE_REG -  Serializer Control Register Bits
@@ -473,6 +477,23 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
        struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
        void __iomem *base = dev->base;
 
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_DSP_B:
+       case SND_SOC_DAIFMT_AC97:
+               mcasp_clr_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, FSXDUR);
+               mcasp_clr_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, FSRDUR);
+               break;
+       default:
+               /* configure a full-word SYNC pulse (LRCLK) */
+               mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, FSXDUR);
+               mcasp_set_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, FSRDUR);
+
+               /* make 1st data bit occur one ACLK cycle after the frame sync */
+               mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, FSXDLY(1));
+               mcasp_set_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, FSRDLY(1));
+               break;
+       }
+
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
        case SND_SOC_DAIFMT_CBS_CFS:
                /* codec is clock and frame slave */
@@ -482,8 +503,7 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
                mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
                mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE);
 
-               mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG,
-                               ACLKX | AHCLKX | AFSX);
+               mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG, ACLKX | AFSX);
                break;
        case SND_SOC_DAIFMT_CBM_CFS:
                /* codec is clock master and frame slave */
@@ -554,59 +574,75 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
        return 0;
 }
 
-static int davinci_config_channel_size(struct davinci_audio_dev *dev,
-                                      int channel_size)
+static int davinci_mcasp_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div)
 {
-       u32 fmt = 0;
-       u32 mask, rotate;
-
-       switch (channel_size) {
-       case DAVINCI_AUDIO_WORD_8:
-               fmt = 0x03;
-               rotate = 6;
-               mask = 0x000000ff;
-               break;
+       struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(dai);
 
-       case DAVINCI_AUDIO_WORD_12:
-               fmt = 0x05;
-               rotate = 5;
-               mask = 0x00000fff;
+       switch (div_id) {
+       case 0:         /* MCLK divider */
+               mcasp_mod_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG,
+                              AHCLKXDIV(div - 1), AHCLKXDIV_MASK);
+               mcasp_mod_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG,
+                              AHCLKRDIV(div - 1), AHCLKRDIV_MASK);
                break;
 
-       case DAVINCI_AUDIO_WORD_16:
-               fmt = 0x07;
-               rotate = 4;
-               mask = 0x0000ffff;
+       case 1:         /* BCLK divider */
+               mcasp_mod_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG,
+                              ACLKXDIV(div - 1), ACLKXDIV_MASK);
+               mcasp_mod_bits(dev->base + DAVINCI_MCASP_ACLKRCTL_REG,
+                              ACLKRDIV(div - 1), ACLKRDIV_MASK);
                break;
 
-       case DAVINCI_AUDIO_WORD_20:
-               fmt = 0x09;
-               rotate = 3;
-               mask = 0x000fffff;
+       case 2:         /* BCLK/LRCLK ratio */
+               dev->bclk_lrclk_ratio = div;
                break;
 
-       case DAVINCI_AUDIO_WORD_24:
-               fmt = 0x0B;
-               rotate = 2;
-               mask = 0x00ffffff;
-               break;
+       default:
+               return -EINVAL;
+       }
 
-       case DAVINCI_AUDIO_WORD_28:
-               fmt = 0x0D;
-               rotate = 1;
-               mask = 0x0fffffff;
-               break;
+       return 0;
+}
 
-       case DAVINCI_AUDIO_WORD_32:
-               fmt = 0x0F;
-               rotate = 0;
-               mask = 0xffffffff;
-               break;
+static int davinci_mcasp_set_sysclk(struct snd_soc_dai *dai, int clk_id,
+                                   unsigned int freq, int dir)
+{
+       struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(dai);
 
-       default:
-               return -EINVAL;
+       if (dir == SND_SOC_CLOCK_OUT) {
+               mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXE);
+               mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG, AHCLKRE);
+               mcasp_set_bits(dev->base + DAVINCI_MCASP_PDIR_REG, AHCLKX);
+       } else {
+               mcasp_clr_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXE);
+               mcasp_clr_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG, AHCLKRE);
+               mcasp_clr_bits(dev->base + DAVINCI_MCASP_PDIR_REG, AHCLKX);
        }
 
+       return 0;
+}
+
+static int davinci_config_channel_size(struct davinci_audio_dev *dev,
+                                      int word_length)
+{
+       u32 fmt;
+       u32 rotate = (32 - word_length) / 4;
+       u32 mask = (1ULL << word_length) - 1;
+
+       /*
+        * if s BCLK-to-LRCLK ratio has been configured via the set_clkdiv()
+        * callback, take it into account here. That allows us to for example
+        * send 32 bits per channel to the codec, while only 16 of them carry
+        * audio payload.
+        * The clock ratio is given for a full period of data (both left and
+        * right channels), so it has to be divided by 2.
+        */
+       if (dev->bclk_lrclk_ratio)
+               word_length = dev->bclk_lrclk_ratio / 2;
+
+       /* mapping of the XSSZ bit-field as described in the datasheet */
+       fmt = (word_length >> 1) - 1;
+
        mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMT_REG,
                                        RXSSZ(fmt), RXSSZ(0x0F));
        mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMT_REG,
@@ -709,8 +745,6 @@ static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)
        if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
                /* bit stream is MSB first  with no delay */
                /* DSP_B mode */
-               mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG,
-                               AHCLKXE);
                mcasp_set_reg(dev->base + DAVINCI_MCASP_TXTDM_REG, mask);
                mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, TXORD);
 
@@ -720,14 +754,10 @@ static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)
                else
                        printk(KERN_ERR "playback tdm slot %d not supported\n",
                                dev->tdm_slots);
-
-               mcasp_clr_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, FSXDUR);
        } else {
                /* bit stream is MSB first with no delay */
                /* DSP_B mode */
                mcasp_set_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, RXORD);
-               mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG,
-                               AHCLKRE);
                mcasp_set_reg(dev->base + DAVINCI_MCASP_RXTDM_REG, mask);
 
                if ((dev->tdm_slots >= 2) && (dev->tdm_slots <= 32))
@@ -736,8 +766,6 @@ static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)
                else
                        printk(KERN_ERR "capture tdm slot %d not supported\n",
                                dev->tdm_slots);
-
-               mcasp_clr_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, FSRDUR);
        }
 }
 
@@ -800,19 +828,27 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
        case SNDRV_PCM_FORMAT_U8:
        case SNDRV_PCM_FORMAT_S8:
                dma_params->data_type = 1;
-               word_length = DAVINCI_AUDIO_WORD_8;
+               word_length = 8;
                break;
 
        case SNDRV_PCM_FORMAT_U16_LE:
        case SNDRV_PCM_FORMAT_S16_LE:
                dma_params->data_type = 2;
-               word_length = DAVINCI_AUDIO_WORD_16;
+               word_length = 16;
+               break;
+
+       case SNDRV_PCM_FORMAT_U24_3LE:
+       case SNDRV_PCM_FORMAT_S24_3LE:
+               dma_params->data_type = 3;
+               word_length = 24;
                break;
 
+       case SNDRV_PCM_FORMAT_U24_LE:
+       case SNDRV_PCM_FORMAT_S24_LE:
        case SNDRV_PCM_FORMAT_U32_LE:
        case SNDRV_PCM_FORMAT_S32_LE:
                dma_params->data_type = 4;
-               word_length = DAVINCI_AUDIO_WORD_32;
+               word_length = 32;
                break;
 
        default:
@@ -880,13 +916,18 @@ static const struct snd_soc_dai_ops davinci_mcasp_dai_ops = {
        .trigger        = davinci_mcasp_trigger,
        .hw_params      = davinci_mcasp_hw_params,
        .set_fmt        = davinci_mcasp_set_dai_fmt,
-
+       .set_clkdiv     = davinci_mcasp_set_clkdiv,
+       .set_sysclk     = davinci_mcasp_set_sysclk,
 };
 
 #define DAVINCI_MCASP_PCM_FMTS (SNDRV_PCM_FMTBIT_S8 | \
                                SNDRV_PCM_FMTBIT_U8 | \
                                SNDRV_PCM_FMTBIT_S16_LE | \
                                SNDRV_PCM_FMTBIT_U16_LE | \
+                               SNDRV_PCM_FMTBIT_S24_LE | \
+                               SNDRV_PCM_FMTBIT_U24_LE | \
+                               SNDRV_PCM_FMTBIT_S24_3LE | \
+                               SNDRV_PCM_FMTBIT_U24_3LE | \
                                SNDRV_PCM_FMTBIT_S32_LE | \
                                SNDRV_PCM_FMTBIT_U32_LE)
 
@@ -1089,7 +1130,6 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
        dev->tdm_slots = pdata->tdm_slots;
        dev->num_serializer = pdata->num_serializer;
        dev->serial_dir = pdata->serial_dir;
-       dev->codec_fmt = pdata->codec_fmt;
        dev->version = pdata->version;
        dev->txnumevt = pdata->txnumevt;
        dev->rxnumevt = pdata->rxnumevt;
@@ -1098,6 +1138,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
        dma_data = &dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK];
        dma_data->asp_chan_q = pdata->asp_chan_q;
        dma_data->ram_chan_q = pdata->ram_chan_q;
+       dma_data->sram_pool = pdata->sram_pool;
        dma_data->sram_size = pdata->sram_size_playback;
        dma_data->dma_addr = (dma_addr_t) (pdata->tx_dma_offset +
                                                        mem->start);
@@ -1115,6 +1156,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
        dma_data = &dev->dma_params[SNDRV_PCM_STREAM_CAPTURE];
        dma_data->asp_chan_q = pdata->asp_chan_q;
        dma_data->ram_chan_q = pdata->ram_chan_q;
+       dma_data->sram_pool = pdata->sram_pool;
        dma_data->sram_size = pdata->sram_size_capture;
        dma_data->dma_addr = (dma_addr_t)(pdata->rx_dma_offset +
                                                        mem->start);
index 0de9ed6ce038a8472aeb762d403fbf26d579bc24..0edd3b5a37fd86a5c04a54b66b8735d900e33a06 100644 (file)
 
 #include "davinci-pcm.h"
 
-#define DAVINCI_MCASP_RATES    SNDRV_PCM_RATE_8000_96000
+#define DAVINCI_MCASP_RATES    SNDRV_PCM_RATE_8000_192000
 #define DAVINCI_MCASP_I2S_DAI  0
 #define DAVINCI_MCASP_DIT_DAI  1
 
-enum {
-       DAVINCI_AUDIO_WORD_8 = 0,
-       DAVINCI_AUDIO_WORD_12,
-       DAVINCI_AUDIO_WORD_16,
-       DAVINCI_AUDIO_WORD_20,
-       DAVINCI_AUDIO_WORD_24,
-       DAVINCI_AUDIO_WORD_32,
-       DAVINCI_AUDIO_WORD_28,  /* This is only valid for McASP */
-};
-
 struct davinci_audio_dev {
        struct davinci_pcm_dma_params dma_params[2];
        void __iomem *base;
-       int sample_rate;
        struct device *dev;
-       unsigned int codec_fmt;
 
        /* McASP specific data */
        int     tdm_slots;
@@ -50,6 +38,7 @@ struct davinci_audio_dev {
        u8      num_serializer;
        u8      *serial_dir;
        u8      version;
+       u8      bclk_lrclk_ratio;
 
        /* McASP FIFO related */
        u8      txnumevt;
index 93ea3bf567e1fd1835ff643ff4e73d67fecdce12..afab81f844ae82c32418d6d1f83301c2d29d1f4e 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/slab.h>
 #include <linux/dma-mapping.h>
 #include <linux/kernel.h>
+#include <linux/genalloc.h>
 
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -23,7 +24,6 @@
 #include <sound/soc.h>
 
 #include <asm/dma.h>
-#include <mach/sram.h>
 
 #include "davinci-pcm.h"
 
@@ -67,13 +67,9 @@ static struct snd_pcm_hardware pcm_hardware_playback = {
                 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME|
                 SNDRV_PCM_INFO_BATCH),
        .formats = DAVINCI_PCM_FMTBITS,
-       .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
-                 SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |
-                 SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
-                 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
-                 SNDRV_PCM_RATE_KNOT),
+       .rates = SNDRV_PCM_RATE_8000_192000 | SNDRV_PCM_RATE_KNOT,
        .rate_min = 8000,
-       .rate_max = 96000,
+       .rate_max = 192000,
        .channels_min = 2,
        .channels_max = 384,
        .buffer_bytes_max = 128 * 1024,
@@ -90,13 +86,9 @@ static struct snd_pcm_hardware pcm_hardware_capture = {
                 SNDRV_PCM_INFO_PAUSE |
                 SNDRV_PCM_INFO_BATCH),
        .formats = DAVINCI_PCM_FMTBITS,
-       .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
-                 SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |
-                 SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
-                 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
-                 SNDRV_PCM_RATE_KNOT),
+       .rates = SNDRV_PCM_RATE_8000_192000 | SNDRV_PCM_RATE_KNOT,
        .rate_min = 8000,
-       .rate_max = 96000,
+       .rate_max = 192000,
        .channels_min = 2,
        .channels_max = 384,
        .buffer_bytes_max = 128 * 1024,
@@ -259,7 +251,9 @@ static void davinci_pcm_dma_irq(unsigned link, u16 ch_status, void *data)
        }
 }
 
-static int allocate_sram(struct snd_pcm_substream *substream, unsigned size,
+#ifdef CONFIG_GENERIC_ALLOCATOR
+static int allocate_sram(struct snd_pcm_substream *substream,
+               struct gen_pool *sram_pool, unsigned size,
                struct snd_pcm_hardware *ppcm)
 {
        struct snd_dma_buffer *buf = &substream->dma_buffer;
@@ -271,9 +265,10 @@ static int allocate_sram(struct snd_pcm_substream *substream, unsigned size,
                return 0;
 
        ppcm->period_bytes_max = size;
-       iram_virt = sram_alloc(size, &iram_phys);
+       iram_virt = (void *)gen_pool_alloc(sram_pool, size);
        if (!iram_virt)
                goto exit1;
+       iram_phys = gen_pool_virt_to_phys(sram_pool, (unsigned)iram_virt);
        iram_dma = kzalloc(sizeof(*iram_dma), GFP_KERNEL);
        if (!iram_dma)
                goto exit2;
@@ -285,11 +280,33 @@ static int allocate_sram(struct snd_pcm_substream *substream, unsigned size,
        return 0;
 exit2:
        if (iram_virt)
-               sram_free(iram_virt, size);
+               gen_pool_free(sram_pool, (unsigned)iram_virt, size);
 exit1:
        return -ENOMEM;
 }
 
+static void davinci_free_sram(struct snd_pcm_substream *substream,
+                             struct snd_dma_buffer *iram_dma)
+{
+       struct davinci_runtime_data *prtd = substream->runtime->private_data;
+       struct gen_pool *sram_pool = prtd->params->sram_pool;
+
+       gen_pool_free(sram_pool, (unsigned) iram_dma->area, iram_dma->bytes);
+}
+#else
+static int allocate_sram(struct snd_pcm_substream *substream,
+               struct gen_pool *sram_pool, unsigned size,
+               struct snd_pcm_hardware *ppcm)
+{
+       return 0;
+}
+
+static void davinci_free_sram(struct snd_pcm_substream *substream,
+                             struct snd_dma_buffer *iram_dma)
+{
+}
+#endif
+
 /*
  * Only used with ping/pong.
  * This is called after runtime->dma_addr, period_bytes and data_type are valid
@@ -676,7 +693,7 @@ static int davinci_pcm_open(struct snd_pcm_substream *substream)
 
        ppcm = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
                        &pcm_hardware_playback : &pcm_hardware_capture;
-       allocate_sram(substream, params->sram_size, ppcm);
+       allocate_sram(substream, params->sram_pool, params->sram_size, ppcm);
        snd_soc_set_runtime_hwparams(substream, ppcm);
        /* ensure that buffer size is a multiple of period size */
        ret = snd_pcm_hw_constraint_integer(runtime,
@@ -819,7 +836,7 @@ static void davinci_pcm_free(struct snd_pcm *pcm)
                buf->area = NULL;
                iram_dma = buf->private_data;
                if (iram_dma) {
-                       sram_free(iram_dma->area, iram_dma->bytes);
+                       davinci_free_sram(substream, iram_dma);
                        kfree(iram_dma);
                }
        }
index fc4d01cdd8c95c92b11694faece56d77fc648bd9..b6ef7039dd097b4ac99c6e9b14a0c35ed59fd203 100644 (file)
@@ -12,6 +12,7 @@
 #ifndef _DAVINCI_PCM_H
 #define _DAVINCI_PCM_H
 
+#include <linux/genalloc.h>
 #include <linux/platform_data/davinci_asp.h>
 #include <mach/edma.h>
 
@@ -20,6 +21,7 @@ struct davinci_pcm_dma_params {
        unsigned short acnt;
        dma_addr_t dma_addr;            /* device physical address for DMA */
        unsigned sram_size;
+       struct gen_pool *sram_pool;     /* SRAM gen_pool for ping pong */
        enum dma_event_q asp_chan_q;    /* event queue number for ASP channel */
        enum dma_event_q ram_chan_q;    /* event queue number for RAM channel */
        unsigned char data_type;        /* xfer data type */
index 10fd172ee3c6777064c654e3fe4d361fd23b4dfe..3b98159d9645a8ecf917fb8c86c41de6a401c929 100644 (file)
@@ -112,12 +112,12 @@ config SND_SOC_IMX_PCM
        tristate
 
 config SND_SOC_IMX_PCM_FIQ
-       tristate
+       bool
        select FIQ
        select SND_SOC_IMX_PCM
 
 config SND_SOC_IMX_PCM_DMA
-       tristate
+       bool
        select SND_SOC_DMAENGINE_PCM
        select SND_SOC_IMX_PCM
 
index 515ba665f97c222714f5b138f1a8c03b95b74724..afd34794db539a0f5de4154a5a635a69f40913e1 100644 (file)
@@ -30,14 +30,18 @@ obj-$(CONFIG_SND_MPC52xx_SOC_EFIKA) += efika-audio-fabric.o
 # i.MX Platform Support
 snd-soc-imx-ssi-objs := imx-ssi.o
 snd-soc-imx-audmux-objs := imx-audmux.o
+snd-soc-imx-pcm-objs := imx-pcm.o
+ifneq ($(CONFIG_SND_SOC_IMX_PCM_FIQ),)
+       snd-soc-imx-pcm-objs += imx-pcm-fiq.o
+endif
+ifneq ($(CONFIG_SND_SOC_IMX_PCM_DMA),)
+       snd-soc-imx-pcm-objs += imx-pcm-dma.o
+endif
 
 obj-$(CONFIG_SND_SOC_IMX_SSI) += snd-soc-imx-ssi.o
 obj-$(CONFIG_SND_SOC_IMX_AUDMUX) += snd-soc-imx-audmux.o
 
 obj-$(CONFIG_SND_SOC_IMX_PCM) += snd-soc-imx-pcm.o
-snd-soc-imx-pcm-y := imx-pcm.o
-snd-soc-imx-pcm-$(CONFIG_SND_SOC_IMX_PCM_FIQ) += imx-pcm-fiq.o
-snd-soc-imx-pcm-$(CONFIG_SND_SOC_IMX_PCM_DMA) += imx-pcm-dma.o
 
 # i.MX Machine Support
 snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o
index b9f16598324c9b4b85373b6f55d785011c4d8b68..2ba08148655f32ee2fa7301c44d65b54e7ea02fb 100644 (file)
@@ -71,7 +71,6 @@ static irqreturn_t kirkwood_dma_irq(int irq, void *dev_id)
                printk(KERN_WARNING "%s: got err interrupt 0x%lx\n",
                                __func__, cause);
                writel(cause, priv->io + KIRKWOOD_ERR_CAUSE);
-               return IRQ_HANDLED;
        }
 
        /* we've enabled only bytes interrupts ... */
@@ -178,7 +177,7 @@ static int kirkwood_dma_open(struct snd_pcm_substream *substream)
        }
 
        dram = mv_mbus_dram_info();
-       addr = virt_to_phys(substream->dma_buffer.area);
+       addr = substream->dma_buffer.addr;
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
                prdata->play_stream = substream;
                kirkwood_dma_conf_mbus_windows(priv->io,
index 542538d10ab7df46b02fc2b6bb3630c8bed45322..1d5db484d2df331b15e8e385cd32e2acd79e4d79 100644 (file)
@@ -95,7 +95,7 @@ static inline void kirkwood_set_dco(void __iomem *io, unsigned long rate)
        do {
                cpu_relax();
                value = readl(io + KIRKWOOD_DCO_SPCR_STATUS);
-               value &= KIRKWOOD_DCO_SPCR_STATUS;
+               value &= KIRKWOOD_DCO_SPCR_STATUS_DCO_LOCK;
        } while (value == 0);
 }
 
@@ -180,67 +180,72 @@ static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream,
                                int cmd, struct snd_soc_dai *dai)
 {
        struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
-       unsigned long value;
-
-       /*
-        * specs says KIRKWOOD_PLAYCTL must be read 2 times before
-        * changing it. So read 1 time here and 1 later.
-        */
-       value = readl(priv->io + KIRKWOOD_PLAYCTL);
+       uint32_t ctl, value;
+
+       ctl = readl(priv->io + KIRKWOOD_PLAYCTL);
+       if (ctl & KIRKWOOD_PLAYCTL_PAUSE) {
+               unsigned timeout = 5000;
+               /*
+                * The Armada510 spec says that if we enter pause mode, the
+                * busy bit must be read back as clear _twice_.  Make sure
+                * we respect that otherwise we get DMA underruns.
+                */
+               do {
+                       value = ctl;
+                       ctl = readl(priv->io + KIRKWOOD_PLAYCTL);
+                       if (!((ctl | value) & KIRKWOOD_PLAYCTL_PLAY_BUSY))
+                               break;
+                       udelay(1);
+               } while (timeout--);
+
+               if ((ctl | value) & KIRKWOOD_PLAYCTL_PLAY_BUSY)
+                       dev_notice(dai->dev, "timed out waiting for busy to deassert: %08x\n",
+                                  ctl);
+       }
 
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
-               /* stop audio, enable interrupts */
-               value = readl(priv->io + KIRKWOOD_PLAYCTL);
-               value |= KIRKWOOD_PLAYCTL_PAUSE;
-               writel(value, priv->io + KIRKWOOD_PLAYCTL);
-
                value = readl(priv->io + KIRKWOOD_INT_MASK);
                value |= KIRKWOOD_INT_CAUSE_PLAY_BYTES;
                writel(value, priv->io + KIRKWOOD_INT_MASK);
 
                /* configure audio & enable i2s playback */
-               value = readl(priv->io + KIRKWOOD_PLAYCTL);
-               value &= ~KIRKWOOD_PLAYCTL_BURST_MASK;
-               value &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE
+               ctl &= ~KIRKWOOD_PLAYCTL_BURST_MASK;
+               ctl &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE
                                | KIRKWOOD_PLAYCTL_SPDIF_EN);
 
                if (priv->burst == 32)
-                       value |= KIRKWOOD_PLAYCTL_BURST_32;
+                       ctl |= KIRKWOOD_PLAYCTL_BURST_32;
                else
-                       value |= KIRKWOOD_PLAYCTL_BURST_128;
-               value |= KIRKWOOD_PLAYCTL_I2S_EN;
-               writel(value, priv->io + KIRKWOOD_PLAYCTL);
+                       ctl |= KIRKWOOD_PLAYCTL_BURST_128;
+               ctl |= KIRKWOOD_PLAYCTL_I2S_EN;
+               writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
                break;
 
        case SNDRV_PCM_TRIGGER_STOP:
                /* stop audio, disable interrupts */
-               value = readl(priv->io + KIRKWOOD_PLAYCTL);
-               value |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE;
-               writel(value, priv->io + KIRKWOOD_PLAYCTL);
+               ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE;
+               writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
 
                value = readl(priv->io + KIRKWOOD_INT_MASK);
                value &= ~KIRKWOOD_INT_CAUSE_PLAY_BYTES;
                writel(value, priv->io + KIRKWOOD_INT_MASK);
 
                /* disable all playbacks */
-               value = readl(priv->io + KIRKWOOD_PLAYCTL);
-               value &= ~(KIRKWOOD_PLAYCTL_I2S_EN | KIRKWOOD_PLAYCTL_SPDIF_EN);
-               writel(value, priv->io + KIRKWOOD_PLAYCTL);
+               ctl &= ~(KIRKWOOD_PLAYCTL_I2S_EN | KIRKWOOD_PLAYCTL_SPDIF_EN);
+               writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
                break;
 
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
        case SNDRV_PCM_TRIGGER_SUSPEND:
-               value = readl(priv->io + KIRKWOOD_PLAYCTL);
-               value |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE;
-               writel(value, priv->io + KIRKWOOD_PLAYCTL);
+               ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE;
+               writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
                break;
 
        case SNDRV_PCM_TRIGGER_RESUME:
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-               value = readl(priv->io + KIRKWOOD_PLAYCTL);
-               value &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE);
-               writel(value, priv->io + KIRKWOOD_PLAYCTL);
+               ctl &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE);
+               writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
                break;
 
        default:
@@ -260,11 +265,6 @@ static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream *substream,
 
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
-               /* stop audio, enable interrupts */
-               value = readl(priv->io + KIRKWOOD_RECCTL);
-               value |= KIRKWOOD_RECCTL_PAUSE;
-               writel(value, priv->io + KIRKWOOD_RECCTL);
-
                value = readl(priv->io + KIRKWOOD_INT_MASK);
                value |= KIRKWOOD_INT_CAUSE_REC_BYTES;
                writel(value, priv->io + KIRKWOOD_INT_MASK);
index aa037b292f3dc05a9b6300c3cc4890988c0c2faf..b304e375568aedf104e144e5c4edfea493407abc 100644 (file)
@@ -229,6 +229,7 @@ int mxs_saif_put_mclk(unsigned int saif_id)
        saif->mclk_in_use = 0;
        return 0;
 }
+EXPORT_SYMBOL_GPL(mxs_saif_put_mclk);
 
 /*
  * Get MCLK and set clock rate, then enable it
@@ -282,6 +283,7 @@ int mxs_saif_get_mclk(unsigned int saif_id, unsigned int mclk,
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(mxs_saif_get_mclk);
 
 /*
  * SAIF DAI format configuration.
@@ -523,16 +525,24 @@ static int mxs_saif_trigger(struct snd_pcm_substream *substream, int cmd,
 
                if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
                        /*
-                        * write a data to saif data register to trigger
-                        * the transfer
+                        * write data to saif data register to trigger
+                        * the transfer.
+                        * For 24-bit format the 32-bit FIFO register stores
+                        * only one channel, so we need to write twice.
+                        * This is also safe for the other non 24-bit formats.
                         */
                        __raw_writel(0, saif->base + SAIF_DATA);
+                       __raw_writel(0, saif->base + SAIF_DATA);
                } else {
                        /*
-                        * read a data from saif data register to trigger
-                        * the receive
+                        * read data from saif data register to trigger
+                        * the receive.
+                        * For 24-bit format the 32-bit FIFO register stores
+                        * only one channel, so we need to read twice.
+                        * This is also safe for the other non 24-bit formats.
                         */
                        __raw_readl(saif->base + SAIF_DATA);
+                       __raw_readl(saif->base + SAIF_DATA);
                }
 
                master_saif->ongoing = 1;
@@ -812,3 +822,4 @@ module_platform_driver(mxs_saif_driver);
 MODULE_AUTHOR("Freescale Semiconductor, Inc.");
 MODULE_DESCRIPTION("MXS ASoC SAIF driver");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:mxs-saif");
index afb8d4f1bedfac70eb98492ce5b4c023bb9d0752..a9a243860428d5c49fce866e1c38f1b2dd82ea5a 100644 (file)
@@ -28,8 +28,6 @@
 
 #include <linux/platform_data/asoc-ti-mcbsp.h>
 
-#include <plat/cpu.h>
-
 #include "mcbsp.h"
 
 static void omap_mcbsp_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val)
@@ -612,7 +610,7 @@ void omap_mcbsp_free(struct omap_mcbsp *mcbsp)
         * system will refuse to enter idle if the CLKS pin source is not reset
         * back to internal source.
         */
-       if (!cpu_class_is_omap1())
+       if (!mcbsp_omap1())
                omap2_mcbsp_set_clks_src(mcbsp, MCBSP_CLKS_PRCM_SRC);
 
        spin_lock(&mcbsp->lock);
index 49a67259ce5a1d115de8bce006e2d6d99b48a633..a89791c239a5d0b654d121501a8353a6ac6ec4a8 100644 (file)
 
 #include "omap-pcm.h"
 
+#ifdef CONFIG_ARCH_OMAP1
+#define mcbsp_omap1()  1
+#else
+#define mcbsp_omap1()  0
+#endif
+
 /* McBSP register numbers. Register address offset = num * reg_step */
 enum {
        /* Common registers */
index a57a4e68dcc6166a2161b49b1d21ab7a8e49dc87..1d6ea8609d284eb72baa9b6ac51d2929cfd47239 100644 (file)
@@ -331,8 +331,8 @@ static __devinit int omap_abe_probe(struct platform_device *pdev)
                        num_links = 1;
                }
 
-               of_property_read_u32(node, "ti,jack-detection",
-                                    &priv->jack_detection);
+               priv->jack_detection = of_property_read_bool(node,
+                                                          "ti,jack-detection");
                of_property_read_u32(node, "ti,mclk-freq",
                                     &priv->mclk_freq);
                if (!priv->mclk_freq) {
index 68f2cd1a92061504bd332c683d286c8ffe8414eb..5a6aeaf552a89666672e4bc2a46a3106ba26a532 100644 (file)
@@ -464,9 +464,9 @@ static __devinit int asoc_dmic_probe(struct platform_device *pdev)
 
        mutex_init(&dmic->mutex);
 
-       dmic->fclk = clk_get(dmic->dev, "dmic_fck");
+       dmic->fclk = clk_get(dmic->dev, "fck");
        if (IS_ERR(dmic->fclk)) {
-               dev_err(dmic->dev, "cant get dmic_fck\n");
+               dev_err(dmic->dev, "cant get fck\n");
                return -ENODEV;
        }
 
index a6ee157478593f1e5eb338e51597df176308a953..09167609c93e99521d8bf47a37b692c77e13c128 100644 (file)
@@ -34,7 +34,6 @@
 #include <sound/initval.h>
 #include <sound/soc.h>
 
-#include <plat/cpu.h>
 #include <linux/platform_data/asoc-ti-mcbsp.h>
 #include "mcbsp.h"
 #include "omap-mcbsp.h"
@@ -512,7 +511,7 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
                regs->srgr2     |= CLKSM;
                break;
        case OMAP_MCBSP_SYSCLK_CLKS_FCLK:
-               if (cpu_class_is_omap1()) {
+               if (mcbsp_omap1()) {
                        err = -EINVAL;
                        break;
                }
@@ -520,7 +519,7 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
                                               MCBSP_CLKS_PRCM_SRC);
                break;
        case OMAP_MCBSP_SYSCLK_CLKS_EXT:
-               if (cpu_class_is_omap1()) {
+               if (mcbsp_omap1()) {
                        err = 0;
                        break;
                }
index 677b567935f8055b6899f74e276bd4c0a39dd213..771bff27ac3e4809e3ae38d75c9d22b648375247 100644 (file)
 
 #include <linux/clk.h>
 #include <linux/platform_device.h>
+#include <linux/gpio.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/soc.h>
 
 #include <asm/mach-types.h>
-#include <mach/hardware.h>
-#include <mach/gpio.h>
-#include <mach/board-zoom.h>
 #include <linux/platform_data/asoc-ti-mcbsp.h>
+#include <linux/platform_data/gpio-omap.h>
 
 /* Register descriptions for twl4030 codec part */
 #include <linux/mfd/twl4030-audio.h>
@@ -38,8 +37,6 @@
 #include "omap-mcbsp.h"
 #include "omap-pcm.h"
 
-#define ZOOM2_HEADSET_MUX_GPIO         (OMAP_MAX_GPIO_LINES + 15)
-
 static int zoom2_hw_params(struct snd_pcm_substream *substream,
                                struct snd_pcm_hw_params *params)
 {
@@ -188,9 +185,6 @@ static int __init zoom2_soc_init(void)
        if (ret)
                goto err1;
 
-       BUG_ON(gpio_request(ZOOM2_HEADSET_MUX_GPIO, "hs_mux") < 0);
-       gpio_direction_output(ZOOM2_HEADSET_MUX_GPIO, 0);
-
        return 0;
 
 err1:
@@ -203,8 +197,6 @@ module_init(zoom2_soc_init);
 
 static void __exit zoom2_soc_exit(void)
 {
-       gpio_free(ZOOM2_HEADSET_MUX_GPIO);
-
        platform_device_unregister(zoom2_snd_device);
 }
 module_exit(zoom2_soc_exit);
index e7b83179aca2b1469af4ec1e03f35e62df1227b2..3c7c3a59ed3987b9017e89c07cf130a2a54c4a39 100644 (file)
@@ -207,6 +207,8 @@ config SND_SOC_BELLS
        select SND_SOC_WM5102
        select SND_SOC_WM5110
        select SND_SOC_WM9081
+       select SND_SOC_WM0010
+       select SND_SOC_WM1250_EV1
 
 config SND_SOC_LOWLAND
        tristate "Audio support for Wolfson Lowland"
index b0d46d63d55ea784f2f6970cd77bd2915a1c32fa..a2ca1567b9e4ff93a481d99065820d887ff8a72c 100644 (file)
@@ -212,7 +212,7 @@ static struct snd_soc_dai_link bells_dai_wm5102[] = {
        {
                .name = "Sub",
                .stream_name = "Sub",
-               .cpu_dai_name = "wm5110-aif3",
+               .cpu_dai_name = "wm5102-aif3",
                .codec_dai_name = "wm9081-hifi",
                .codec_name = "wm9081.1-006c",
                .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
index 9d7f30774a44d9524cb71f6697fc0ce96825295c..a606d0f93d1cea4db2e88f47e8ba0d94b36aa59f 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/module.h>
 #include <linux/workqueue.h>
 #include <sound/soc.h>
+#include <sound/pcm_params.h>
 #include <sound/sh_fsi.h>
 
 /* PortA/PortB register */
@@ -188,6 +189,14 @@ typedef int (*set_rate_func)(struct device *dev, int rate, int enable);
  *             --> go to codecs
  */
 
+/*
+ *     FSI clock
+ *
+ * FSIxCLK [CPG] (ick) ------->        |
+ *                             |-> FSI_DIV (div)-> FSI2
+ * FSIxCK [external] (xck) --->        |
+ */
+
 /*
  *             struct
  */
@@ -228,6 +237,20 @@ struct fsi_stream {
        dma_addr_t              dma;
 };
 
+struct fsi_clk {
+       /* see [FSI clock] */
+       struct clk *own;
+       struct clk *xck;
+       struct clk *ick;
+       struct clk *div;
+       int (*set_rate)(struct device *dev,
+                       struct fsi_priv *fsi,
+                       unsigned long rate);
+
+       unsigned long rate;
+       unsigned int count;
+};
+
 struct fsi_priv {
        void __iomem *base;
        struct fsi_master *master;
@@ -236,11 +259,17 @@ struct fsi_priv {
        struct fsi_stream playback;
        struct fsi_stream capture;
 
+       struct fsi_clk clock;
+
        u32 fmt;
 
        int chan_num:16;
        int clk_master:1;
+       int clk_cpg:1;
        int spdif:1;
+       int enable_stream:1;
+       int bit_clk_inv:1;
+       int lr_clk_inv:1;
 
        long rate;
 };
@@ -370,6 +399,11 @@ static int fsi_is_spdif(struct fsi_priv *fsi)
        return fsi->spdif;
 }
 
+static int fsi_is_enable_stream(struct fsi_priv *fsi)
+{
+       return fsi->enable_stream;
+}
+
 static int fsi_is_play(struct snd_pcm_substream *substream)
 {
        return substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
@@ -717,14 +751,335 @@ static void fsi_spdif_clk_ctrl(struct fsi_priv *fsi, int enable)
 /*
  *             clock function
  */
+static int fsi_clk_init(struct device *dev,
+                       struct fsi_priv *fsi,
+                       int xck,
+                       int ick,
+                       int div,
+                       int (*set_rate)(struct device *dev,
+                                       struct fsi_priv *fsi,
+                                       unsigned long rate))
+{
+       struct fsi_clk *clock = &fsi->clock;
+       int is_porta = fsi_is_port_a(fsi);
+
+       clock->xck      = NULL;
+       clock->ick      = NULL;
+       clock->div      = NULL;
+       clock->rate     = 0;
+       clock->count    = 0;
+       clock->set_rate = set_rate;
+
+       clock->own = devm_clk_get(dev, NULL);
+       if (IS_ERR(clock->own))
+               return -EINVAL;
+
+       /* external clock */
+       if (xck) {
+               clock->xck = devm_clk_get(dev, is_porta ? "xcka" : "xckb");
+               if (IS_ERR(clock->xck)) {
+                       dev_err(dev, "can't get xck clock\n");
+                       return -EINVAL;
+               }
+               if (clock->xck == clock->own) {
+                       dev_err(dev, "cpu doesn't support xck clock\n");
+                       return -EINVAL;
+               }
+       }
+
+       /* FSIACLK/FSIBCLK */
+       if (ick) {
+               clock->ick = devm_clk_get(dev,  is_porta ? "icka" : "ickb");
+               if (IS_ERR(clock->ick)) {
+                       dev_err(dev, "can't get ick clock\n");
+                       return -EINVAL;
+               }
+               if (clock->ick == clock->own) {
+                       dev_err(dev, "cpu doesn't support ick clock\n");
+                       return -EINVAL;
+               }
+       }
+
+       /* FSI-DIV */
+       if (div) {
+               clock->div = devm_clk_get(dev,  is_porta ? "diva" : "divb");
+               if (IS_ERR(clock->div)) {
+                       dev_err(dev, "can't get div clock\n");
+                       return -EINVAL;
+               }
+               if (clock->div == clock->own) {
+                       dev_err(dev, "cpu doens't support div clock\n");
+                       return -EINVAL;
+               }
+       }
+
+       return 0;
+}
+
+#define fsi_clk_invalid(fsi) fsi_clk_valid(fsi, 0)
+static void fsi_clk_valid(struct fsi_priv *fsi, unsigned long rate)
+{
+       fsi->clock.rate = rate;
+}
+
+static int fsi_clk_is_valid(struct fsi_priv *fsi)
+{
+       return  fsi->clock.set_rate &&
+               fsi->clock.rate;
+}
+
+static int fsi_clk_enable(struct device *dev,
+                         struct fsi_priv *fsi,
+                         unsigned long rate)
+{
+       struct fsi_clk *clock = &fsi->clock;
+       int ret = -EINVAL;
+
+       if (!fsi_clk_is_valid(fsi))
+               return ret;
+
+       if (0 == clock->count) {
+               ret = clock->set_rate(dev, fsi, rate);
+               if (ret < 0) {
+                       fsi_clk_invalid(fsi);
+                       return ret;
+               }
+
+               if (clock->xck)
+                       clk_enable(clock->xck);
+               if (clock->ick)
+                       clk_enable(clock->ick);
+               if (clock->div)
+                       clk_enable(clock->div);
+
+               clock->count++;
+       }
+
+       return ret;
+}
+
+static int fsi_clk_disable(struct device *dev,
+                           struct fsi_priv *fsi)
+{
+       struct fsi_clk *clock = &fsi->clock;
+
+       if (!fsi_clk_is_valid(fsi))
+               return -EINVAL;
+
+       if (1 == clock->count--) {
+               if (clock->xck)
+                       clk_disable(clock->xck);
+               if (clock->ick)
+                       clk_disable(clock->ick);
+               if (clock->div)
+                       clk_disable(clock->div);
+       }
+
+       return 0;
+}
+
+static int fsi_clk_set_ackbpf(struct device *dev,
+                             struct fsi_priv *fsi,
+                             int ackmd, int bpfmd)
+{
+       u32 data = 0;
+
+       /* check ackmd/bpfmd relationship */
+       if (bpfmd > ackmd) {
+               dev_err(dev, "unsupported rate (%d/%d)\n", ackmd, bpfmd);
+               return -EINVAL;
+       }
+
+       /*  ACKMD */
+       switch (ackmd) {
+       case 512:
+               data |= (0x0 << 12);
+               break;
+       case 256:
+               data |= (0x1 << 12);
+               break;
+       case 128:
+               data |= (0x2 << 12);
+               break;
+       case 64:
+               data |= (0x3 << 12);
+               break;
+       case 32:
+               data |= (0x4 << 12);
+               break;
+       default:
+               dev_err(dev, "unsupported ackmd (%d)\n", ackmd);
+               return -EINVAL;
+       }
+
+       /* BPFMD */
+       switch (bpfmd) {
+       case 32:
+               data |= (0x0 << 8);
+               break;
+       case 64:
+               data |= (0x1 << 8);
+               break;
+       case 128:
+               data |= (0x2 << 8);
+               break;
+       case 256:
+               data |= (0x3 << 8);
+               break;
+       case 512:
+               data |= (0x4 << 8);
+               break;
+       case 16:
+               data |= (0x7 << 8);
+               break;
+       default:
+               dev_err(dev, "unsupported bpfmd (%d)\n", bpfmd);
+               return -EINVAL;
+       }
+
+       dev_dbg(dev, "ACKMD/BPFMD = %d/%d\n", ackmd, bpfmd);
+
+       fsi_reg_mask_set(fsi, CKG1, (ACKMD_MASK | BPFMD_MASK) , data);
+       udelay(10);
+
+       return 0;
+}
+
+static int fsi_clk_set_rate_external(struct device *dev,
+                                    struct fsi_priv *fsi,
+                                    unsigned long rate)
+{
+       struct clk *xck = fsi->clock.xck;
+       struct clk *ick = fsi->clock.ick;
+       unsigned long xrate;
+       int ackmd, bpfmd;
+       int ret = 0;
+
+       /* check clock rate */
+       xrate = clk_get_rate(xck);
+       if (xrate % rate) {
+               dev_err(dev, "unsupported clock rate\n");
+               return -EINVAL;
+       }
+
+       clk_set_parent(ick, xck);
+       clk_set_rate(ick, xrate);
+
+       bpfmd = fsi->chan_num * 32;
+       ackmd = xrate / rate;
+
+       dev_dbg(dev, "external/rate = %ld/%ld\n", xrate, rate);
+
+       ret = fsi_clk_set_ackbpf(dev, fsi, ackmd, bpfmd);
+       if (ret < 0)
+               dev_err(dev, "%s failed", __func__);
+
+       return ret;
+}
+
+static int fsi_clk_set_rate_cpg(struct device *dev,
+                               struct fsi_priv *fsi,
+                               unsigned long rate)
+{
+       struct clk *ick = fsi->clock.ick;
+       struct clk *div = fsi->clock.div;
+       unsigned long target = 0; /* 12288000 or 11289600 */
+       unsigned long actual, cout;
+       unsigned long diff, min;
+       unsigned long best_cout, best_act;
+       int adj;
+       int ackmd, bpfmd;
+       int ret = -EINVAL;
+
+       if (!(12288000 % rate))
+               target = 12288000;
+       if (!(11289600 % rate))
+               target = 11289600;
+       if (!target) {
+               dev_err(dev, "unsupported rate\n");
+               return ret;
+       }
+
+       bpfmd = fsi->chan_num * 32;
+       ackmd = target / rate;
+       ret = fsi_clk_set_ackbpf(dev, fsi, ackmd, bpfmd);
+       if (ret < 0) {
+               dev_err(dev, "%s failed", __func__);
+               return ret;
+       }
+
+       /*
+        * The clock flow is
+        *
+        * [CPG] = cout => [FSI_DIV] = audio => [FSI] => [codec]
+        *
+        * But, it needs to find best match of CPG and FSI_DIV
+        * combination, since it is difficult to generate correct
+        * frequency of audio clock from ick clock only.
+        * Because ick is created from its parent clock.
+        *
+        * target       = rate x [512/256/128/64]fs
+        * cout         = round(target x adjustment)
+        * actual       = cout / adjustment (by FSI-DIV) ~= target
+        * audio        = actual
+        */
+       min = ~0;
+       best_cout = 0;
+       best_act = 0;
+       for (adj = 1; adj < 0xffff; adj++) {
+
+               cout = target * adj;
+               if (cout > 100000000) /* max clock = 100MHz */
+                       break;
+
+               /* cout/actual audio clock */
+               cout    = clk_round_rate(ick, cout);
+               actual  = cout / adj;
+
+               /* find best frequency */
+               diff = abs(actual - target);
+               if (diff < min) {
+                       min             = diff;
+                       best_cout       = cout;
+                       best_act        = actual;
+               }
+       }
+
+       ret = clk_set_rate(ick, best_cout);
+       if (ret < 0) {
+               dev_err(dev, "ick clock failed\n");
+               return -EIO;
+       }
+
+       ret = clk_set_rate(div, clk_round_rate(div, best_act));
+       if (ret < 0) {
+               dev_err(dev, "div clock failed\n");
+               return -EIO;
+       }
+
+       dev_dbg(dev, "ick/div = %ld/%ld\n",
+               clk_get_rate(ick), clk_get_rate(div));
+
+       return ret;
+}
+
 static int fsi_set_master_clk(struct device *dev, struct fsi_priv *fsi,
                              long rate, int enable)
 {
        set_rate_func set_rate = fsi_get_info_set_rate(fsi);
        int ret;
 
-       if (!set_rate)
-               return 0;
+       /*
+        * CAUTION
+        *
+        * set_rate will be deleted
+        */
+       if (!set_rate) {
+               if (enable)
+                       return fsi_clk_enable(dev, fsi, rate);
+               else
+                       return fsi_clk_disable(dev, fsi);
+       }
 
        ret = set_rate(dev, rate, enable);
        if (ret < 0) /* error */
@@ -792,10 +1147,9 @@ static int fsi_set_master_clk(struct device *dev, struct fsi_priv *fsi,
  */
 static void fsi_pio_push16(struct fsi_priv *fsi, u8 *_buf, int samples)
 {
-       u32 enable_stream = fsi_get_info_flags(fsi) & SH_FSI_ENABLE_STREAM_MODE;
        int i;
 
-       if (enable_stream) {
+       if (fsi_is_enable_stream(fsi)) {
                /*
                 * stream mode
                 * see
@@ -953,8 +1307,6 @@ static void fsi_pio_start_stop(struct fsi_priv *fsi, struct fsi_stream *io,
 
 static int fsi_pio_push_init(struct fsi_priv *fsi, struct fsi_stream *io)
 {
-       u32 enable_stream = fsi_get_info_flags(fsi) & SH_FSI_ENABLE_STREAM_MODE;
-
        /*
         * we can use 16bit stream mode
         * when "playback" and "16bit data"
@@ -962,7 +1314,7 @@ static int fsi_pio_push_init(struct fsi_priv *fsi, struct fsi_stream *io)
         * see
         *      fsi_pio_push16()
         */
-       if (enable_stream)
+       if (fsi_is_enable_stream(fsi))
                io->bus_option = BUSOP_SET(24, PACKAGE_24BITBUS_BACK) |
                                 BUSOP_SET(16, PACKAGE_16BITBUS_STREAM);
        else
@@ -1296,6 +1648,16 @@ static int fsi_hw_startup(struct fsi_priv *fsi,
 
        /* clock inversion (CKG2) */
        data = 0;
+       if (fsi->bit_clk_inv)
+               data |= (1 << 0);
+       if (fsi->lr_clk_inv)
+               data |= (1 << 4);
+       if (fsi_is_clk_master(fsi))
+               data <<= 8;
+       /* FIXME
+        *
+        * SH_FSI_xxx_INV style will be removed
+        */
        if (SH_FSI_LRM_INV & flags)
                data |= 1 << 12;
        if (SH_FSI_BRM_INV & flags)
@@ -1334,14 +1696,21 @@ static int fsi_hw_startup(struct fsi_priv *fsi,
        /* fifo init */
        fsi_fifo_init(fsi, io, dev);
 
+       /* start master clock */
+       if (fsi_is_clk_master(fsi))
+               return fsi_set_master_clk(dev, fsi, fsi->rate, 1);
+
        return 0;
 }
 
-static void fsi_hw_shutdown(struct fsi_priv *fsi,
+static int fsi_hw_shutdown(struct fsi_priv *fsi,
                            struct device *dev)
 {
+       /* stop master clock */
        if (fsi_is_clk_master(fsi))
-               fsi_set_master_clk(dev, fsi, fsi->rate, 0);
+               return fsi_set_master_clk(dev, fsi, fsi->rate, 0);
+
+       return 0;
 }
 
 static int fsi_dai_startup(struct snd_pcm_substream *substream,
@@ -1349,6 +1718,7 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream,
 {
        struct fsi_priv *fsi = fsi_get_priv(substream);
 
+       fsi_clk_invalid(fsi);
        fsi->rate = 0;
 
        return 0;
@@ -1359,6 +1729,7 @@ static void fsi_dai_shutdown(struct snd_pcm_substream *substream,
 {
        struct fsi_priv *fsi = fsi_get_priv(substream);
 
+       fsi_clk_invalid(fsi);
        fsi->rate = 0;
 }
 
@@ -1372,13 +1743,16 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
                fsi_stream_init(fsi, io, substream);
-               fsi_hw_startup(fsi, io, dai->dev);
-               ret = fsi_stream_transfer(io);
-               if (0 == ret)
+               if (!ret)
+                       ret = fsi_hw_startup(fsi, io, dai->dev);
+               if (!ret)
+                       ret = fsi_stream_transfer(io);
+               if (!ret)
                        fsi_stream_start(fsi, io);
                break;
        case SNDRV_PCM_TRIGGER_STOP:
-               fsi_hw_shutdown(fsi, dai->dev);
+               if (!ret)
+                       ret = fsi_hw_shutdown(fsi, dai->dev);
                fsi_stream_stop(fsi, io);
                fsi_stream_quit(fsi, io);
                break;
@@ -1414,7 +1788,6 @@ static int fsi_set_fmt_spdif(struct fsi_priv *fsi)
 
        fsi->fmt = CR_DTMD_SPDIF_PCM | CR_PCM;
        fsi->chan_num = 2;
-       fsi->spdif = 1;
 
        return 0;
 }
@@ -1423,7 +1796,6 @@ static int fsi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 {
        struct fsi_priv *fsi = fsi_get_priv_frm_dai(dai);
        set_rate_func set_rate = fsi_get_info_set_rate(fsi);
-       u32 flags = fsi_get_info_flags(fsi);
        int ret;
 
        /* set master/slave audio interface */
@@ -1437,23 +1809,50 @@ static int fsi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
                return -EINVAL;
        }
 
-       if (fsi_is_clk_master(fsi) && !set_rate) {
-               dev_err(dai->dev, "platform doesn't have set_rate\n");
-               return -EINVAL;
-       }
-
-       /* set format */
-       switch (flags & SH_FSI_FMT_MASK) {
-       case SH_FSI_FMT_DAI:
-               ret = fsi_set_fmt_dai(fsi, fmt & SND_SOC_DAIFMT_FORMAT_MASK);
+       /* set clock inversion */
+       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+       case SND_SOC_DAIFMT_NB_IF:
+               fsi->bit_clk_inv = 0;
+               fsi->lr_clk_inv = 1;
                break;
-       case SH_FSI_FMT_SPDIF:
-               ret = fsi_set_fmt_spdif(fsi);
+       case SND_SOC_DAIFMT_IB_NF:
+               fsi->bit_clk_inv = 1;
+               fsi->lr_clk_inv = 0;
                break;
+       case SND_SOC_DAIFMT_IB_IF:
+               fsi->bit_clk_inv = 1;
+               fsi->lr_clk_inv = 1;
+               break;
+       case SND_SOC_DAIFMT_NB_NF:
        default:
-               ret = -EINVAL;
+               fsi->bit_clk_inv = 0;
+               fsi->lr_clk_inv = 0;
+               break;
+       }
+
+       if (fsi_is_clk_master(fsi)) {
+               /*
+                * CAUTION
+                *
+                * set_rate will be deleted
+                */
+               if (set_rate)
+                       dev_warn(dai->dev, "set_rate will be removed soon\n");
+
+               if (fsi->clk_cpg)
+                       fsi_clk_init(dai->dev, fsi, 0, 1, 1,
+                                    fsi_clk_set_rate_cpg);
+               else
+                       fsi_clk_init(dai->dev, fsi, 1, 1, 0,
+                                    fsi_clk_set_rate_external);
        }
 
+       /* set format */
+       if (fsi_is_spdif(fsi))
+               ret = fsi_set_fmt_spdif(fsi);
+       else
+               ret = fsi_set_fmt_dai(fsi, fmt & SND_SOC_DAIFMT_FORMAT_MASK);
+
        return ret;
 }
 
@@ -1462,19 +1861,13 @@ static int fsi_dai_hw_params(struct snd_pcm_substream *substream,
                             struct snd_soc_dai *dai)
 {
        struct fsi_priv *fsi = fsi_get_priv(substream);
-       long rate = params_rate(params);
-       int ret;
 
-       if (!fsi_is_clk_master(fsi))
-               return 0;
-
-       ret = fsi_set_master_clk(dai->dev, fsi, rate, 1);
-       if (ret < 0)
-               return ret;
-
-       fsi->rate = rate;
+       if (fsi_is_clk_master(fsi)) {
+               fsi->rate = params_rate(params);
+               fsi_clk_valid(fsi, fsi->rate);
+       }
 
-       return ret;
+       return 0;
 }
 
 static const struct snd_soc_dai_ops fsi_dai_ops = {
@@ -1498,7 +1891,7 @@ static struct snd_pcm_hardware fsi_pcm_hardware = {
        .rates                  = FSI_RATES,
        .rate_min               = 8000,
        .rate_max               = 192000,
-       .channels_min           = 1,
+       .channels_min           = 2,
        .channels_max           = 2,
        .buffer_bytes_max       = 64 * 1024,
        .period_bytes_min       = 32,
@@ -1586,14 +1979,14 @@ static struct snd_soc_dai_driver fsi_soc_dai[] = {
                .playback = {
                        .rates          = FSI_RATES,
                        .formats        = FSI_FMTS,
-                       .channels_min   = 1,
-                       .channels_max   = 8,
+                       .channels_min   = 2,
+                       .channels_max   = 2,
                },
                .capture = {
                        .rates          = FSI_RATES,
                        .formats        = FSI_FMTS,
-                       .channels_min   = 1,
-                       .channels_max   = 8,
+                       .channels_min   = 2,
+                       .channels_max   = 2,
                },
                .ops = &fsi_dai_ops,
        },
@@ -1602,14 +1995,14 @@ static struct snd_soc_dai_driver fsi_soc_dai[] = {
                .playback = {
                        .rates          = FSI_RATES,
                        .formats        = FSI_FMTS,
-                       .channels_min   = 1,
-                       .channels_max   = 8,
+                       .channels_min   = 2,
+                       .channels_max   = 2,
                },
                .capture = {
                        .rates          = FSI_RATES,
                        .formats        = FSI_FMTS,
-                       .channels_min   = 1,
-                       .channels_max   = 8,
+                       .channels_min   = 2,
+                       .channels_max   = 2,
                },
                .ops = &fsi_dai_ops,
        },
@@ -1624,15 +2017,29 @@ static struct snd_soc_platform_driver fsi_soc_platform = {
 /*
  *             platform function
  */
-static void fsi_handler_init(struct fsi_priv *fsi)
+static void fsi_port_info_init(struct fsi_priv *fsi,
+                              struct sh_fsi_port_info *info)
+{
+       if (info->flags & SH_FSI_FMT_SPDIF)
+               fsi->spdif = 1;
+
+       if (info->flags & SH_FSI_CLK_CPG)
+               fsi->clk_cpg = 1;
+
+       if (info->flags & SH_FSI_ENABLE_STREAM_MODE)
+               fsi->enable_stream = 1;
+}
+
+static void fsi_handler_init(struct fsi_priv *fsi,
+                            struct sh_fsi_port_info *info)
 {
        fsi->playback.handler   = &fsi_pio_push_handler; /* default PIO */
        fsi->playback.priv      = fsi;
        fsi->capture.handler    = &fsi_pio_pop_handler;  /* default PIO */
        fsi->capture.priv       = fsi;
 
-       if (fsi->info->tx_id) {
-               fsi->playback.slave.shdma_slave.slave_id = fsi->info->tx_id;
+       if (info->tx_id) {
+               fsi->playback.slave.shdma_slave.slave_id = info->tx_id;
                fsi->playback.handler = &fsi_dma_push_handler;
        }
 }
@@ -1642,10 +2049,16 @@ static int fsi_probe(struct platform_device *pdev)
        struct fsi_master *master;
        const struct platform_device_id *id_entry;
        struct sh_fsi_platform_info *info = pdev->dev.platform_data;
+       struct sh_fsi_port_info nul_info, *pinfo;
+       struct fsi_priv *fsi;
        struct resource *res;
        unsigned int irq;
        int ret;
 
+       nul_info.flags  = 0;
+       nul_info.tx_id  = 0;
+       nul_info.rx_id  = 0;
+
        id_entry = pdev->id_entry;
        if (!id_entry) {
                dev_err(&pdev->dev, "unknown fsi device\n");
@@ -1678,22 +2091,28 @@ static int fsi_probe(struct platform_device *pdev)
        spin_lock_init(&master->lock);
 
        /* FSI A setting */
-       master->fsia.base       = master->base;
-       master->fsia.master     = master;
-       master->fsia.info       = &info->port_a;
-       fsi_handler_init(&master->fsia);
-       ret = fsi_stream_probe(&master->fsia, &pdev->dev);
+       pinfo           = (info) ? &info->port_a : &nul_info;
+       fsi             = &master->fsia;
+       fsi->base       = master->base;
+       fsi->master     = master;
+       fsi->info       = pinfo;
+       fsi_port_info_init(fsi, pinfo);
+       fsi_handler_init(fsi, pinfo);
+       ret = fsi_stream_probe(fsi, &pdev->dev);
        if (ret < 0) {
                dev_err(&pdev->dev, "FSIA stream probe failed\n");
                return ret;
        }
 
        /* FSI B setting */
-       master->fsib.base       = master->base + 0x40;
-       master->fsib.master     = master;
-       master->fsib.info       = &info->port_b;
-       fsi_handler_init(&master->fsib);
-       ret = fsi_stream_probe(&master->fsib, &pdev->dev);
+       pinfo           = (info) ? &info->port_b : &nul_info;
+       fsi             = &master->fsib;
+       fsi->base       = master->base + 0x40;
+       fsi->master     = master;
+       fsi->info       = pinfo;
+       fsi_port_info_init(fsi, pinfo);
+       fsi_handler_init(fsi, pinfo);
+       ret = fsi_stream_probe(fsi, &pdev->dev);
        if (ret < 0) {
                dev_err(&pdev->dev, "FSIB stream probe failed\n");
                goto exit_fsia;
@@ -1702,7 +2121,7 @@ static int fsi_probe(struct platform_device *pdev)
        pm_runtime_enable(&pdev->dev);
        dev_set_drvdata(&pdev->dev, master);
 
-       ret = request_irq(irq, &fsi_interrupt, 0,
+       ret = devm_request_irq(&pdev->dev, irq, &fsi_interrupt, 0,
                          id_entry->name, master);
        if (ret) {
                dev_err(&pdev->dev, "irq request err\n");
@@ -1712,7 +2131,7 @@ static int fsi_probe(struct platform_device *pdev)
        ret = snd_soc_register_platform(&pdev->dev, &fsi_soc_platform);
        if (ret < 0) {
                dev_err(&pdev->dev, "cannot snd soc register\n");
-               goto exit_free_irq;
+               goto exit_fsib;
        }
 
        ret = snd_soc_register_dais(&pdev->dev, fsi_soc_dai,
@@ -1726,8 +2145,6 @@ static int fsi_probe(struct platform_device *pdev)
 
 exit_snd_soc:
        snd_soc_unregister_platform(&pdev->dev);
-exit_free_irq:
-       free_irq(irq, master);
 exit_fsib:
        pm_runtime_disable(&pdev->dev);
        fsi_stream_remove(&master->fsib);
@@ -1743,7 +2160,6 @@ static int fsi_remove(struct platform_device *pdev)
 
        master = dev_get_drvdata(&pdev->dev);
 
-       free_irq(master->irq, master);
        pm_runtime_disable(&pdev->dev);
 
        snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(fsi_soc_dai));
@@ -1774,10 +2190,6 @@ static void __fsi_resume(struct fsi_priv *fsi,
                return;
 
        fsi_hw_startup(fsi, io, dev);
-
-       if (fsi_is_clk_master(fsi) && fsi->rate)
-               fsi_set_master_clk(dev, fsi, fsi->rate, 1);
-
        fsi_stream_start(fsi, io);
 }
 
index d1198627fc40397b772adad1104579c35842507f..10d21be383f6d511221094a1fa3a9a3b9657a464 100644 (file)
@@ -2786,8 +2786,9 @@ int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol,
        val = (ucontrol->value.integer.value[0] + min) & mask;
        val = val << shift;
 
-       if (snd_soc_update_bits_locked(codec, reg, val_mask, val))
-                       return err;
+       err = snd_soc_update_bits_locked(codec, reg, val_mask, val);
+       if (err < 0)
+               return err;
 
        if (snd_soc_volsw_is_stereo(mc)) {
                val_mask = mask << rshift;
index d0a4be38dc0f0473bdafe38d6b18ca30b11de61b..6e35bcae02df4b6a0e79709482a018f099615e21 100644 (file)
@@ -3745,7 +3745,7 @@ void snd_soc_dapm_shutdown(struct snd_soc_card *card)
 {
        struct snd_soc_codec *codec;
 
-       list_for_each_entry(codec, &card->codec_dev_list, list) {
+       list_for_each_entry(codec, &card->codec_dev_list, card_list) {
                soc_dapm_shutdown_codec(&codec->dapm);
                if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY)
                        snd_soc_dapm_set_bias_level(&codec->dapm,
index bbc125748a3843decc6ffd04d171fcf6f6b9fc5c..111b7d921e890c0051444b1a28fb6edfe78fd837 100644 (file)
@@ -317,3 +317,5 @@ int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream)
        return 0;
 }
 EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close);
+
+MODULE_LICENSE("GPL");
index 356611d9654db90e1f0206995de6b7064b83bdf9..54f7e25b6f7d479d30bed372ba5d12ce1abacb22 100644 (file)
@@ -57,6 +57,20 @@ static struct snd_soc_card mop500_card = {
        .num_links = ARRAY_SIZE(mop500_dai_links),
 };
 
+static void mop500_of_node_put(void)
+{
+       int i;
+
+       for (i = 0; i < 2; i++) {
+               if (mop500_dai_links[i].cpu_of_node)
+                       of_node_put((struct device_node *)
+                               mop500_dai_links[i].cpu_of_node);
+               if (mop500_dai_links[i].codec_of_node)
+                       of_node_put((struct device_node *)
+                               mop500_dai_links[i].codec_of_node);
+       }
+}
+
 static int __devinit mop500_of_probe(struct platform_device *pdev,
                                struct device_node *np)
 {
@@ -69,6 +83,7 @@ static int __devinit mop500_of_probe(struct platform_device *pdev,
 
        if (!(msp_np[0] && msp_np[1] && codec_np)) {
                dev_err(&pdev->dev, "Phandle missing or invalid\n");
+               mop500_of_node_put();
                return -EINVAL;
        }
 
@@ -83,6 +98,7 @@ static int __devinit mop500_of_probe(struct platform_device *pdev,
 
        return 0;
 }
+
 static int __devinit mop500_probe(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
@@ -128,6 +144,7 @@ static int __devexit mop500_remove(struct platform_device *pdev)
 
        snd_soc_unregister_card(mop500_card);
        mop500_ab8500_remove(mop500_card);
+       mop500_of_node_put();
 
        return 0;
 }
index b7c996e77570bd527a0a92fd904276a40c44cd2b..a26c6bf0a29b2ad570050519b7e6c87e418e62a5 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/pinctrl/consumer.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
+#include <linux/io.h>
 #include <linux/of.h>
 
 #include <mach/hardware.h>
@@ -697,14 +698,11 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev,
                        platform_data = devm_kzalloc(&pdev->dev,
                                sizeof(struct msp_i2s_platform_data), GFP_KERNEL);
                        if (!platform_data)
-                               ret = -ENOMEM;
+                               return -ENOMEM;
                }
        } else
                if (!platform_data)
-                       ret = -EINVAL;
-
-       if (ret)
-               goto err_res;
+                       return -EINVAL;
 
        dev_dbg(&pdev->dev, "%s: Enter (name: %s, id: %d).\n", __func__,
                pdev->name, platform_data->id);
index 561bb74fd364ae388cb8dc2af548e014b0bb801b..dbf7999d18b4e7b300c0063f73aadf5dfa3f0f95 100644 (file)
@@ -339,7 +339,7 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
        }
 
        mutex_init(&chip->mutex);
-       mutex_init(&chip->shutdown_mutex);
+       init_rwsem(&chip->shutdown_rwsem);
        chip->index = idx;
        chip->dev = dev;
        chip->card = card;
@@ -559,9 +559,11 @@ static void snd_usb_audio_disconnect(struct usb_device *dev,
                return;
 
        card = chip->card;
-       mutex_lock(&register_mutex);
-       mutex_lock(&chip->shutdown_mutex);
+       down_write(&chip->shutdown_rwsem);
        chip->shutdown = 1;
+       up_write(&chip->shutdown_rwsem);
+
+       mutex_lock(&register_mutex);
        chip->num_interfaces--;
        if (chip->num_interfaces <= 0) {
                snd_card_disconnect(card);
@@ -582,11 +584,9 @@ static void snd_usb_audio_disconnect(struct usb_device *dev,
                        snd_usb_mixer_disconnect(p);
                }
                usb_chip[chip->index] = NULL;
-               mutex_unlock(&chip->shutdown_mutex);
                mutex_unlock(&register_mutex);
                snd_card_free_when_closed(card);
        } else {
-               mutex_unlock(&chip->shutdown_mutex);
                mutex_unlock(&register_mutex);
        }
 }
@@ -618,16 +618,20 @@ int snd_usb_autoresume(struct snd_usb_audio *chip)
 {
        int err = -ENODEV;
 
+       down_read(&chip->shutdown_rwsem);
        if (!chip->shutdown && !chip->probing)
                err = usb_autopm_get_interface(chip->pm_intf);
+       up_read(&chip->shutdown_rwsem);
 
        return err;
 }
 
 void snd_usb_autosuspend(struct snd_usb_audio *chip)
 {
+       down_read(&chip->shutdown_rwsem);
        if (!chip->shutdown && !chip->probing)
                usb_autopm_put_interface(chip->pm_intf);
+       up_read(&chip->shutdown_rwsem);
 }
 
 static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message)
index afa4f9e9b27a2673b1fc955d680859cb7f964f02..814cb357ff88235dd87f37425985602867e3f5d5 100644 (file)
@@ -126,6 +126,7 @@ struct snd_usb_substream {
        struct snd_usb_endpoint *sync_endpoint;
        unsigned long flags;
        bool need_setup_ep;             /* (re)configure EP at prepare? */
+       unsigned int speed;             /* USB_SPEED_XXX */
 
        u64 formats;                    /* format bitmasks (all or'ed) */
        unsigned int num_formats;               /* number of supported audio formats (list) */
index 7f78c6d782b079d621d007f7c757e7cfd93587c7..34de6f2faf6120b492eb65208b9c9805aafe44e3 100644 (file)
@@ -35,6 +35,7 @@
 
 #define EP_FLAG_ACTIVATED      0
 #define EP_FLAG_RUNNING                1
+#define EP_FLAG_STOPPING       2
 
 /*
  * snd_usb_endpoint is a model that abstracts everything related to an
@@ -502,10 +503,20 @@ static int wait_clear_urbs(struct snd_usb_endpoint *ep)
        if (alive)
                snd_printk(KERN_ERR "timeout: still %d active urbs on EP #%x\n",
                                        alive, ep->ep_num);
+       clear_bit(EP_FLAG_STOPPING, &ep->flags);
 
        return 0;
 }
 
+/* sync the pending stop operation;
+ * this function itself doesn't trigger the stop operation
+ */
+void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep)
+{
+       if (ep && test_bit(EP_FLAG_STOPPING, &ep->flags))
+               wait_clear_urbs(ep);
+}
+
 /*
  * unlink active urbs.
  */
@@ -918,6 +929,8 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep,
 
                if (wait)
                        wait_clear_urbs(ep);
+               else
+                       set_bit(EP_FLAG_STOPPING, &ep->flags);
        }
 }
 
index 6376ccf10fd470688daf103b37ff74bcf67af3ea..3d4c9705041ff5074c609dd2bfb303781a523c4e 100644 (file)
@@ -19,6 +19,7 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
 int  snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep);
 void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep,
                           int force, int can_sleep, int wait);
+void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep);
 int  snd_usb_endpoint_activate(struct snd_usb_endpoint *ep);
 int  snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep);
 void snd_usb_endpoint_free(struct list_head *head);
index c83f6143c0eb34d8f77f969e1928427458b4268a..eeefbce3873c11dc35a6e174c4ace79daeeaa8c1 100644 (file)
@@ -148,6 +148,7 @@ struct snd_usb_midi_out_endpoint {
                struct snd_usb_midi_out_endpoint* ep;
                struct snd_rawmidi_substream *substream;
                int active;
+               bool autopm_reference;
                uint8_t cable;          /* cable number << 4 */
                uint8_t state;
 #define STATE_UNKNOWN  0
@@ -1076,7 +1077,8 @@ static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream)
                return -ENXIO;
        }
        err = usb_autopm_get_interface(umidi->iface);
-       if (err < 0)
+       port->autopm_reference = err >= 0;
+       if (err < 0 && err != -EACCES)
                return -EIO;
        substream->runtime->private_data = port;
        port->state = STATE_UNKNOWN;
@@ -1087,9 +1089,11 @@ static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream)
 static int snd_usbmidi_output_close(struct snd_rawmidi_substream *substream)
 {
        struct snd_usb_midi* umidi = substream->rmidi->private_data;
+       struct usbmidi_out_port *port = substream->runtime->private_data;
 
        substream_open(substream, 0);
-       usb_autopm_put_interface(umidi->iface);
+       if (port->autopm_reference)
+               usb_autopm_put_interface(umidi->iface);
        return 0;
 }
 
index fe56c9da38e9e6c78cdd6706f09e9639d8a502ab..298070e8f2d4e354da19dbca3e3d704a7b799321 100644 (file)
@@ -287,25 +287,32 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int v
        unsigned char buf[2];
        int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1;
        int timeout = 10;
-       int err;
+       int idx = 0, err;
 
        err = snd_usb_autoresume(cval->mixer->chip);
        if (err < 0)
                return -EIO;
+       down_read(&chip->shutdown_rwsem);
        while (timeout-- > 0) {
+               if (chip->shutdown)
+                       break;
+               idx = snd_usb_ctrl_intf(chip) | (cval->id << 8);
                if (snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), request,
                                    USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-                                   validx, snd_usb_ctrl_intf(chip) | (cval->id << 8),
-                                   buf, val_len) >= val_len) {
+                                   validx, idx, buf, val_len) >= val_len) {
                        *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len));
-                       snd_usb_autosuspend(cval->mixer->chip);
-                       return 0;
+                       err = 0;
+                       goto out;
                }
        }
-       snd_usb_autosuspend(cval->mixer->chip);
        snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n",
-                   request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type);
-       return -EINVAL;
+                   request, validx, idx, cval->val_type);
+       err = -EINVAL;
+
+ out:
+       up_read(&chip->shutdown_rwsem);
+       snd_usb_autosuspend(cval->mixer->chip);
+       return err;
 }
 
 static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret)
@@ -313,7 +320,7 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v
        struct snd_usb_audio *chip = cval->mixer->chip;
        unsigned char buf[2 + 3*sizeof(__u16)]; /* enough space for one range */
        unsigned char *val;
-       int ret, size;
+       int idx = 0, ret, size;
        __u8 bRequest;
 
        if (request == UAC_GET_CUR) {
@@ -330,16 +337,22 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v
        if (ret)
                goto error;
 
-       ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest,
+       down_read(&chip->shutdown_rwsem);
+       if (chip->shutdown)
+               ret = -ENODEV;
+       else {
+               idx = snd_usb_ctrl_intf(chip) | (cval->id << 8);
+               ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest,
                              USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-                             validx, snd_usb_ctrl_intf(chip) | (cval->id << 8),
-                             buf, size);
+                             validx, idx, buf, size);
+       }
+       up_read(&chip->shutdown_rwsem);
        snd_usb_autosuspend(chip);
 
        if (ret < 0) {
 error:
                snd_printk(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n",
-                          request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type);
+                          request, validx, idx, cval->val_type);
                return ret;
        }
 
@@ -417,7 +430,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
 {
        struct snd_usb_audio *chip = cval->mixer->chip;
        unsigned char buf[2];
-       int val_len, err, timeout = 10;
+       int idx = 0, val_len, err, timeout = 10;
 
        if (cval->mixer->protocol == UAC_VERSION_1) {
                val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1;
@@ -440,19 +453,27 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
        err = snd_usb_autoresume(chip);
        if (err < 0)
                return -EIO;
-       while (timeout-- > 0)
+       down_read(&chip->shutdown_rwsem);
+       while (timeout-- > 0) {
+               if (chip->shutdown)
+                       break;
+               idx = snd_usb_ctrl_intf(chip) | (cval->id << 8);
                if (snd_usb_ctl_msg(chip->dev,
                                    usb_sndctrlpipe(chip->dev, 0), request,
                                    USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
-                                   validx, snd_usb_ctrl_intf(chip) | (cval->id << 8),
-                                   buf, val_len) >= 0) {
-                       snd_usb_autosuspend(chip);
-                       return 0;
+                                   validx, idx, buf, val_len) >= 0) {
+                       err = 0;
+                       goto out;
                }
-       snd_usb_autosuspend(chip);
+       }
        snd_printdd(KERN_ERR "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n",
-                   request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type, buf[0], buf[1]);
-       return -EINVAL;
+                   request, validx, idx, cval->val_type, buf[0], buf[1]);
+       err = -EINVAL;
+
+ out:
+       up_read(&chip->shutdown_rwsem);
+       snd_usb_autosuspend(chip);
+       return err;
 }
 
 static int set_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int value)
index 690000db0ec01bb97e215f1b8470bd278a544ebd..ae2b7143522097bffd2a6060721d4f3db6b8000e 100644 (file)
@@ -283,6 +283,11 @@ static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e
        if (value > 1)
                return -EINVAL;
        changed = value != mixer->audigy2nx_leds[index];
+       down_read(&mixer->chip->shutdown_rwsem);
+       if (mixer->chip->shutdown) {
+               err = -ENODEV;
+               goto out;
+       }
        if (mixer->chip->usb_id == USB_ID(0x041e, 0x3042))
                err = snd_usb_ctl_msg(mixer->chip->dev,
                              usb_sndctrlpipe(mixer->chip->dev, 0), 0x24,
@@ -299,6 +304,8 @@ static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e
                              usb_sndctrlpipe(mixer->chip->dev, 0), 0x24,
                              USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
                              value, index + 2, NULL, 0);
+ out:
+       up_read(&mixer->chip->shutdown_rwsem);
        if (err < 0)
                return err;
        mixer->audigy2nx_leds[index] = value;
@@ -392,11 +399,16 @@ static void snd_audigy2nx_proc_read(struct snd_info_entry *entry,
 
        for (i = 0; jacks[i].name; ++i) {
                snd_iprintf(buffer, "%s: ", jacks[i].name);
-               err = snd_usb_ctl_msg(mixer->chip->dev,
+               down_read(&mixer->chip->shutdown_rwsem);
+               if (mixer->chip->shutdown)
+                       err = 0;
+               else
+                       err = snd_usb_ctl_msg(mixer->chip->dev,
                                      usb_rcvctrlpipe(mixer->chip->dev, 0),
                                      UAC_GET_MEM, USB_DIR_IN | USB_TYPE_CLASS |
                                      USB_RECIP_INTERFACE, 0,
                                      jacks[i].unitid << 8, buf, 3);
+               up_read(&mixer->chip->shutdown_rwsem);
                if (err == 3 && (buf[0] == 3 || buf[0] == 6))
                        snd_iprintf(buffer, "%02x %02x\n", buf[1], buf[2]);
                else
@@ -426,10 +438,15 @@ static int snd_xonar_u1_switch_put(struct snd_kcontrol *kcontrol,
        else
                new_status = old_status & ~0x02;
        changed = new_status != old_status;
-       err = snd_usb_ctl_msg(mixer->chip->dev,
+       down_read(&mixer->chip->shutdown_rwsem);
+       if (mixer->chip->shutdown)
+               err = -ENODEV;
+       else
+               err = snd_usb_ctl_msg(mixer->chip->dev,
                              usb_sndctrlpipe(mixer->chip->dev, 0), 0x08,
                              USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
                              50, 0, &new_status, 1);
+       up_read(&mixer->chip->shutdown_rwsem);
        if (err < 0)
                return err;
        mixer->xonar_u1_status = new_status;
@@ -468,11 +485,17 @@ static int snd_nativeinstruments_control_get(struct snd_kcontrol *kcontrol,
        u8 bRequest = (kcontrol->private_value >> 16) & 0xff;
        u16 wIndex = kcontrol->private_value & 0xffff;
        u8 tmp;
+       int ret;
 
-       int ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), bRequest,
+       down_read(&mixer->chip->shutdown_rwsem);
+       if (mixer->chip->shutdown)
+               ret = -ENODEV;
+       else
+               ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), bRequest,
                                  USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
                                  0, cpu_to_le16(wIndex),
                                  &tmp, sizeof(tmp), 1000);
+       up_read(&mixer->chip->shutdown_rwsem);
 
        if (ret < 0) {
                snd_printk(KERN_ERR
@@ -493,11 +516,17 @@ static int snd_nativeinstruments_control_put(struct snd_kcontrol *kcontrol,
        u8 bRequest = (kcontrol->private_value >> 16) & 0xff;
        u16 wIndex = kcontrol->private_value & 0xffff;
        u16 wValue = ucontrol->value.integer.value[0];
+       int ret;
 
-       int ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), bRequest,
+       down_read(&mixer->chip->shutdown_rwsem);
+       if (mixer->chip->shutdown)
+               ret = -ENODEV;
+       else
+               ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), bRequest,
                                  USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
                                  cpu_to_le16(wValue), cpu_to_le16(wIndex),
                                  NULL, 0, 1000);
+       up_read(&mixer->chip->shutdown_rwsem);
 
        if (ret < 0) {
                snd_printk(KERN_ERR
@@ -656,11 +685,16 @@ static int snd_ftu_eff_switch_get(struct snd_kcontrol *kctl,
                return -EINVAL;
 
 
-       err = snd_usb_ctl_msg(chip->dev,
+       down_read(&mixer->chip->shutdown_rwsem);
+       if (mixer->chip->shutdown)
+               err = -ENODEV;
+       else
+               err = snd_usb_ctl_msg(chip->dev,
                        usb_rcvctrlpipe(chip->dev, 0), UAC_GET_CUR,
                        USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
                        validx << 8, snd_usb_ctrl_intf(chip) | (id << 8),
                        value, val_len);
+       up_read(&mixer->chip->shutdown_rwsem);
        if (err < 0)
                return err;
 
@@ -703,11 +737,16 @@ static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl,
 
        if (!pval->is_cached) {
                /* Read current value */
-               err = snd_usb_ctl_msg(chip->dev,
+               down_read(&mixer->chip->shutdown_rwsem);
+               if (mixer->chip->shutdown)
+                       err = -ENODEV;
+               else
+                       err = snd_usb_ctl_msg(chip->dev,
                                usb_rcvctrlpipe(chip->dev, 0), UAC_GET_CUR,
                                USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
                                validx << 8, snd_usb_ctrl_intf(chip) | (id << 8),
                                value, val_len);
+               up_read(&mixer->chip->shutdown_rwsem);
                if (err < 0)
                        return err;
 
@@ -719,11 +758,16 @@ static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl,
        if (cur_val != new_val) {
                value[0] = new_val;
                value[1] = 0;
-               err = snd_usb_ctl_msg(chip->dev,
+               down_read(&mixer->chip->shutdown_rwsem);
+               if (mixer->chip->shutdown)
+                       err = -ENODEV;
+               else
+                       err = snd_usb_ctl_msg(chip->dev,
                                usb_sndctrlpipe(chip->dev, 0), UAC_SET_CUR,
                                USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
                                validx << 8, snd_usb_ctrl_intf(chip) | (id << 8),
                                value, val_len);
+               up_read(&mixer->chip->shutdown_rwsem);
                if (err < 0)
                        return err;
 
index 55e19e1b80ec4eeb282c91cea482ef7434cf8dce..ef6fa24fc473b08a89dd33ef8158f004185f54cb 100644 (file)
@@ -71,6 +71,8 @@ static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream
        unsigned int hwptr_done;
 
        subs = (struct snd_usb_substream *)substream->runtime->private_data;
+       if (subs->stream->chip->shutdown)
+               return SNDRV_PCM_POS_XRUN;
        spin_lock(&subs->lock);
        hwptr_done = subs->hwptr_done;
        substream->runtime->delay = snd_usb_pcm_delay(subs,
@@ -444,7 +446,6 @@ static int configure_endpoint(struct snd_usb_substream *subs)
 {
        int ret;
 
-       mutex_lock(&subs->stream->chip->shutdown_mutex);
        /* format changed */
        stop_endpoints(subs, 0, 0, 0);
        ret = snd_usb_endpoint_set_params(subs->data_endpoint,
@@ -455,19 +456,16 @@ static int configure_endpoint(struct snd_usb_substream *subs)
                                          subs->cur_audiofmt,
                                          subs->sync_endpoint);
        if (ret < 0)
-               goto unlock;
+               return ret;
 
        if (subs->sync_endpoint)
-               ret = snd_usb_endpoint_set_params(subs->data_endpoint,
+               ret = snd_usb_endpoint_set_params(subs->sync_endpoint,
                                                  subs->pcm_format,
                                                  subs->channels,
                                                  subs->period_bytes,
                                                  subs->cur_rate,
                                                  subs->cur_audiofmt,
                                                  NULL);
-
-unlock:
-       mutex_unlock(&subs->stream->chip->shutdown_mutex);
        return ret;
 }
 
@@ -505,7 +503,13 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
                return -EINVAL;
        }
 
-       if ((ret = set_format(subs, fmt)) < 0)
+       down_read(&subs->stream->chip->shutdown_rwsem);
+       if (subs->stream->chip->shutdown)
+               ret = -ENODEV;
+       else
+               ret = set_format(subs, fmt);
+       up_read(&subs->stream->chip->shutdown_rwsem);
+       if (ret < 0)
                return ret;
 
        subs->interface = fmt->iface;
@@ -527,10 +531,12 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream)
        subs->cur_audiofmt = NULL;
        subs->cur_rate = 0;
        subs->period_bytes = 0;
-       mutex_lock(&subs->stream->chip->shutdown_mutex);
-       stop_endpoints(subs, 0, 1, 1);
-       deactivate_endpoints(subs);
-       mutex_unlock(&subs->stream->chip->shutdown_mutex);
+       down_read(&subs->stream->chip->shutdown_rwsem);
+       if (!subs->stream->chip->shutdown) {
+               stop_endpoints(subs, 0, 1, 1);
+               deactivate_endpoints(subs);
+       }
+       up_read(&subs->stream->chip->shutdown_rwsem);
        return snd_pcm_lib_free_vmalloc_buffer(substream);
 }
 
@@ -552,12 +558,22 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
                return -ENXIO;
        }
 
-       if (snd_BUG_ON(!subs->data_endpoint))
-               return -EIO;
+       down_read(&subs->stream->chip->shutdown_rwsem);
+       if (subs->stream->chip->shutdown) {
+               ret = -ENODEV;
+               goto unlock;
+       }
+       if (snd_BUG_ON(!subs->data_endpoint)) {
+               ret = -EIO;
+               goto unlock;
+       }
+
+       snd_usb_endpoint_sync_pending_stop(subs->sync_endpoint);
+       snd_usb_endpoint_sync_pending_stop(subs->data_endpoint);
 
        ret = set_format(subs, subs->cur_audiofmt);
        if (ret < 0)
-               return ret;
+               goto unlock;
 
        iface = usb_ifnum_to_if(subs->dev, subs->cur_audiofmt->iface);
        alts = &iface->altsetting[subs->cur_audiofmt->altset_idx];
@@ -567,12 +583,12 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
                                       subs->cur_audiofmt,
                                       subs->cur_rate);
        if (ret < 0)
-               return ret;
+               goto unlock;
 
        if (subs->need_setup_ep) {
                ret = configure_endpoint(subs);
                if (ret < 0)
-                       return ret;
+                       goto unlock;
                subs->need_setup_ep = false;
        }
 
@@ -592,9 +608,11 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
        /* for playback, submit the URBs now; otherwise, the first hwptr_done
         * updates for all URBs would happen at the same time when starting */
        if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK)
-               return start_endpoints(subs, 1);
+               ret = start_endpoints(subs, 1);
 
-       return 0;
+ unlock:
+       up_read(&subs->stream->chip->shutdown_rwsem);
+       return ret;
 }
 
 static struct snd_pcm_hardware snd_usb_hardware =
@@ -647,7 +665,7 @@ static int hw_check_valid_format(struct snd_usb_substream *subs,
                return 0;
        }
        /* check whether the period time is >= the data packet interval */
-       if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL) {
+       if (subs->speed != USB_SPEED_FULL) {
                ptime = 125 * (1 << fp->datainterval);
                if (ptime > pt->max || (ptime == pt->max && pt->openmax)) {
                        hwc_debug("   > check: ptime %u > max %u\n", ptime, pt->max);
@@ -925,7 +943,7 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
                return err;
 
        param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME;
-       if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL)
+       if (subs->speed == USB_SPEED_FULL)
                /* full speed devices have fixed data packet interval */
                ptmin = 1000;
        if (ptmin == 1000)
index ebc1a5b5b3f1ba79c4c25ea66aadd34fd053e6d6..d218f763501fcdb9c4d038826a4bb12b14e4197b 100644 (file)
@@ -108,7 +108,7 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s
                        }
                        snd_iprintf(buffer, "\n");
                }
-               if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL)
+               if (subs->speed != USB_SPEED_FULL)
                        snd_iprintf(buffer, "    Data packet interval: %d us\n",
                                    125 * (1 << fp->datainterval));
                // snd_iprintf(buffer, "    Max Packet Size = %d\n", fp->maxpacksize);
@@ -124,7 +124,7 @@ static void proc_dump_ep_status(struct snd_usb_substream *subs,
                return;
        snd_iprintf(buffer, "    Packet Size = %d\n", ep->curpacksize);
        snd_iprintf(buffer, "    Momentary freq = %u Hz (%#x.%04x)\n",
-                   snd_usb_get_speed(subs->dev) == USB_SPEED_FULL
+                   subs->speed == USB_SPEED_FULL
                    ? get_full_speed_hz(ep->freqm)
                    : get_high_speed_hz(ep->freqm),
                    ep->freqm >> 16, ep->freqm & 0xffff);
index 083ed81160e58b094ee8f4fca637371aa5b5fff4..1de0c8c002a8a2d35bc80e7de9a9c764a5945fc2 100644 (file)
@@ -90,6 +90,7 @@ static void snd_usb_init_substream(struct snd_usb_stream *as,
        subs->direction = stream;
        subs->dev = as->chip->dev;
        subs->txfr_quirk = as->chip->txfr_quirk;
+       subs->speed = snd_usb_get_speed(subs->dev);
 
        snd_usb_set_pcm_ops(as->pcm, stream);
 
index b8233ebe250f88648cc0baf2f6cfcfd13aa6de8f..ef42797f56fb56adf950eef3b764c5533263a8d9 100644 (file)
@@ -37,7 +37,7 @@ struct snd_usb_audio {
        struct usb_interface *pm_intf;
        u32 usb_id;
        struct mutex mutex;
-       struct mutex shutdown_mutex;
+       struct rw_semaphore shutdown_rwsem;
        unsigned int shutdown:1;
        unsigned int probing:1;
        unsigned int autosuspended:1;   
index 411ee5664e98e1e765bf992f379c16ec30569585..178b88ae3d2f174a5a085f233163d54cef152337 100644 (file)
@@ -414,7 +414,7 @@ static int show_html_page(const char *perf_cmd)
 int cmd_help(int argc, const char **argv, const char *prefix __maybe_unused)
 {
        bool show_all = false;
-       enum help_format help_format = HELP_FORMAT_NONE;
+       enum help_format help_format = HELP_FORMAT_MAN;
        struct option builtin_help_options[] = {
        OPT_BOOLEAN('a', "all", &show_all, "print all available commands"),
        OPT_SET_UINT('m', "man", &help_format, "show man page", HELP_FORMAT_MAN),
index dec8ced61fb00c2bc7114346db3edaf0f7dd89b7..7aaee39f6774f1fc49131dd7a3d67f002bee823c 100644 (file)
@@ -56,6 +56,10 @@ static int trace__read_syscall_info(struct trace *trace, int id)
 {
        char tp_name[128];
        struct syscall *sc;
+       const char *name = audit_syscall_to_name(id, trace->audit_machine);
+
+       if (name == NULL)
+               return -1;
 
        if (id > trace->syscalls.max) {
                struct syscall *nsyscalls = realloc(trace->syscalls.table, (id + 1) * sizeof(*sc));
@@ -75,11 +79,8 @@ static int trace__read_syscall_info(struct trace *trace, int id)
        }
 
        sc = trace->syscalls.table + id;
-       sc->name = audit_syscall_to_name(id, trace->audit_machine);
-       if (sc->name == NULL)
-               return -1;
-
-       sc->fmt = syscall_fmt__find(sc->name);
+       sc->name = name;
+       sc->fmt  = syscall_fmt__find(sc->name);
 
        snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name);
        sc->tp_format = event_format__new("syscalls", tp_name);
@@ -267,6 +268,13 @@ again:
                        if (evlist->threads->map[0] == -1 || evlist->threads->nr > 1)
                                printf("%d ", sample.tid);
 
+                       if (sample.raw_data == NULL) {
+                               printf("%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",
+                                      perf_evsel__name(evsel), sample.tid,
+                                      sample.cpu, sample.raw_size);
+                               continue;
+                       }
+
                        handler = evsel->handler.func;
                        handler(trace, evsel, &sample);
                }
index 28c18d1d52c3efceeb2847a1b68bd3dd000d45b6..516ecd9ddd6ee275c1e3144abc8a3d091b6114bb 100644 (file)
@@ -513,7 +513,8 @@ static int test__group1(struct perf_evlist *evlist)
        TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
        TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
        TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
-       TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
+       /* use of precise requires exclude_guest */
+       TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
        TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
        TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 2);
        TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
@@ -599,7 +600,8 @@ static int test__group3(struct perf_evlist *evlist __maybe_unused)
        TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
        TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
        TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
-       TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
+       /* use of precise requires exclude_guest */
+       TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
        TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
        TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 3);
        TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
@@ -662,7 +664,8 @@ static int test__group4(struct perf_evlist *evlist __maybe_unused)
        TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
        TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
        TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
-       TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
+       /* use of precise requires exclude_guest */
+       TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
        TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
        TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 1);
        TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
@@ -676,7 +679,8 @@ static int test__group4(struct perf_evlist *evlist __maybe_unused)
        TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
        TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
        TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
-       TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
+       /* use of precise requires exclude_guest */
+       TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
        TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
        TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 2);
        TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
index fb4b7ea6752fd86121a968fa77212727f603d7e9..8b3e5939afb6ea00ef6cd74275eae99f35de0c25 100644 (file)
@@ -39,7 +39,6 @@ int thread__set_comm(struct thread *self, const char *comm)
        err = self->comm == NULL ? -ENOMEM : 0;
        if (!err) {
                self->comm_set = true;
-               map_groups__flush(&self->mg);
        }
        return err;
 }
index 2655ae9a3ad8d9e6f7676006336a5e3b8fec99d1..ea095abbe97e7cc7bec26c575a1d177dc1e2c61d 100644 (file)
@@ -206,8 +206,10 @@ int get_msr(int cpu, off_t offset, unsigned long long *msr)
        retval = pread(fd, msr, sizeof *msr, offset);
        close(fd);
 
-       if (retval != sizeof *msr)
+       if (retval != sizeof *msr) {
+               fprintf(stderr, "%s offset 0x%zx read failed\n", pathname, offset);
                return -1;
+       }
 
        return 0;
 }
@@ -1101,7 +1103,9 @@ void turbostat_loop()
 
 restart:
        retval = for_all_cpus(get_counters, EVEN_COUNTERS);
-       if (retval) {
+       if (retval < -1) {
+               exit(retval);
+       } else if (retval == -1) {
                re_initialize();
                goto restart;
        }
@@ -1114,7 +1118,9 @@ restart:
                }
                sleep(interval_sec);
                retval = for_all_cpus(get_counters, ODD_COUNTERS);
-               if (retval) {
+               if (retval < -1) {
+                       exit(retval);
+               } else if (retval == -1) {
                        re_initialize();
                        goto restart;
                }
@@ -1126,7 +1132,9 @@ restart:
                flush_stdout();
                sleep(interval_sec);
                retval = for_all_cpus(get_counters, EVEN_COUNTERS);
-               if (retval) {
+               if (retval < -1) {
+                       exit(retval);
+               } else if (retval == -1) {
                        re_initialize();
                        goto restart;
                }
@@ -1545,8 +1553,11 @@ void turbostat_init()
 int fork_it(char **argv)
 {
        pid_t child_pid;
+       int status;
 
-       for_all_cpus(get_counters, EVEN_COUNTERS);
+       status = for_all_cpus(get_counters, EVEN_COUNTERS);
+       if (status)
+               exit(status);
        /* clear affinity side-effect of get_counters() */
        sched_setaffinity(0, cpu_present_setsize, cpu_present_set);
        gettimeofday(&tv_even, (struct timezone *)NULL);
@@ -1556,7 +1567,6 @@ int fork_it(char **argv)
                /* child */
                execvp(argv[0], argv);
        } else {
-               int status;
 
                /* parent */
                if (child_pid == -1) {
@@ -1568,7 +1578,7 @@ int fork_it(char **argv)
                signal(SIGQUIT, SIG_IGN);
                if (waitpid(child_pid, &status, 0) == -1) {
                        perror("wait");
-                       exit(1);
+                       exit(status);
                }
        }
        /*
@@ -1585,7 +1595,7 @@ int fork_it(char **argv)
 
        fprintf(stderr, "%.6f sec\n", tv_delta.tv_sec + tv_delta.tv_usec/1000000.0);
 
-       return 0;
+       return status;
 }
 
 void cmdline(int argc, char **argv)
@@ -1594,7 +1604,7 @@ void cmdline(int argc, char **argv)
 
        progname = argv[0];
 
-       while ((opt = getopt(argc, argv, "+pPSvisc:sC:m:M:")) != -1) {
+       while ((opt = getopt(argc, argv, "+pPSvi:sc:sC:m:M:")) != -1) {
                switch (opt) {
                case 'p':
                        show_core_only++;
index b51d787176d323bb3a2d6f0016b2d2cf4db16d3d..c7ba7614061b22f04d78b5d60e3669dd8767fbed 100755 (executable)
@@ -1740,8 +1740,10 @@ sub install {
     open(IN, "$output_config") or dodie("Can't read config file");
     while (<IN>) {
        if (/CONFIG_MODULES(=y)?/) {
-           $install_mods = 1 if (defined($1));
-           last;
+           if (defined($1)) {
+               $install_mods = 1;
+               last;
+           }
        }
     }
     close(IN);
index 43480149119ee773f0a32cc8abe995903609fd11..85baf11e2acd7d11aa4990a0f7f53f8d28689a20 100644 (file)
@@ -1,4 +1,4 @@
-TARGETS = breakpoints kcmp mqueue vm cpu-hotplug memory-hotplug epoll
+TARGETS = breakpoints kcmp mqueue vm cpu-hotplug memory-hotplug
 
 all:
        for TARGET in $(TARGETS); do \
diff --git a/tools/testing/selftests/epoll/Makefile b/tools/testing/selftests/epoll/Makefile
deleted file mode 100644 (file)
index 19806ed..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-# Makefile for epoll selftests
-
-all: test_epoll
-%: %.c
-       gcc -pthread -g -o $@ $^
-
-run_tests: all
-       ./test_epoll
-
-clean:
-       $(RM) test_epoll
diff --git a/tools/testing/selftests/epoll/test_epoll.c b/tools/testing/selftests/epoll/test_epoll.c
deleted file mode 100644 (file)
index e0fcff1..0000000
+++ /dev/null
@@ -1,344 +0,0 @@
-/*
- *  tools/testing/selftests/epoll/test_epoll.c
- *
- *  Copyright 2012 Adobe Systems Incorporated
- *
- *  This program is free software; you can redistribute 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.
- *
- *  Paton J. Lewis <palewis@adobe.com>
- *
- */
-
-#include <errno.h>
-#include <fcntl.h>
-#include <pthread.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/epoll.h>
-#include <sys/socket.h>
-
-/*
- * A pointer to an epoll_item_private structure will be stored in the epoll
- * item's event structure so that we can get access to the epoll_item_private
- * data after calling epoll_wait:
- */
-struct epoll_item_private {
-       int index;  /* Position of this struct within the epoll_items array. */
-       int fd;
-       uint32_t events;
-       pthread_mutex_t mutex;  /* Guards the following variables... */
-       int stop;
-       int status;  /* Stores any error encountered while handling item. */
-       /* The following variable allows us to test whether we have encountered
-          a problem while attempting to cancel and delete the associated
-          event. When the test program exits, 'deleted' should be exactly
-          one. If it is greater than one, then the failed test reflects a real
-          world situation where we would have tried to access the epoll item's
-          private data after deleting it: */
-       int deleted;
-};
-
-struct epoll_item_private *epoll_items;
-
-/*
- * Delete the specified item from the epoll set. In a real-world secneario this
- * is where we would free the associated data structure, but in this testing
- * environment we retain the structure so that we can test for double-deletion:
- */
-void delete_item(int index)
-{
-       __sync_fetch_and_add(&epoll_items[index].deleted, 1);
-}
-
-/*
- * A pointer to a read_thread_data structure will be passed as the argument to
- * each read thread:
- */
-struct read_thread_data {
-       int stop;
-       int status;  /* Indicates any error encountered by the read thread. */
-       int epoll_set;
-};
-
-/*
- * The function executed by the read threads:
- */
-void *read_thread_function(void *function_data)
-{
-       struct read_thread_data *thread_data =
-               (struct read_thread_data *)function_data;
-       struct epoll_event event_data;
-       struct epoll_item_private *item_data;
-       char socket_data;
-
-       /* Handle events until we encounter an error or this thread's 'stop'
-          condition is set: */
-       while (1) {
-               int result = epoll_wait(thread_data->epoll_set,
-                                       &event_data,
-                                       1,      /* Number of desired events */
-                                       1000);  /* Timeout in ms */
-               if (result < 0) {
-                       /* Breakpoints signal all threads. Ignore that while
-                          debugging: */
-                       if (errno == EINTR)
-                               continue;
-                       thread_data->status = errno;
-                       return 0;
-               } else if (thread_data->stop)
-                       return 0;
-               else if (result == 0)  /* Timeout */
-                       continue;
-
-               /* We need the mutex here because checking for the stop
-                  condition and re-enabling the epoll item need to be done
-                  together as one atomic operation when EPOLL_CTL_DISABLE is
-                  available: */
-               item_data = (struct epoll_item_private *)event_data.data.ptr;
-               pthread_mutex_lock(&item_data->mutex);
-
-               /* Remove the item from the epoll set if we want to stop
-                  handling that event: */
-               if (item_data->stop)
-                       delete_item(item_data->index);
-               else {
-                       /* Clear the data that was written to the other end of
-                          our non-blocking socket: */
-                       do {
-                               if (read(item_data->fd, &socket_data, 1) < 1) {
-                                       if ((errno == EAGAIN) ||
-                                           (errno == EWOULDBLOCK))
-                                               break;
-                                       else
-                                               goto error_unlock;
-                               }
-                       } while (item_data->events & EPOLLET);
-
-                       /* The item was one-shot, so re-enable it: */
-                       event_data.events = item_data->events;
-                       if (epoll_ctl(thread_data->epoll_set,
-                                                 EPOLL_CTL_MOD,
-                                                 item_data->fd,
-                                                 &event_data) < 0)
-                               goto error_unlock;
-               }
-
-               pthread_mutex_unlock(&item_data->mutex);
-       }
-
-error_unlock:
-       thread_data->status = item_data->status = errno;
-       pthread_mutex_unlock(&item_data->mutex);
-       return 0;
-}
-
-/*
- * A pointer to a write_thread_data structure will be passed as the argument to
- * the write thread:
- */
-struct write_thread_data {
-       int stop;
-       int status;  /* Indicates any error encountered by the write thread. */
-       int n_fds;
-       int *fds;
-};
-
-/*
- * The function executed by the write thread. It writes a single byte to each
- * socket in turn until the stop condition for this thread is set. If writing to
- * a socket would block (i.e. errno was EAGAIN), we leave that socket alone for
- * the moment and just move on to the next socket in the list. We don't care
- * about the order in which we deliver events to the epoll set. In fact we don't
- * care about the data we're writing to the pipes at all; we just want to
- * trigger epoll events:
- */
-void *write_thread_function(void *function_data)
-{
-       const char data = 'X';
-       int index;
-       struct write_thread_data *thread_data =
-               (struct write_thread_data *)function_data;
-       while (!write_thread_data->stop)
-               for (index = 0;
-                    !thread_data->stop && (index < thread_data->n_fds);
-                    ++index)
-                       if ((write(thread_data->fds[index], &data, 1) < 1) &&
-                               (errno != EAGAIN) &&
-                               (errno != EWOULDBLOCK)) {
-                               write_thread_data->status = errno;
-                               return;
-                       }
-}
-
-/*
- * Arguments are currently ignored:
- */
-int main(int argc, char **argv)
-{
-       const int n_read_threads = 100;
-       const int n_epoll_items = 500;
-       int index;
-       int epoll_set = epoll_create1(0);
-       struct write_thread_data write_thread_data = {
-               0, 0, n_epoll_items, malloc(n_epoll_items * sizeof(int))
-       };
-       struct read_thread_data *read_thread_data =
-               malloc(n_read_threads * sizeof(struct read_thread_data));
-       pthread_t *read_threads = malloc(n_read_threads * sizeof(pthread_t));
-       pthread_t write_thread;
-
-       printf("-----------------\n");
-       printf("Runing test_epoll\n");
-       printf("-----------------\n");
-
-       epoll_items = malloc(n_epoll_items * sizeof(struct epoll_item_private));
-
-       if (epoll_set < 0 || epoll_items == 0 || write_thread_data.fds == 0 ||
-               read_thread_data == 0 || read_threads == 0)
-               goto error;
-
-       if (sysconf(_SC_NPROCESSORS_ONLN) < 2) {
-               printf("Error: please run this test on a multi-core system.\n");
-               goto error;
-       }
-
-       /* Create the socket pairs and epoll items: */
-       for (index = 0; index < n_epoll_items; ++index) {
-               int socket_pair[2];
-               struct epoll_event event_data;
-               if (socketpair(AF_UNIX,
-                              SOCK_STREAM | SOCK_NONBLOCK,
-                              0,
-                              socket_pair) < 0)
-                       goto error;
-               write_thread_data.fds[index] = socket_pair[0];
-               epoll_items[index].index = index;
-               epoll_items[index].fd = socket_pair[1];
-               if (pthread_mutex_init(&epoll_items[index].mutex, NULL) != 0)
-                       goto error;
-               /* We always use EPOLLONESHOT because this test is currently
-                  structured to demonstrate the need for EPOLL_CTL_DISABLE,
-                  which only produces useful information in the EPOLLONESHOT
-                  case (without EPOLLONESHOT, calling epoll_ctl with
-                  EPOLL_CTL_DISABLE will never return EBUSY). If support for
-                  testing events without EPOLLONESHOT is desired, it should
-                  probably be implemented in a separate unit test. */
-               epoll_items[index].events = EPOLLIN | EPOLLONESHOT;
-               if (index < n_epoll_items / 2)
-                       epoll_items[index].events |= EPOLLET;
-               epoll_items[index].stop = 0;
-               epoll_items[index].status = 0;
-               epoll_items[index].deleted = 0;
-               event_data.events = epoll_items[index].events;
-               event_data.data.ptr = &epoll_items[index];
-               if (epoll_ctl(epoll_set,
-                             EPOLL_CTL_ADD,
-                             epoll_items[index].fd,
-                             &event_data) < 0)
-                       goto error;
-       }
-
-       /* Create and start the read threads: */
-       for (index = 0; index < n_read_threads; ++index) {
-               read_thread_data[index].stop = 0;
-               read_thread_data[index].status = 0;
-               read_thread_data[index].epoll_set = epoll_set;
-               if (pthread_create(&read_threads[index],
-                                  NULL,
-                                  read_thread_function,
-                                  &read_thread_data[index]) != 0)
-                       goto error;
-       }
-
-       if (pthread_create(&write_thread,
-                          NULL,
-                          write_thread_function,
-                          &write_thread_data) != 0)
-               goto error;
-
-       /* Cancel all event pollers: */
-#ifdef EPOLL_CTL_DISABLE
-       for (index = 0; index < n_epoll_items; ++index) {
-               pthread_mutex_lock(&epoll_items[index].mutex);
-               ++epoll_items[index].stop;
-               if (epoll_ctl(epoll_set,
-                             EPOLL_CTL_DISABLE,
-                             epoll_items[index].fd,
-                             NULL) == 0)
-                       delete_item(index);
-               else if (errno != EBUSY) {
-                       pthread_mutex_unlock(&epoll_items[index].mutex);
-                       goto error;
-               }
-               /* EBUSY means events were being handled; allow the other thread
-                  to delete the item. */
-               pthread_mutex_unlock(&epoll_items[index].mutex);
-       }
-#else
-       for (index = 0; index < n_epoll_items; ++index) {
-               pthread_mutex_lock(&epoll_items[index].mutex);
-               ++epoll_items[index].stop;
-               pthread_mutex_unlock(&epoll_items[index].mutex);
-               /* Wait in case a thread running read_thread_function is
-                  currently executing code between epoll_wait and
-                  pthread_mutex_lock with this item. Note that a longer delay
-                  would make double-deletion less likely (at the expense of
-                  performance), but there is no guarantee that any delay would
-                  ever be sufficient. Note also that we delete all event
-                  pollers at once for testing purposes, but in a real-world
-                  environment we are likely to want to be able to cancel event
-                  pollers at arbitrary times. Therefore we can't improve this
-                  situation by just splitting this loop into two loops
-                  (i.e. signal 'stop' for all items, sleep, and then delete all
-                  items). We also can't fix the problem via EPOLL_CTL_DEL
-                  because that command can't prevent the case where some other
-                  thread is executing read_thread_function within the region
-                  mentioned above: */
-               usleep(1);
-               pthread_mutex_lock(&epoll_items[index].mutex);
-               if (!epoll_items[index].deleted)
-                       delete_item(index);
-               pthread_mutex_unlock(&epoll_items[index].mutex);
-       }
-#endif
-
-       /* Shut down the read threads: */
-       for (index = 0; index < n_read_threads; ++index)
-               __sync_fetch_and_add(&read_thread_data[index].stop, 1);
-       for (index = 0; index < n_read_threads; ++index) {
-               if (pthread_join(read_threads[index], NULL) != 0)
-                       goto error;
-               if (read_thread_data[index].status)
-                       goto error;
-       }
-
-       /* Shut down the write thread: */
-       __sync_fetch_and_add(&write_thread_data.stop, 1);
-       if ((pthread_join(write_thread, NULL) != 0) || write_thread_data.status)
-               goto error;
-
-       /* Check for final error conditions: */
-       for (index = 0; index < n_epoll_items; ++index) {
-               if (epoll_items[index].status != 0)
-                       goto error;
-               if (pthread_mutex_destroy(&epoll_items[index].mutex) < 0)
-                       goto error;
-       }
-       for (index = 0; index < n_epoll_items; ++index)
-               if (epoll_items[index].deleted != 1) {
-                       printf("Error: item data deleted %1d times.\n",
-                                  epoll_items[index].deleted);
-                       goto error;
-               }
-
-       printf("[PASS]\n");
-       return 0;
-
- error:
-       printf("[FAIL]\n");
-       return errno;
-}
index cd1b03e80899960147c9fc18777a1f5a35f9e08f..b76edf2f833349c8762c95ec4fc20d36f44c73f0 100644 (file)
@@ -35,7 +35,7 @@
 #include <sys/mount.h>
 #include <sys/statfs.h>
 #include "../../include/uapi/linux/magic.h"
-#include "../../include/linux/kernel-page-flags.h"
+#include "../../include/uapi/linux/kernel-page-flags.h"
 
 
 #ifndef MAX_PATH
index af0f22fb1ef71e6dc94c620873bc3241c2883430..aca6edcbbc6fa09113389e87b3e76a55a871da98 100644 (file)
@@ -303,7 +303,7 @@ static int cpio_mkfile(const char *name, const char *location,
        int retval;
        int rc = -1;
        int namesize;
-       int i;
+       unsigned int i;
 
        mode |= S_IFREG;
 
@@ -381,25 +381,28 @@ error:
 
 static char *cpio_replace_env(char *new_location)
 {
-       char expanded[PATH_MAX + 1];
-       char env_var[PATH_MAX + 1];
-       char *start;
-       char *end;
-
-       for (start = NULL; (start = strstr(new_location, "${")); ) {
-               end = strchr(start, '}');
-               if (start < end) {
-                       *env_var = *expanded = '\0';
-                       strncat(env_var, start + 2, end - start - 2);
-                       strncat(expanded, new_location, start - new_location);
-                       strncat(expanded, getenv(env_var), PATH_MAX);
-                       strncat(expanded, end + 1, PATH_MAX);
-                       strncpy(new_location, expanded, PATH_MAX);
-               } else
-                       break;
-       }
-
-       return new_location;
+       char expanded[PATH_MAX + 1];
+       char env_var[PATH_MAX + 1];
+       char *start;
+       char *end;
+
+       for (start = NULL; (start = strstr(new_location, "${")); ) {
+               end = strchr(start, '}');
+               if (start < end) {
+                       *env_var = *expanded = '\0';
+                       strncat(env_var, start + 2, end - start - 2);
+                       strncat(expanded, new_location, start - new_location);
+                       strncat(expanded, getenv(env_var),
+                               PATH_MAX - strlen(expanded));
+                       strncat(expanded, end + 1,
+                               PATH_MAX - strlen(expanded));
+                       strncpy(new_location, expanded, PATH_MAX);
+                       new_location[PATH_MAX] = 0;
+               } else
+                       break;
+       }
+
+       return new_location;
 }
 
 
index e59bb63cb089634c7d9bed701be0581bf536726a..be70035fd42a14edad4c24ae411c4b9d3fdf396c 100644 (file)
@@ -1322,9 +1322,7 @@ EXPORT_SYMBOL_GPL(kvm_release_page_clean);
 
 void kvm_release_pfn_clean(pfn_t pfn)
 {
-       WARN_ON(is_error_pfn(pfn));
-
-       if (!kvm_is_mmio_pfn(pfn))
+       if (!is_error_pfn(pfn) && !kvm_is_mmio_pfn(pfn))
                put_page(pfn_to_page(pfn));
 }
 EXPORT_SYMBOL_GPL(kvm_release_pfn_clean);